Santhosh has uploaded a new change for review.
https://gerrit.wikimedia.org/r/236529
Change subject: Stats: Separate total and language graph, and show draft count
in graph
......................................................................
Stats: Separate total and language graph, and show draft count in graph
This is in preparation for showing deletion stats and weekly trend
graphs.
Showing both total and language specific stats is difficult to
understand because the difference is widening fast. So separated them.
ApiQueryContentTranslationLanguageTrend now return cumulative count
for translations in progress as well. Soon it should retun
cumulative deleted stats too.
Bug: T105192
Bug: T90538
Change-Id: Ifd4bd0e3a92ac022428edf3915552ea99142dbfb
---
M api/ApiQueryContentTranslationLanguageTrend.php
M includes/Translation.php
M modules/stats/ext.cx.stats.js
M modules/stats/styles/ext.cx.stats.less
4 files changed, 196 insertions(+), 47 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation
refs/changes/29/236529/1
diff --git a/api/ApiQueryContentTranslationLanguageTrend.php
b/api/ApiQueryContentTranslationLanguageTrend.php
index cd5bf33..e8b9e43 100644
--- a/api/ApiQueryContentTranslationLanguageTrend.php
+++ b/api/ApiQueryContentTranslationLanguageTrend.php
@@ -32,7 +32,10 @@
$result->addValue(
array( 'query' ),
'contenttranslationlangtrend',
- ContentTranslation\Translation::getTrend( $source,
$target, $interval )
+ array(
+ 'translations' =>
ContentTranslation\Translation::getPublishTrend( $source, $target, $interval ),
+ 'drafts' =>
ContentTranslation\Translation::getDraftTrend( $source, $target, $interval )
+ )
);
}
diff --git a/includes/Translation.php b/includes/Translation.php
index c0a7c98..59c4a2d 100644
--- a/includes/Translation.php
+++ b/includes/Translation.php
@@ -211,10 +211,90 @@
}
/**
+ * Get time-wise cumulative number of drafts for given
+ * language pairs, with given interval.
+ */
+ public static function getDraftTrend( $source, $target, $interval ) {
+ $dbr = Database::getConnection( DB_SLAVE );
+
+ $draftCondition = $dbr->makeList(
+ array(
+ 'translation_status' => 'draft',
+ 'translation_target_url IS NULL'
+ ),
+ LIST_AND
+ );
+
+ $groupBy = null;
+
+ if ( $interval === 'week' ) {
+ $groupBy = array(
+ 'GROUP BY' => array(
+
'YEARWEEK(translation_last_updated_timestamp)',
+ ),
+ );
+ } elseif ( $interval === 'month' ) {
+ $groupBy = array(
+ 'GROUP BY' => array(
+
'YEAR(translation_last_updated_timestamp),
MONTH(translation_last_updated_timestamp)',
+ ),
+ );
+ }
+
+ $conditions = array( $draftCondition );
+
+ if ( $source !== null ) {
+ $conditions['translation_source_language'] = $source;
+ }
+
+ if ( $target !== null ) {
+ $conditions['translation_target_language'] = $target;
+ }
+
+ $rows = $dbr->select(
+ array( 'translations' => 'cx_translations' ),
+ array(
+ "DATE_FORMAT(
translations.translation_last_updated_timestamp, '%Y-%m-%d' ) AS date",
+ '(' . $dbr->selectSQLText(
+ 'cx_translations',
+ 'count(*)',
+ $dbr->makeList( array(
+
'translation_last_updated_timestamp <=
MAX(translations.translation_last_updated_timestamp)',
+ $dbr->makeList( $conditions,
LIST_AND ),
+ ),
+ LIST_AND )
+ ) . ') translatons_count',
+ ),
+ $dbr->makeList( $conditions, LIST_AND ),
+ __METHOD__,
+ $groupBy
+ );
+
+ $prev = 0;
+ $result = array();
+ foreach ( $rows as $row ) {
+ $count = (int)$row->translatons_count;
+ $result[] = array(
+ 'date' => $interval === 'week' ?
+ // Week end date
+ date( 'Y-m-d', strtotime( $row->date .
' + ' .
+ ( 6 - date( 'w', strtotime(
$row->date ) ) ) . ' days' ) ) :
+ date( 'Y-m', strtotime( $row->date ) ),
+ 'count' => $count,
+ 'delta' => $count - $prev,
+ );
+
+ $prev = $count;
+ }
+
+ return $result;
+ }
+
+ /**
* Get time-wise cumulative number of translations for given
* language pairs, with given interval.
*/
- public static function getTrend( $source, $target, $interval ) {
+ public static function getPublishTrend( $source, $target, $interval ) {
$dbr = Database::getConnection( DB_SLAVE );
$publishedCondition = $dbr->makeList(
diff --git a/modules/stats/ext.cx.stats.js b/modules/stats/ext.cx.stats.js
index 15bd6fc..769cba3 100644
--- a/modules/stats/ext.cx.stats.js
+++ b/modules/stats/ext.cx.stats.js
@@ -32,8 +32,14 @@
$( '<div>' ).addClass( 'bounce3' )
);
this.$highlights = $( '<div>' ).addClass( 'cx-stats-highlights'
);
- this.$graph = $( '<canvas>' ).attr( {
- id: 'cxtrend',
+ this.$cumlativeGraph = $( '<canvas>' ).attr( {
+ id: 'cxcumulative',
+ width: this.$container.width() - 200, // Leave a 200px
margin buffer to avoid overflow
+ height: 400
+ } );
+
+ this.$languageCumulativeGraph = $( '<canvas>' ).attr( {
+ id: 'cxlangcumulative',
width: this.$container.width() - 200, // Leave a 200px
margin buffer to avoid overflow
height: 400
} );
@@ -42,18 +48,28 @@
$spinner,
this.$highlights,
$( '<h2>' ).text( mw.msg(
'cx-stats-published-translations-title' ) ),
- $( '<div>' ).addClass( 'cx-stats-trend' ).append(
this.$graph )
+ $( '<div>' ).addClass( 'cx-stats-cumulative__total'
).append( this.$cumlativeGraph ),
+ $( '<h2>' ).text( mw.message(
+ 'cx-trend-translations-to',
+ $.uls.data.getAutonym( mw.config.get(
'wgContentLanguage' ) )
+ ).escaped() ),
+ $( '<div>' ).addClass( 'cx-stats-cumulative__lang'
).append( this.$languageCumulativeGraph )
);
$.when(
this.getCXTrends(),
this.getCXTrends( mw.config.get( 'wgContentLanguage' ) )
).done( function ( totalTrend, languageTrend ) {
- self.totalTranslationTrend = totalTrend;
- self.languageTranslationTrend = languageTrend;
- self.languageTranslationTrend = mergeAndFill(
totalTrend, languageTrend );
+ self.totalTranslationTrend = totalTrend.translations;
+ self.languageTranslationTrend =
languageTrend.translations;
+ self.languageTranslationTrend = mergeAndFill(
self.totalTranslationTrend, self.languageTranslationTrend );
+
+ self.totalDraftTrend = mergeAndFill(
self.totalTranslationTrend, totalTrend.drafts );
+ self.languageDraftTrend = mergeAndFill(
self.languageTranslationTrend, languageTrend.drafts );
+ self.languageDraftTrend = mergeAndFill(
self.totalDraftTrend, self.languageDraftTrend );
self.renderHighlights();
- self.drawGraph( 'count' );
+ self.drawCumulativeGraph( 'count' );
+ self.drawLanguageCumulativeGraph( 'count' );
} );
this.getCXStats().then( function ( data ) {
if ( !data || !data.query ) {
@@ -127,8 +143,7 @@
'cx-stats-local-published-number',
fmt( langTotal ),
fmt( localLanguage )
- )
- )
+ ) )
);
weekLangTrendText = mw.msg( 'percent', fmt( weekLangTrend ) );
@@ -368,7 +383,9 @@
$total = $( '<a>' )
.addClass( 'cx-stats-chart__total' )
.prop( 'href',
mw.cx.siteMapper.getPageUrl(
- model[ i ].language,
'Special:NewPages', { tagfilter: 'contenttranslation' }
+ model[ i ].language,
'Special:NewPages', {
+ tagfilter:
'contenttranslation'
+ }
) )
.text( fmt( model[ i ][ property ] ) );
} else {
@@ -424,10 +441,10 @@
} );
};
- CXStats.prototype.drawGraph = function ( type ) {
- var data, cxTrendGraph, ctx;
+ CXStats.prototype.drawCumulativeGraph = function ( type ) {
+ var data, cxCumulativeGraph, ctx;
- ctx = this.$graph[ 0 ].getContext( '2d' );
+ ctx = this.$cumlativeGraph[ 0 ].getContext( '2d' );
data = {
labels: $.map( this.totalTranslationTrend, function (
data ) {
@@ -435,34 +452,88 @@
} ),
datasets: [
{
- label: mw.message(
'cx-trend-all-translations' ).escaped(),
- strokeColor: '#FD6E8A',
- pointColor: '#FD6E8A',
+ label: mw.msg(
'cx-trend-all-translations' ),
+ fillColor: 'rgba(70, 130, 180, 0.2)',
+ strokeColor: 'rgba(70, 130, 180, 1)',
+ pointColor: 'rgba(70, 130, 180, 1)',
+ pointStrokeColor: '#fff',
+ pointHighlightFill: '#fff',
+ pointHighlightStroke: 'rgba(70, 130,
180, 1)',
data: $.map(
this.totalTranslationTrend, function ( data ) {
- return data[type];
+ return data[ type ];
} )
},
{
- label: mw.message(
- 'cx-trend-translations-to',
- $.uls.data.getAutonym(
mw.config.get( 'wgContentLanguage' ) )
- ).escaped(),
- strokeColor: '#80B3FF',
- pointColor: '#80B3FF',
- data: $.map(
this.languageTranslationTrend, function ( data ) {
- return data[type];
+ label: mw.msg(
'cx-stats-draft-translations-title' ),
+ fillColor: 'rgba(220,220,220,0.2)',
+ strokeColor: 'rgba(220,220,220,1)',
+ pointColor: 'rgba(220,220,220,1)',
+ pointStrokeColor: '#fff',
+ pointHighlightFill: '#fff',
+ pointHighlightStroke:
'rgba(220,220,220,1)',
+ data: $.map( this.totalDraftTrend,
function ( data ) {
+ return data[ type ];
} )
}
]
};
/*global Chart:false */
- cxTrendGraph = new Chart( ctx ).Line( data, {
+ cxCumulativeGraph = new Chart( ctx ).Line( data, {
+ responsive: true,
datasetFill: false,
legendTemplate: '<ul><% for (var i=0;
i<datasets.length; i++){%><li
style=\"color:<%=datasets[i].strokeColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'
} );
- this.$container.find( '.cx-stats-trend' ).append(
cxTrendGraph.generateLegend() );
+ this.$container.find( '.cx-stats-cumulative__total' ).append(
cxCumulativeGraph.generateLegend() );
+ };
+
+ CXStats.prototype.drawLanguageCumulativeGraph = function ( type ) {
+ var data, cxCumulativeGraph, ctx;
+
+ ctx = this.$languageCumulativeGraph[ 0 ].getContext( '2d' );
+
+ data = {
+ labels: $.map( this.totalTranslationTrend, function (
data ) {
+ return data.date;
+ } ),
+ datasets: [
+ {
+ label: mw.message(
+ 'cx-trend-translations-to',
+ $.uls.data.getAutonym(
mw.config.get( 'wgContentLanguage' ) )
+ ).escaped(),
+ strokeColor: 'rgba(70, 130, 180, 1)',
+ pointColor: 'rgba(70, 130, 180, 1)',
+ pointStrokeColor: '#fff',
+ pointHighlightFill: '#fff',
+ pointHighlightStroke: 'rgba(70, 130,
180, 1)',
+ data: $.map(
this.languageTranslationTrend, function ( data ) {
+ return data[ type ];
+ } )
+ },
+ {
+ label: mw.msg(
'cx-stats-draft-translations-title' ),
+ strokeColor: 'rgba(220, 220, 220, 1)',
+ pointColor: 'rgba(220, 220, 220, 1 )',
+ pointStrokeColor: '#fff',
+ pointHighlightFill: '#fff',
+ pointHighlightStroke:
'rgba(220,220,220,1)',
+ data: $.map( this.languageDraftTrend,
function ( data ) {
+ return data[ type ];
+ } )
+ }
+ ]
+ };
+
+ /*global Chart:false */
+ cxCumulativeGraph = new Chart( ctx ).Line( data, {
+ datasetFill: false,
+ responsive: true,
+ legendTemplate: '<ul><% for (var i=0;
i<datasets.length; i++){%><li
style=\"color:<%=datasets[i].strokeColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'
+ } );
+
+ this.$container.find( '.cx-stats-cumulative__lang' ).append(
cxCumulativeGraph.generateLegend() );
};
CXStats.prototype.transformJsonToModel = function ( records ) {
@@ -557,8 +628,7 @@
* @return {[Object]} Array of translations to a particular language,
after padding
*/
function mergeAndFill( totalData, languageData ) {
- var i,
- padding = [];
+ var i;
if ( totalData.length === languageData.length ) {
return languageData;
@@ -570,23 +640,18 @@
if ( !languageData || languageData.length === 0 ) {
break;
}
-
- if ( totalData[ i ].date === languageData[ 0 ].date ) {
- languageData = padding.concat( languageData );
- } else {
- padding.push( {
- date: totalData[ i ].date,
- count: 0
+ if ( languageData[ i ] && new Date( totalData[ i ].date
) > new Date( languageData[ i ].date ) ) {
+ totalData.splice( i, 0, {
+ date: languageData[ i ].date,
+ count: totalData[ i - 1 ] ? totalData[
i - 1 ].count : 0
} );
}
- }
-
- // Fill at the end if languageData is shorter than totalData
- for ( i = languageData.length; i < totalData.length; i++ ) {
- languageData.push( {
- date: totalData[ i ].date,
- count: languageData.length ? languageData[ i -
1 ].count : 0
- } );
+ if ( !languageData[ i ] || new Date( totalData[ i
].date ) < new Date( languageData[ i ].date ) ) {
+ languageData.splice( i, 0, {
+ date: totalData[ i ].date,
+ count: languageData[ i - 1 ] ?
languageData[ i - 1 ].count : 0
+ } );
+ }
}
return languageData;
diff --git a/modules/stats/styles/ext.cx.stats.less
b/modules/stats/styles/ext.cx.stats.less
index c5ef8b9..126b0fc 100644
--- a/modules/stats/styles/ext.cx.stats.less
+++ b/modules/stats/styles/ext.cx.stats.less
@@ -150,7 +150,8 @@
text-align: left;
}
-.cx-stats-trend {
+.cx-stats-cumulative__lang,
+.cx-stats-cumulative__total {
background-color: #fff;
}
--
To view, visit https://gerrit.wikimedia.org/r/236529
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifd4bd0e3a92ac022428edf3915552ea99142dbfb
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Santhosh <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits