2010-07-25 23:13:27 -04:00
NEWSBLUR . ReaderStatistics = function ( feed _id , options ) {
var defaults = { } ;
this . options = $ . extend ( { } , defaults , options ) ;
2012-05-17 18:40:46 -07:00
this . model = NEWSBLUR . assets ;
2010-07-25 23:13:27 -04:00
this . feed _id = feed _id ;
this . feed = this . model . get _feed ( feed _id ) ;
2010-07-30 17:12:20 -04:00
this . feeds = this . model . get _feeds ( ) ;
2010-07-30 23:50:49 -04:00
this . first _load = true ;
2010-07-25 23:13:27 -04:00
this . runner ( ) ;
} ;
2011-11-12 18:19:57 -08:00
NEWSBLUR . ReaderStatistics . prototype = new NEWSBLUR . Modal ;
NEWSBLUR . ReaderStatistics . prototype . constructor = NEWSBLUR . ReaderStatistics ;
_ . extend ( NEWSBLUR . ReaderStatistics . prototype , {
2010-07-25 23:13:27 -04:00
runner : function ( ) {
2010-08-03 09:19:38 -04:00
var self = this ;
2012-02-16 18:36:52 -08:00
this . initialize _feed ( this . feed _id ) ;
2010-07-25 23:13:27 -04:00
this . make _modal ( ) ;
this . open _modal ( ) ;
2010-08-03 09:19:38 -04:00
setTimeout ( function ( ) {
self . get _stats ( ) ;
} , 50 ) ;
2010-07-30 17:12:20 -04:00
2012-01-13 17:54:17 -08:00
this . $modal . bind ( 'click' , $ . rescope ( this . handle _click , this ) ) ;
2010-07-30 17:12:20 -04:00
this . $modal . bind ( 'change' , $ . rescope ( this . handle _change , this ) ) ;
2010-07-25 23:13:27 -04:00
} ,
make _modal : function ( ) {
var self = this ;
this . $modal = $ . make ( 'div' , { className : 'NB-modal-statistics NB-modal' } , [
2010-08-03 09:19:38 -04:00
$ . make ( 'div' , { className : 'NB-modal-feed-chooser-container' } , [
2013-12-19 12:29:07 -08:00
this . make _feed _chooser ( { skip _starred : true } )
2010-08-03 09:19:38 -04:00
] ) ,
2010-07-30 17:12:20 -04:00
$ . make ( 'div' , { className : 'NB-modal-loading' } ) ,
2010-07-25 23:13:27 -04:00
$ . make ( 'h2' , { className : 'NB-modal-title' } , 'Statistics & History' ) ,
$ . make ( 'h2' , { className : 'NB-modal-subtitle' } , [
2012-01-26 18:59:40 -08:00
$ . make ( 'img' , { className : 'NB-modal-feed-image feed_favicon' , src : $ . favicon ( this . feed ) } ) ,
2011-07-27 22:17:34 -07:00
$ . make ( 'div' , { className : 'NB-modal-feed-heading' } , [
2012-05-21 20:08:27 -07:00
$ . make ( 'span' , { className : 'NB-modal-feed-title' } , this . feed . get ( 'feed_title' ) ) ,
2013-06-14 10:54:11 -07:00
$ . make ( 'span' , { className : 'NB-modal-feed-subscribers ' + ( _ . isUndefined ( this . feed . get ( 'num_subscribers' ) ) && 'NB-hidden' ) } , Inflector . pluralize ( ' subscriber' , this . feed . get ( 'num_subscribers' ) , true ) )
2011-07-27 22:17:34 -07:00
] )
2010-07-26 22:21:58 -04:00
] ) ,
2010-08-03 09:19:38 -04:00
$ . make ( 'div' , { className : 'NB-modal-statistics-info' } )
2010-07-25 23:13:27 -04:00
] ) ;
2010-10-10 20:14:31 -04:00
var $stats = this . make _stats ( {
'last_update' : '' ,
2012-07-07 10:04:13 -07:00
'next_update' : '' ,
'loading' : true
2010-10-10 20:14:31 -04:00
} ) ;
$ ( '.NB-modal-statistics-info' , this . $modal ) . replaceWith ( $stats ) ;
2010-07-25 23:13:27 -04:00
} ,
get _stats : function ( ) {
2010-07-30 17:12:20 -04:00
var $loading = $ ( '.NB-modal-loading' , this . $modal ) ;
$loading . addClass ( 'NB-active' ) ;
2012-02-16 18:36:52 -08:00
var statistics _fn = this . options . social _feed ? this . model . get _social _statistics : this . model . get _feed _statistics ;
statistics _fn . call ( this . model , this . feed _id , $ . rescope ( this . populate _stats , this ) ) ;
2010-07-25 23:13:27 -04:00
} ,
populate _stats : function ( s , data ) {
2010-07-30 23:50:49 -04:00
var self = this ;
2010-07-25 23:13:27 -04:00
NEWSBLUR . log ( [ 'Stats' , data ] ) ;
2010-07-30 23:50:49 -04:00
2010-07-30 17:12:20 -04:00
var $loading = $ ( '.NB-modal-loading' , this . $modal ) ;
$loading . removeClass ( 'NB-active' ) ;
2012-01-13 17:54:17 -08:00
var $stats = this . make _stats ( data ) ;
2010-07-30 23:50:49 -04:00
$ ( '.NB-modal-statistics-info' , this . $modal ) . replaceWith ( $stats ) ;
2013-06-29 11:26:42 -07:00
$ ( ".NB-modal-feed-subscribers" , this . $modal ) . removeClass ( 'NB-hidden' ) . text ( Inflector . pluralize ( ' subscriber' , data . num _subscribers , true ) ) ;
2013-06-29 11:42:39 -07:00
var $expires _label = $ ( ".NB-statistics-push-expires-label" , this . $modal ) ;
2013-06-29 11:29:23 -07:00
var $expires = $ ( ".NB-statistics-push-expires" , this . $modal ) ;
2013-06-29 11:31:20 -07:00
if ( data [ 'push_expires' ] ) {
2013-06-29 11:37:21 -07:00
$expires _label . html ( "Push expires" ) ;
$expires . html ( data [ 'push_expires' ] ) ;
2013-06-29 11:29:23 -07:00
} else {
2013-06-29 11:37:21 -07:00
$expires _label . html ( "" ) ;
2013-06-29 11:29:23 -07:00
$expires . html ( "" ) ;
}
2010-07-30 23:50:49 -04:00
setTimeout ( function ( ) {
self . make _charts ( data ) ;
2013-03-19 11:11:17 -07:00
} , this . first _load ? 200 : 50 ) ;
2010-07-30 23:50:49 -04:00
setTimeout ( function ( ) {
2010-08-01 23:47:40 -04:00
$ . modal . impl . resize ( self . $modal ) ;
2010-08-13 18:18:46 -04:00
} , 100 ) ;
2010-07-30 23:50:49 -04:00
} ,
2012-01-13 18:00:33 -08:00
make _stats : function ( data ) {
2013-02-11 16:07:08 -08:00
var update _interval = NEWSBLUR . utils . calculate _update _interval ( data [ 'update_interval_minutes' ] ) ;
var premium _update _interval = NEWSBLUR . utils . calculate _update _interval ( data [ 'premium_update_interval_minutes' ] ) ;
2012-01-13 17:54:17 -08:00
2010-07-26 22:21:58 -04:00
var $stats = $ . make ( 'div' , { className : 'NB-modal-statistics-info' } , [
2012-02-16 18:36:52 -08:00
( ! this . options . social _feed && $ . make ( 'div' , { className : 'NB-statistics-stat NB-statistics-updates' } , [
2010-07-28 01:14:25 -04:00
$ . make ( 'div' , { className : 'NB-statistics-update' } , [
2010-07-30 17:12:20 -04:00
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Last Update' ) ,
2010-10-10 20:14:31 -04:00
$ . make ( 'div' , { className : 'NB-statistics-count' } , ' ' + ( data [ 'last_update' ] && ( data [ 'last_update' ] + ' ago' ) ) )
2010-07-28 01:14:25 -04:00
] ) ,
$ . make ( 'div' , { className : 'NB-statistics-update' } , [
2013-03-30 20:33:00 -07:00
( data [ 'push' ] && $ . make ( 'div' , { className : 'NB-statistics-realtime' } , [
$ . make ( 'div' , { className : 'NB-statistics-label' } , [
$ . make ( 'img' , { src : NEWSBLUR . Globals . MEDIA _URL + '/img/reader/realtime_spinner.gif' , className : 'NB-statisics-realtime-spinner' } ) ,
'Real-time'
] ) ,
$ . make ( 'div' , { className : 'NB-statistics-count' } , 'Supplemented by checks every ' + update _interval )
] ) ) ,
( ! data [ 'push' ] && $ . make ( 'div' , [
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Every' ) ,
$ . make ( 'div' , { className : 'NB-statistics-count' } , update _interval )
] ) )
2010-07-28 01:14:25 -04:00
] ) ,
$ . make ( 'div' , { className : 'NB-statistics-update' } , [
2010-07-30 17:12:20 -04:00
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Next Update' ) ,
2012-02-13 11:07:32 -08:00
( data . active && $ . make ( 'div' , { className : 'NB-statistics-count' } , ' ' + ( data [ 'next_update' ] && ( 'in ' + data [ 'next_update' ] ) ) ) ) ,
2012-07-07 10:04:13 -07:00
( ! data . active && ! data . loading && $ . make ( 'div' , { className : 'NB-statistics-count' } , "Not active" ) )
2012-01-13 17:54:17 -08:00
] ) ,
2013-03-28 12:17:30 -07:00
( ( data . average _stories _per _month == 0 || data . stories _last _month == 0 ) &&
2013-04-23 17:04:21 -07:00
data . update _interval _minutes > 60 &&
2013-03-28 12:17:30 -07:00
$ . make ( 'div' , { className : 'NB-statistics-update-explainer' } , [
$ . make ( 'b' , 'Why so infrequently?' ) ,
'This site has published zero stories in the past month or has averaged less than a single story a month. As soon as it starts publishing at least once a month, it will automatically fetch more frequently.'
] ) ) ,
2013-04-17 14:36:13 -07:00
( data . errors _since _good &&
$ . make ( 'div' , { className : 'NB-statistics-update-explainer' } , [
$ . make ( 'b' , 'Why is the next update not at the normal rate?' ) ,
'This site has is throwing exceptions and is not in a healthy state. Look at the bottom of this dialog to see the exact status codes for the feed. The more errors for the feed, the longer time taken between fetches.'
] ) ) ,
2012-01-13 17:54:17 -08:00
( ! NEWSBLUR . Globals . is _premium && $ . make ( 'div' , { className : 'NB-statistics-premium-stats' } , [
$ . make ( 'div' , { className : 'NB-statistics-update' } , [
$ . make ( 'div' , { className : 'NB-statistics-label' } , [
'If you went ' ,
$ . make ( 'a' , { href : '#' , className : 'NB-premium-link NB-splash-link' } , 'premium' ) ,
', ' ,
$ . make ( 'br' ) ,
'this site would update every'
] ) ,
2013-03-30 20:33:00 -07:00
$ . make ( 'div' , { className : 'NB-statistics-count' } , premium _update _interval ) ,
( data [ 'push' ] && $ . make ( 'div' , { className : 'NB-statistics-realtime' } , [
$ . make ( 'div' , { className : 'NB-statistics-label' } , [
'but it wouldn\'t matter because' ,
$ . make ( 'br' ) ,
'this site is already in real-time'
] )
] ) )
2012-01-13 17:54:17 -08:00
] )
] ) )
2012-02-16 18:36:52 -08:00
] ) ) ,
2010-07-30 17:12:20 -04:00
$ . make ( 'div' , { className : 'NB-statistics-stat NB-statistics-history' } , [
$ . make ( 'div' , { className : 'NB-statistics-history-stat' } , [
2010-08-13 10:43:48 -04:00
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Stories per month' )
2010-07-30 23:50:49 -04:00
] ) ,
2013-03-19 11:11:17 -07:00
$ . make ( 'canvas' , { id : 'NB-statistics-history-chart' , className : 'NB-statistics-history-chart' } )
2011-02-13 14:47:58 -05:00
] ) ,
2011-04-09 11:06:36 -04:00
( data . classifier _counts && $ . make ( 'div' , { className : 'NB-statistics-state NB-statistics-classifiers' } , [
this . make _classifier _count ( 'tag' , data . classifier _counts [ 'tag' ] ) ,
this . make _classifier _count ( 'author' , data . classifier _counts [ 'author' ] ) ,
this . make _classifier _count ( 'title' , data . classifier _counts [ 'title' ] ) ,
this . make _classifier _count ( 'feed' , data . classifier _counts [ 'feed' ] )
] ) ) ,
2012-02-17 17:41:20 -08:00
( ! this . options . social _feed && $ . make ( 'div' , { className : 'NB-statistics-stat NB-statistics-fetches' } , [
2011-02-13 14:47:58 -05:00
$ . make ( 'div' , { className : 'NB-statistics-fetches-half' } , [
2012-04-09 14:58:53 -07:00
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Feed Fetch' ) ,
$ . make ( 'div' , this . make _history ( data , 'feed_fetch' ) )
2011-02-13 14:47:58 -05:00
] ) ,
$ . make ( 'div' , { className : 'NB-statistics-fetches-half' } , [
2012-04-09 14:58:53 -07:00
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Page Fetch' ) ,
$ . make ( 'div' , this . make _history ( data , 'page_fetch' ) )
] ) ,
2012-04-09 15:09:29 -07:00
$ . make ( 'div' , { className : 'NB-statistics-fetches-half' } , [
2012-04-09 14:58:53 -07:00
$ . make ( 'div' , { className : 'NB-statistics-label' } , 'Feed Push' ) ,
2013-06-29 11:26:42 -07:00
$ . make ( 'div' , this . make _history ( data , 'feed_push' ) ) ,
2013-06-29 11:37:21 -07:00
$ . make ( 'div' , { className : 'NB-statistics-label NB-statistics-push-expires-label' } , 'Push Expires' ) ,
2013-06-29 11:26:42 -07:00
$ . make ( 'div' , { className : 'NB-statistics-label NB-statistics-push-expires' } )
2011-02-13 14:47:58 -05:00
] )
2012-02-17 17:41:20 -08:00
] ) )
2010-07-26 22:21:58 -04:00
] ) ;
2010-07-30 23:50:49 -04:00
return $stats ;
} ,
2011-04-09 11:06:36 -04:00
make _classifier _count : function ( facet , data ) {
2011-04-09 14:47:37 -04:00
var self = this ;
2011-04-09 11:06:36 -04:00
if ( ! data ) return ;
var $facets = $ . make ( 'div' , { className : 'NB-statistics-facets' } , [
2011-04-09 14:37:07 -04:00
$ . make ( 'div' , { className : 'NB-statistics-facet-title' } , Inflector . pluralize ( facet , data . length ) )
2011-04-09 11:06:36 -04:00
] ) ;
2011-04-09 14:37:07 -04:00
var max = 10 ;
_ . each ( data , function ( v ) {
if ( v . pos > max || v . neg > max ) {
max = Math . max ( v . pos , v . neg ) ;
}
} ) ;
var max _width = 100 ;
var multiplier = max _width / parseFloat ( max , 10 ) ;
var calculate _width = function ( count ) {
2011-04-09 14:49:24 -04:00
return Math . max ( 1 , multiplier * count ) ;
2011-04-09 14:37:07 -04:00
} ;
_ . each ( data , function ( counts ) {
2011-04-09 11:06:36 -04:00
var pos = counts . pos || 0 ;
var neg = counts . neg || 0 ;
2011-04-09 14:37:07 -04:00
var key = counts [ facet ] ;
2013-08-15 16:35:23 -07:00
if ( facet == 'feed' && self . options . social _feed && counts [ 'feed_id' ] != 0 ) {
2013-08-15 16:32:44 -07:00
key = [ $ . make ( 'div' , [
$ . make ( 'img' , { className : 'NB-modal-feed-image feed_favicon' , src : $ . favicon ( counts [ 'feed_id' ] ) } ) ,
$ . make ( 'span' , { className : 'NB-modal-feed-title' } , counts [ 'feed_title' ] )
] ) ] ;
} else if ( facet == 'feed' ) {
2011-04-09 14:47:37 -04:00
key = [ $ . make ( 'div' , [
2012-01-26 18:59:40 -08:00
$ . make ( 'img' , { className : 'NB-modal-feed-image feed_favicon' , src : $ . favicon ( self . feed ) } ) ,
2012-05-21 20:08:27 -07:00
$ . make ( 'span' , { className : 'NB-modal-feed-title' } , self . feed . get ( 'feed_title' ) )
2011-04-09 14:47:37 -04:00
] ) ] ;
}
if ( ! key || ( ! pos && ! neg ) ) return ;
2011-04-09 11:06:36 -04:00
var $facet = $ . make ( 'div' , { className : 'NB-statistics-facet' } , [
2011-04-09 13:38:14 -04:00
( pos && $ . make ( 'div' , { className : 'NB-statistics-facet-pos' } , [
2011-04-09 14:37:07 -04:00
$ . make ( 'div' , { className : 'NB-statistics-facet-bar' } ) . css ( 'width' , calculate _width ( pos ) ) ,
2012-05-21 20:08:27 -07:00
$ . make ( 'div' , { className : 'NB-statistics-facet-count' } , Inflector . pluralize ( ' like' , pos , true ) ) . css ( 'margin-left' , calculate _width ( pos ) + 5 )
2011-04-09 13:38:14 -04:00
] ) ) ,
( neg && $ . make ( 'div' , { className : 'NB-statistics-facet-neg' } , [
2011-04-09 14:37:07 -04:00
$ . make ( 'div' , { className : 'NB-statistics-facet-bar' } ) . css ( 'width' , calculate _width ( neg ) ) ,
2012-05-21 20:08:27 -07:00
$ . make ( 'div' , { className : 'NB-statistics-facet-count' } , Inflector . pluralize ( ' dislike' , neg , true ) ) . css ( 'margin-right' , calculate _width ( neg ) + 5 )
2011-04-09 13:38:14 -04:00
] ) ) ,
$ . make ( 'div' , { className : 'NB-statistics-facet-separator' } ) ,
2011-04-09 11:06:36 -04:00
$ . make ( 'div' , { className : 'NB-statistics-facet-name' } , key )
] ) ;
$facets . append ( $facet ) ;
} ) ;
return $facets ;
} ,
2011-02-13 14:47:58 -05:00
make _history : function ( data , fetch _type ) {
2012-04-09 14:58:53 -07:00
var fetches = data [ fetch _type + '_history' ] ;
2012-04-09 15:09:29 -07:00
var $history ;
if ( ! fetches || ! fetches . length ) {
2012-12-28 21:42:52 -08:00
$history = $ . make ( 'div' , { className : 'NB-history-empty' } , "Nothing recorded." ) ;
2012-04-09 15:09:29 -07:00
} else {
$history = _ . map ( fetches , function ( fetch ) {
var feed _ok = _ . contains ( [ 200 , 304 ] , fetch . status _code ) || ! fetch . status _code ;
var status _class = feed _ok ? ' NB-ok ' : ' NB-errorcode ' ;
2012-12-28 21:42:52 -08:00
return $ . make ( 'div' , { className : 'NB-history-fetch' + status _class , title : feed _ok ? '' : fetch . exception } , [
$ . make ( 'div' , { className : 'NB-history-fetch-date' } , fetch . fetch _date || fetch . push _date ) ,
$ . make ( 'div' , { className : 'NB-history-fetch-message' } , [
2012-04-09 15:09:29 -07:00
fetch . message ,
2012-12-28 21:42:52 -08:00
( fetch . status _code && $ . make ( 'div' , { className : 'NB-history-fetch-code' } , ' (' + fetch . status _code + ')' ) )
2012-04-09 15:09:29 -07:00
] )
] ) ;
} ) ;
}
2011-02-13 14:47:58 -05:00
return $history ;
} ,
2010-07-30 23:50:49 -04:00
make _charts : function ( data ) {
2013-03-19 11:11:17 -07:00
var labels = _ . map ( data [ 'story_count_history' ] , function ( date ) {
2010-08-13 10:43:48 -04:00
var date _matched = date [ 0 ] . match ( /(\d{4})-(\d{1,2})/ ) ;
2013-03-19 11:11:17 -07:00
var date = ( new Date ( parseInt ( date _matched [ 1 ] , 10 ) , parseInt ( date _matched [ 2 ] , 10 ) - 1 ) ) ;
return NEWSBLUR . utils . shortMonthNames [ date . getMonth ( ) ] + " " + date . getUTCFullYear ( ) ;
2010-07-30 23:50:49 -04:00
} ) ;
2013-03-19 11:28:57 -07:00
if ( labels . length > 16 ) {
var cut _size = Math . round ( labels . length / 16.0 ) ;
labels = _ . map ( labels , function ( label , c ) {
if ( ( c % cut _size ) == 0 ) return label ;
return "" ;
} ) ;
}
2013-03-19 11:11:17 -07:00
var values = _ . map ( data [ 'story_count_history' ] , function ( date ) {
return date [ 1 ] ;
} ) ;
var points = {
labels : labels ,
datasets : [
{
fillColor : "rgba(151,187,205,0.5)" ,
strokeColor : "rgba(151,187,205,1)" ,
pointColor : "rgba(151,187,205,1)" ,
pointStrokeColor : "#fff" ,
data : values
}
]
} ;
2010-08-13 10:43:48 -04:00
var $plot = $ ( ".NB-statistics-history-chart" ) ;
2013-03-19 11:11:17 -07:00
var width = $plot . width ( ) ;
var height = $plot . height ( ) ;
$plot . attr ( 'width' , width ) ;
$plot . attr ( 'height' , height ) ;
var myLine = new Chart ( $plot . get ( 0 ) . getContext ( "2d" ) ) . Line ( points , {
scaleLabel : "<%= Math.round(value) %>"
} ) ;
2010-07-30 17:12:20 -04:00
} ,
2012-01-13 17:54:17 -08:00
close _and _load _premium : function ( ) {
this . close ( function ( ) {
NEWSBLUR . reader . open _feedchooser _modal ( ) ;
} ) ;
} ,
// ===========
// = Actions =
// ===========
2010-07-30 17:12:20 -04:00
handle _change : function ( elem , e ) {
var self = this ;
$ . targetIs ( e , { tagSelector : '.NB-modal-feed-chooser' } , function ( $t , $p ) {
var feed _id = $t . val ( ) ;
2010-07-30 23:50:49 -04:00
self . first _load = false ;
2010-07-30 17:12:20 -04:00
self . initialize _feed ( feed _id ) ;
self . get _stats ( ) ;
} ) ;
2012-01-13 17:54:17 -08:00
} ,
handle _click : function ( elem , e ) {
var self = this ;
$ . targetIs ( e , { tagSelector : '.NB-premium-link' } , function ( $t , $p ) {
e . preventDefault ( ) ;
self . close _and _load _premium ( ) ;
} ) ;
2010-07-25 23:13:27 -04:00
}
2011-11-12 18:19:57 -08:00
} ) ;