Intelligence Trainer. A whopper of a commit.

This commit is contained in:
Samuel Clay 2010-08-01 19:12:42 -04:00
parent 543384ed84
commit 66eae41e2d
17 changed files with 574 additions and 153 deletions

View file

@ -21,10 +21,12 @@ def save_classifier(request):
# Make subscription as dirty, so unread counts can be recalculated
usersub = UserSubscription.objects.get(user=request.user, feed=feed)
if not usersub.needs_unread_recalc:
if not usersub.needs_unread_recalc or not usersub.is_trained:
usersub.needs_unread_recalc = True
usersub.is_trained = True
usersub.save()
def _save_classifier(ClassifierCls, content_type, ContentCls=None, post_content_field=None):
classifiers = {
'like_'+content_type: 1,
@ -87,4 +89,5 @@ def get_classifiers_feed(request):
response = dict(code=code, payload=payload)
return response
return response

View file

@ -0,0 +1,149 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'UserSubscription.is_trained'
db.add_column('reader_usersubscription', 'is_trained', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)
def backwards(self, orm):
# Deleting field 'UserSubscription.is_trained'
db.delete_column('reader_usersubscription', 'is_trained')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'reader.feature': {
'Meta': {'object_name': 'Feature'},
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'reader.userstory': {
'Meta': {'unique_together': "(('user', 'feed', 'story'),)", 'object_name': 'UserStory'},
'feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Feed']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'opinion': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'read_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'story': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Story']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'reader.usersubscription': {
'Meta': {'unique_together': "(('user', 'feed'),)", 'object_name': 'UserSubscription'},
'feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Feed']"}),
'feed_opens': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_trained': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'last_read_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 17, 13, 2, 23, 54046)'}),
'mark_read_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 17, 13, 2, 23, 54155)'}),
'needs_unread_recalc': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'unread_count_negative': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'unread_count_neutral': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'unread_count_positive': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'unread_count_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2000, 1, 1, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'reader.usersubscriptionfolders': {
'Meta': {'object_name': 'UserSubscriptionFolders'},
'folders': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'rss_feeds.feed': {
'Meta': {'object_name': 'Feed', 'db_table': "'feeds'"},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
'average_stories_per_month': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'creation': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'days_to_trim': ('django.db.models.fields.IntegerField', [], {'default': '90'}),
'etag': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'feed_address': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '255'}),
'feed_link': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '1000', 'null': 'True', 'blank': 'True'}),
'feed_tagline': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'null': 'True', 'blank': 'True'}),
'feed_title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_load_time': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'last_modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'last_update': ('django.db.models.fields.DateTimeField', [], {'default': '0', 'auto_now': 'True', 'blank': 'True'}),
'min_to_decay': ('django.db.models.fields.IntegerField', [], {'default': '15'}),
'next_scheduled_update': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'num_subscribers': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'popular_authors': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
'popular_tags': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
'stories_last_month': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'stories_last_year': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
},
'rss_feeds.story': {
'Meta': {'unique_together': "(('story_feed', 'story_guid_hash'),)", 'object_name': 'Story', 'db_table': "'stories'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'story_author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.StoryAuthor']"}),
'story_author_name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}),
'story_content': ('utils.compressed_textfield.StoryField', [], {'null': 'True', 'blank': 'True'}),
'story_content_type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'story_date': ('django.db.models.fields.DateTimeField', [], {}),
'story_feed': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stories'", 'to': "orm['rss_feeds.Feed']"}),
'story_guid': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'story_guid_hash': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'story_original_content': ('utils.compressed_textfield.StoryField', [], {'null': 'True', 'blank': 'True'}),
'story_past_trim_date': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'story_permalink': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'story_tags': ('django.db.models.fields.CharField', [], {'max_length': '2000', 'null': 'True', 'blank': 'True'}),
'story_title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rss_feeds.Tag']", 'symmetrical': 'False'})
},
'rss_feeds.storyauthor': {
'Meta': {'object_name': 'StoryAuthor'},
'author_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Feed']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'rss_feeds.tag': {
'Meta': {'object_name': 'Tag'},
'feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Feed']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
}
}
complete_apps = ['reader']

View file

@ -29,6 +29,7 @@ class UserSubscription(models.Model):
unread_count_updated = models.DateTimeField(default=datetime.datetime(2000,1,1))
needs_unread_recalc = models.BooleanField(default=False)
feed_opens = models.IntegerField(default=0)
is_trained = models.BooleanField(default=False)
def __unicode__(self):
return '[' + self.feed.feed_title + '] '

View file

@ -23,4 +23,5 @@ urlpatterns = patterns('',
url(r'^add_feature', views.add_feature, name='add-feature'),
url(r'^load_features', views.load_features, name='load-features'),
url(r'^save_feed_order', views.save_feed_order, name='save-feed-order'),
url(r'^get_feeds_trainer', views.get_feeds_trainer, name='get-feeds-trainer'),
)

View file

@ -534,6 +534,25 @@ def save_feed_order(request):
return {}
@json.json_view
def get_feeds_trainer(request):
classifiers = []
usersubs = UserSubscription.objects.filter(user=request.user).select_related('feed')\
.order_by('-feed__stories_last_month')
for us in usersubs:
if not us.is_trained and us.feed.stories_last_month > 0:
classifier = dict()
classifier['classifiers'] = get_classifiers_for_user(request.user, us.feed)
classifier['feed_id'] = us.feed.pk
classifier['stories_last_month'] = us.feed.stories_last_month
classifier['feed_tags'] = json.decode(us.feed.popular_tags) if us.feed.popular_tags else []
classifier['feed_authors'] = json.decode(us.feed.popular_authors) if us.feed.popular_authors else []
classifiers.append(classifier)
return classifiers
@login_required
def login_as(request):
if not request.user.is_staff:

View file

@ -35,7 +35,7 @@ class Migration(SchemaMigration):
db.alter_column('stories', 'story_tags', self.gf('django.db.models.fields.CharField')(max_length=2000, null=True, blank=True))
# Adding unique constraint on 'Story', fields ['story_feed', 'story_guid_hash']
db.create_unique('stories', ['story_feed_id', 'story_guid_hash'])
# db.create_unique('stories', ['story_feed_id', 'story_guid_hash'])
def backwards(self, orm):

View file

@ -1474,17 +1474,72 @@ a.NB-splash-link:hover {
text-shadow: 1px 1px 0px #e0e0e0;
}
.NB-disabled {
color: #A0A0A0;
.NB-modal .NB-modal-subtitle {
margin:10px 0 0;
padding:8px 12px;
font-size: 14px;
position: relative;
background-color: #F6F6F6;
}
.NB-modal .NB-modal-feed-title {
display: block;
margin: 0 40px 0 23px;
text-decoration: none;
color: #272727;
overflow: hidden;
text-shadow: 0 1px 0 #EBF3FA;
}
.NB-modal .NB-modal-feed-image {
float: left;
}
.NB-modal .NB-modal-submit input[type=submit],
.NB-modal .NB-modal-submit .NB-modal-submit-button {
border: 1px solid #606060;
font-size: 12px;
padding: 4px 8px;
text-transform: uppercase;
margin: 2px 4px 2px;
border: 1px solid #606060;
-moz-box-shadow:2px 2px 0 #D0D0D0;
-webkit-box-shadow:2px 2px 0 #D0D0D0;
box-shadow:2px 2px 0 #D0D0D0;
border-radius: 4px;
-moz-border-radius: 4px;
cursor: pointer;
text-decoration: none;
}
.NB-modal .NB-modal-submit .NB-modal-submit-back {
background-color: #d5d4dB;
color: #909090;
}
.NB-modal .NB-modal-submit .NB-modal-submit-close {
background-color: #d5d4dB;
color: #909090;
font-weight: bold;
}
.NB-modal .NB-modal-submit .NB-modal-submit-save {
background-color: #217412;
font-weight: bold;
color: #FCFCFC;
}
.NB-modal .NB-modal-submit .NB-disabled {
background-color: #d5d4dB;
color: #909090;
border: 1px solid #A0A0A0;
-moz-box-shadow:2px 2px 0 #E6E6E6;
-webkit-box-shadow:2px 2px 0 #E6E6E6;
box-shadow:2px 2px 0 #E6E6E6;
}
.NB-modal .NB-modal-submit {
margin: 16px 0 0 0;
font-size: 13px;
}
.NB-modal .NB-modal-submit input[type=submit] {
font-size: 14px;
overflow: hidden;
}
.NB-modal img.feed_favicon {
@ -1518,6 +1573,11 @@ a.NB-splash-link:hover {
/* = Classifier = */
/* ============== */
.NB-classifier {
border-radius: 14px;
-moz-border-radius: 14px;
}
.NB-classifier h2.NB-like {
color: #007000;
}
@ -1592,6 +1652,27 @@ a.NB-splash-link:hover {
.NB-classifiers {
}
.NB-classifier .NB-modal-submit .NB-modal-submit-back {
float: left;
color: #FFF;
background-color: #b5b4bB;
}
.NB-classifier .NB-modal-submit .NB-modal-submit-close {
float: right;
color: #FFF;
background-color: #b5b4bB;
}
.NB-classifier .NB-modal-submit .NB-modal-submit-save {
float: right;
padding-left: 12px !important;
padding-right: 12px !important;
}
.NB-classifier-trainer-counts {
float: right;
color: #606060;
font-size: 17px;
}
/* ======================= */
/* = Intelligence Slider = */
/* ======================= */
@ -1644,10 +1725,12 @@ a.NB-splash-link:hover {
.NB-add .NB-add-danger {
display: block;
clear: both;
font-size: 12px;
color: #535558;
font-weight: bold;
margin: 8px 0 0;
float: left;
}
.NB-add .NB-add-danger img {
@ -1714,6 +1797,12 @@ a.NB-splash-link:hover {
margin: 0 4px;
}
.NB-add .NB-opml-reader-oauth {
margin: 4px 0 6px 0;
text-decoration: none;
float: left;
display: block;
}
/* ================ */
/* = Manage Feeds = */
/* ================ */
@ -1847,20 +1936,23 @@ background: transparent;
display: block;
margin: 2px 6px 6px 0;
cursor: pointer;
padding: 2px 9px 2px 4px;
padding: 0 9px 0 4px;
font-size: 12px;
text-transform: uppercase;
}
.NB-classifiers .NB-classifier input[type=checkbox] {
margin: 0 6px 0 4px;
float: none;
margin: 3px 6px 2px 4px;
cursor: pointer;
float: left;
}
.NB-classifiers .NB-classifier label {
cursor: pointer;
color: black;
float: left;
display: block;
padding: 2px 0;
}
.NB-classifiers .NB-classifier label b {
@ -2243,7 +2335,7 @@ background: transparent;
.NB-menu-manage .NB-menu-manage-subtitle {
font-size: 12px;
color: #617C4B;
color: #718C7B;
}
.NB-menu-manage li:hover .NB-menu-manage-subtitle {
@ -2342,26 +2434,6 @@ background: transparent;
.NB-modal-statistics {
}
.NB-modal-statistics .NB-modal-subtitle {
border-bottom: 3px solid #E0E0E0;
font-size: 14px;
margin-bottom: 6px;
padding-bottom: 6px;
position: relative;
}
.NB-modal-statistics .NB-modal-statistics-feed-title {
display: block;
margin: 4px 40px 2px 23px;
text-decoration: none;
color: #272727;
overflow: hidden;
text-shadow: 0 1px 0 #EBF3FA;
}
.NB-modal-statistics .NB-modal-statistics-feed-image {
float: left;
}
.NB-modal-statistics .NB-statistics-stat {
background-color: #E0FFE0;
clear: both;

View file

@ -129,6 +129,14 @@ NEWSBLUR.log = function(msg) {
return true;
}
},
entity: function(str) {
var e = document.createElement('div');
e.innerHTML = String(str);
return e.innerHTML;
},
make: function(){
var $elem, text, children, type, name, props;

View file

@ -141,7 +141,7 @@
minWidth: null,
maxHeight: null,
maxWidth: null,
autoResize: false,
autoResize: true,
autoPosition: true,
zIndex: 1000,
close: true,
@ -446,6 +446,13 @@
return [h, el.width()];
},
resize: function(data) {
if (data) {
this.d.data = data;
}
w = this.getDimensions();
this.setContainerDimensions();
},
getVal: function (v) {
return v == 'auto' ? 0
: v.indexOf('%') > 0 ? v
@ -459,34 +466,21 @@
var ch = $.browser.opera ? s.d.container.height() : s.getVal(s.d.container.css('height')),
cw = $.browser.opera ? s.d.container.width() : s.getVal(s.d.container.css('width')),
dh = s.d.data.outerHeight(true), dw = s.d.data.outerWidth(true);
var mh = s.o.maxHeight && s.o.maxHeight < w[0] ? s.o.maxHeight : w[0],
w = s.getDimensions();
var mh = (s.o.maxHeight && s.o.maxHeight < w[0] ? s.o.maxHeight : w[0]) - 80,
mw = s.o.maxWidth && s.o.maxWidth < w[1] ? s.o.maxWidth : w[1];
// NEWSBLUR.log(['heights', ch, dh, mh, w]);
// height
if (!ch) {
if (!dh) {ch = s.o.minHeight;}
else {
if (dh > mh) {ch = mh;}
else if (dh < s.o.minHeight) {ch = s.o.minHeight;}
else {ch = dh;}
}
}
else {
ch = ch > mh ? mh : ch;
}
if (dh > mh) {ch = mh;}
else if (dh < s.o.minHeight) {ch = s.o.minHeight;}
else {ch = dh;}
// width
if (!cw) {
if (!dw) {cw = s.o.minWidth;}
else {
if (dw > mw) {cw = mw;}
else if (dw < s.o.minWidth) {cw = s.o.minWidth;}
else {cw = dw;}
}
}
else {
cw = cw > mw ? mw : cw;
}
if (dw > mw) {cw = mw;}
else if (dw < s.o.minWidth) {cw = s.o.minWidth;}
else {cw = dw;}
s.d.container.css({height: ch, width: cw});
if (dh > ch || dw > cw) {

View file

@ -244,6 +244,13 @@ NEWSBLUR.AssetModel.Reader.prototype = {
$.isFunction(callback) && callback(data, first_load);
},
get_feeds_trainer: function(callback) {
var self = this;
this.make_request('/reader/get_feeds_trainer', {}, callback,
null, {'ajax_group': 'feed'});
},
refresh_feeds: function(callback) {
var self = this;

View file

@ -1149,13 +1149,13 @@
mark_story_as_like: function(story_id, $button) {
var feed_id = this.active_feed;
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierStory(story_id, feed_id, 1);
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierStory(story_id, feed_id, {'score': 1});
},
mark_story_as_dislike: function(story_id, $button) {
var feed_id = this.active_feed;
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierStory(story_id, feed_id, -1);
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierStory(story_id, feed_id, {'score': -1});
},
// =====================
@ -1518,7 +1518,8 @@
open_feed_intelligence_modal: function(score) {
var feed_id = this.active_feed;
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierFeed(feed_id, score);
// NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierFeed(feed_id, {'score': score});
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierTrainer({'score': score});
},
// ==========================
@ -1855,6 +1856,11 @@
$.make('div', { className: 'NB-menu-manage-title' }, 'Mark all feeds as read'),
$.make('div', { className: 'NB-menu-manage-subtitle' }, 'Choose how many days back.')
]),
$.make('li', { className: 'NB-menu-manage-feed NB-menu-manage-feed-train' }, [
$.make('div', { className: 'NB-menu-manage-image' }),
$.make('div', { className: 'NB-menu-manage-title' }, 'Train intelligence'),
$.make('div', { className: 'NB-menu-manage-subtitle' }, 'Accurate filters are happy filters.')
]),
$.make('li', { className: 'NB-menu-manage-preferences' }, [
$.make('div', { className: 'NB-menu-manage-image' }),
$.make('div', { className: 'NB-menu-manage-title' }, 'Preferences'),
@ -1883,7 +1889,7 @@
$.make('li', { className: 'NB-menu-manage-feed NB-menu-manage-feed-train' }, [
$.make('div', { className: 'NB-menu-manage-image' }),
$.make('div', { className: 'NB-menu-manage-title' }, 'Train intelligence'),
$.make('div', { className: 'NB-menu-manage-subtitle' }, 'Accurate filters are happy filters.')
$.make('div', { className: 'NB-menu-manage-subtitle' }, 'Choose classifiers for this site.')
]),
$.make('li', { className: 'NB-menu-manage-feed NB-menu-manage-feed-stats' }, [
$.make('div', { className: 'NB-menu-manage-image' }),

View file

@ -24,7 +24,7 @@ NEWSBLUR.ReaderAddFeed.prototype = {
this.$add = $.make('div', { className: 'NB-add NB-modal' }, [
$.make('h2', { className: 'NB-modal-title' }, 'Add feeds and folders'),
$.make('div', { className: 'NB-add-form' }, [
$.make('div', { className: 'NB-fieldset NB-add-add-url' }, [
$.make('div', { className: 'NB-fieldset NB-add-add-url NB-modal-submit' }, [
$.make('h5', [
$.make('div', { className: 'NB-add-folders' }, this.make_folders()),
'Add a new feed'
@ -34,12 +34,12 @@ NEWSBLUR.ReaderAddFeed.prototype = {
$.make('div', { className: 'NB-loading' }),
$.make('label', { 'for': 'NB-add-url' }, 'RSS or URL: '),
$.make('input', { type: 'text', id: 'NB-add-url', className: 'NB-add-url', name: 'url' }),
$.make('input', { type: 'submit', value: 'Add it', className: 'NB-add-url-submit' }),
$.make('input', { type: 'submit', value: 'Add it', className: 'NB-modal-submit-save NB-add-url-submit' }),
$.make('div', { className: 'NB-error' })
])
])
]),
$.make('div', { className: 'NB-fieldset NB-add-add-folder' }, [
$.make('div', { className: 'NB-fieldset NB-add-add-folder NB-modal-submit' }, [
$.make('h5', [
$.make('div', { className: 'NB-add-folders' }, this.make_folders()),
'Add a new folder'
@ -51,18 +51,18 @@ NEWSBLUR.ReaderAddFeed.prototype = {
$.make('div', { className: 'NB-folder-icon' })
]),
$.make('input', { type: 'text', id: 'NB-add-folder', className: 'NB-add-folder', name: 'url' }),
$.make('input', { type: 'submit', value: 'Add folder', className: 'NB-add-folder-submit' }),
$.make('input', { type: 'submit', value: 'Add folder', className: 'NB-add-folder-submit NB-modal-submit-save' }),
$.make('div', { className: 'NB-error' })
])
])
]),
$.make('div', { className: 'NB-fieldset NB-anonymous-ok' }, [
$.make('div', { className: 'NB-fieldset NB-anonymous-ok NB-modal-submit' }, [
$.make('h5', [
'Import from Google Reader'
'Import feeds'
]),
$.make('div', { className: 'NB-fieldset-fields' }, [
$.make('a', { href: NEWSBLUR.URLs['opml-reader-authorize'], className: 'NB-opml-reader-oauth NB-splash-link' }, [
'Import everything from Google Reader (OAuth)',
$.make('a', { href: NEWSBLUR.URLs['opml-reader-authorize'], className: 'NB-opml-reader-oauth NB-modal-submit-save NB-modal-submit-button' }, [
'Import from Google Reader',
$.make('img', { className: 'NB-add-google-reader-arrow', src: NEWSBLUR.Globals['MEDIA_URL']+'img/icons/silk/arrow_right.png' })
]),
$.make('div', { className: 'NB-add-danger' }, [
@ -71,13 +71,13 @@ NEWSBLUR.ReaderAddFeed.prototype = {
])
])
]),
$.make('div', { className: 'NB-fieldset NB-add-opml' }, [
$.make('div', { className: 'NB-fieldset NB-add-opml NB-modal-submit' }, [
$.make('h5', 'Upload OPML'),
$.make('div', { className: 'NB-fieldset-fields' }, [
$.make('form', { method: 'post', enctype: 'multipart/form-data', className: 'NB-add-form' }, [
$.make('div', { className: 'NB-loading' }),
$.make('input', { type: 'file', name: 'file', id: 'opml_file_input' }),
$.make('input', { type: 'submit', className: 'NB-add-opml-button', value: 'Upload OPML File' }).click(function(e) {
$.make('input', { type: 'submit', className: 'NB-add-opml-button NB-modal-submit-save', value: 'Upload OPML File' }).click(function(e) {
e.preventDefault();
self.handle_opml_upload();
return false;
@ -142,17 +142,17 @@ NEWSBLUR.ReaderAddFeed.prototype = {
this.$add.modal({
'minWidth': 600,
'maxHeight': height,
'overlayClose': true,
'onOpen': function (dialog) {
dialog.overlay.fadeIn(200, function () {
dialog.container.fadeIn(200);
dialog.data.fadeIn(200);
dialog.data.fadeIn(200, function() {
$.modal.impl.setContainerDimensions();
});
});
},
'onShow': function(dialog) {
$('#simplemodal-container').corner('6px').css({'width': 600, 'height': height});
$.modal.impl.setPosition();
},
'onClose': function(dialog) {
dialog.data.hide().empty().remove();

View file

@ -1,21 +1,46 @@
NEWSBLUR.ReaderClassifierFeed = function(feed_id, score, options) {
var defaults = {};
NEWSBLUR.ReaderClassifierTrainer = function(options) {
var defaults = {
'score': 1,
'training': true
};
this.flags = {
'publisher': true,
'story': false
};
this.cache = {};
this.trainer_iterator = 0;
this.feed_id = null;
this.options = $.extend({}, defaults, options);
this.score = this.options['score'];
this.model = NEWSBLUR.AssetModel.reader();
this.google_favicon_url = 'http://www.google.com/s2/favicons?domain_url=';
this.runner_trainer();
};
NEWSBLUR.ReaderClassifierFeed = function(feed_id, options) {
var defaults = {
'score': 1,
'training': false
};
this.flags = {
'publisher': true,
'story': false
};
this.feed_id = feed_id;
this.score = score;
this.options = $.extend({}, defaults, options);
this.score = this.options['score'];
this.model = NEWSBLUR.AssetModel.reader();
this.google_favicon_url = 'http://www.google.com/s2/favicons?domain_url=';
this.runner_feed();
};
NEWSBLUR.ReaderClassifierStory = function(story_id, feed_id, score, options) {
var defaults = {};
NEWSBLUR.ReaderClassifierStory = function(story_id, feed_id, options) {
var defaults = {
'score': 1
};
this.flags = {
'publisher': false,
@ -23,8 +48,8 @@ NEWSBLUR.ReaderClassifierStory = function(story_id, feed_id, score, options) {
};
this.story_id = story_id;
this.feed_id = feed_id;
this.score = score;
this.options = $.extend({}, defaults, options);
this.score = this.options['score'];
this.model = NEWSBLUR.AssetModel.reader();
this.google_favicon_url = 'http://www.google.com/s2/favicons?domain_url=';
this.runner_story();
@ -32,19 +57,37 @@ NEWSBLUR.ReaderClassifierStory = function(story_id, feed_id, score, options) {
var classifier = {
runner_feed: function() {
this.find_story_and_feed();
this.make_modal_feed();
this.make_modal_title();
this.make_modal_intelligence_slider();
this.handle_text_highlight();
runner_trainer: function() {
this.user_classifiers = {};
this.make_trainer_intro();
this.get_feeds_trainer();
this.handle_select_checkboxes();
this.handle_cancel();
this.handle_select_title();
this.open_modal();
this.$modal.parent().bind('click.reader_classifer', $.rescope(this.handle_clicks, this));
},
runner_feed: function() {
this.user_classifiers = this.model.classifiers;
this.find_story_and_feed();
this.make_modal_feed();
this.make_modal_title();
this.make_modal_intelligence_slider();
this.handle_select_checkboxes();
this.handle_cancel();
this.handle_select_title();
this.open_modal();
this.$modal.bind('submit.reader_classifer', $.rescope(this.handle_submit, this));
},
runner_story: function() {
this.user_classifiers = this.model.classifiers;
this.find_story_and_feed();
this.make_modal_story();
this.make_modal_title();
@ -55,6 +98,49 @@ var classifier = {
this.open_modal();
},
load_next_feed_in_trainer: function(backwards) {
if (backwards) {
this.trainer_iterator = Math.max(1, this.trainer_iterator - 1);
} else {
this.trainer_iterator = Math.min(this.trainer_data.length, this.trainer_iterator + 1);
}
var trainer_data = this.trainer_data[this.trainer_iterator-1];
this.feed_id = trainer_data['feed_id'];
this.feed = this.model.get_feed(this.feed_id);
this.feed_tags = trainer_data['feed_tags'];
this.feed_authors = trainer_data['feed_authors'];
this.user_classifiers = trainer_data['classifiers'];
this.make_modal_feed();
this.make_modal_title();
this.make_modal_trainer_count();
if (backwards || this.feed_id in this.cache) {
this.$modal = this.cache[this.feed_id];
}
$('.NB-modal').replaceWith(this.$modal);
// var height = this.$modal.outerHeight(true);
$.modal.impl.resize(this.$modal);
},
get_feeds_trainer: function() {
this.model.get_feeds_trainer($.rescope(this.load_feeds_trainer, this));
},
load_feeds_trainer: function(e, data) {
var $begin = $('.NB-modal-submit-begin', this.$modal);
NEWSBLUR.log(['data', data]);
this.trainer_data = data;
$begin.text('Begin Training')
.addClass('NB-modal-submit-save')
.removeClass('NB-disabled');
},
find_story_and_feed: function() {
if (this.story_id) {
this.story = this.model.get_story(this.story_id);
@ -62,6 +148,22 @@ var classifier = {
this.feed = this.model.get_feed(this.feed_id);
this.feed_tags = this.model.get_feed_tags();
this.feed_authors = this.model.get_feed_authors();
$('.NB-modal-subtitle .NB-modal-feed-image', this.$modal).attr('src', this.google_favicon_url + this.feed['feed_link']);
$('.NB-modal-subtitle .NB-modal-feed-title', this.$modal).html(this.feed['feed_title']);
},
make_trainer_intro: function() {
var self = this;
this.$modal = $.make('div', { className: 'NB-classifier NB-modal NB-trainer'}, [
$.make('h2', { className: 'NB-modal-title' }, 'Intelligence Trainer'),
$.make('h2', { className: 'NB-modal-title' }, 'Trained feed are happy feeds'),
$.make('div', { className: 'NB-modal-submit' }, [
$.make('a', { href: '#', className: 'NB-modal-submit-save NB-modal-submit-begin NB-modal-submit-button NB-disabled' }, 'Loading Training...')
])
]);
},
make_modal_feed: function() {
@ -69,11 +171,17 @@ var classifier = {
var feed = this.feed;
var opinion = (this.score == 1 ? 'like_' : 'dislike_');
NEWSBLUR.log(['Make feed', feed, this.feed_authors, this.feed_tags]);
// NEWSBLUR.log(['Make feed', feed, this.feed_authors, this.feed_tags]);
this.$classifier = $.make('div', { className: 'NB-classifier NB-modal' }, [
this.make_modal_intelligence_slider(),
this.$modal = $.make('div', { className: 'NB-classifier NB-modal' }, [
$.make('div', { className: 'NB-modal-loading' }),
(!this.options['training'] && this.make_modal_intelligence_slider()),
(this.options['training'] && $.make('div', { className: 'NB-classifier-trainer-counts' })),
$.make('h2', { className: 'NB-modal-title' }),
$.make('h2', { className: 'NB-modal-subtitle' }, [
$.make('img', { className: 'NB-modal-feed-image feed_favicon', src: this.google_favicon_url + this.feed.feed_link }),
$.make('span', { className: 'NB-modal-feed-title' }, this.feed.feed_title)
]),
$.make('form', { method: 'post', className: 'NB-publisher' }, [
(this.feed_authors.length && $.make('div', { className: 'NB-modal-field NB-fieldset NB-classifiers' }, [
$.make('h5', 'Authors'),
@ -93,19 +201,22 @@ var classifier = {
this.make_publisher(feed, opinion)
)
]),
$.make('div', { className: 'NB-modal-submit' }, [
(this.options['training'] && $.make('div', { className: 'NB-modal-submit' }, [
$.make('input', { name: 'score', value: this.score, type: 'hidden' }),
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
$.make('a', { href: '#', className: 'NB-modal-submit-button NB-modal-submit-back' }, $.entity('&laquo;') + ' Back'),
$.make('a', { href: '#', className: 'NB-modal-submit-button NB-modal-submit-save' }, 'Save & Next '+$.entity('&raquo;')),
$.make('a', { href: '#', className: 'NB-modal-submit-button NB-modal-submit-close' }, 'Close')
])),
(!this.options['training'] && $.make('div', { className: 'NB-modal-submit' }, [
$.make('input', { name: 'score', value: this.score, type: 'hidden' }),
$.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }),
$.make('input', { type: 'submit', disabled: 'true', className: 'NB-disabled', value: 'Check what you like above...' }),
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
$.make('input', { type: 'submit', disabled: 'true', className: 'NB-modal-submit-save NB-disabled', value: 'Check what you like above...' }),
' or ',
$.make('a', { href: '#', className: 'NB-modal-cancel' }, 'cancel')
])
]).bind('submit', function(e) {
e.preventDefault();
self.save_publisher();
return false;
})
]))
])
]);
},
@ -120,7 +231,7 @@ var classifier = {
// HTML entities decoding.
story.story_title = $('<div/>').html(story.story_title).text();
this.$classifier = $.make('div', { className: 'NB-classifier NB-modal' }, [
this.$modal = $.make('div', { className: 'NB-classifier NB-modal' }, [
this.make_modal_intelligence_slider(),
$.make('h2', { className: 'NB-modal-title' }),
$.make('form', { method: 'post' }, [
@ -157,9 +268,9 @@ var classifier = {
]),
$.make('div', { className: 'NB-modal-submit' }, [
$.make('input', { name: 'score', value: this.score, type: 'hidden' }),
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
$.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }),
$.make('input', { type: 'submit', disabled: 'true', className: 'NB-disabled', value: 'Check what you like above...' }),
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
$.make('input', { type: 'submit', disabled: 'true', className: 'NB-modal-submit-save NB-disabled', value: 'Check what you like above...' }),
' or ',
$.make('a', { href: '#', className: 'NB-modal-cancel' }, 'cancel')
])
@ -172,7 +283,7 @@ var classifier = {
},
make_modal_title: function() {
var $modal_title = $('.NB-modal-title', this.$classifier);
var $modal_title = $('.NB-modal-title', this.$modal);
if (this.flags['publisher']) {
if (this.score == 1) {
@ -189,6 +300,13 @@ var classifier = {
}
},
make_modal_trainer_count: function() {
var $count = $('.NB-classifier-trainer-counts', this.$modal);
var count = this.trainer_iterator;
var total = this.trainer_data.length;
$count.html(count + '/' + total);
},
make_modal_intelligence_slider: function() {
var self = this;
var $slider = $.make('div', { className: 'NB-taskbar-intelligence NB-modal-slider' }, [
@ -208,14 +326,14 @@ var classifier = {
// self.switch_feed_view_unread_view(ui.value);
self.score = ui.value - 1;
self.make_modal_title();
$('input[name^=like],input[name^=dislike]', self.$classifier).attr('name', function(i, current_name) {
$('input[name^=like],input[name^=dislike]', self.$modal).attr('name', function(i, current_name) {
if (self.score == -1) {
return 'dis' + current_name.substr(current_name.indexOf('like_'));
} else if (self.score == 1) {
return current_name.substr(current_name.indexOf('like_'));
}
});
var $submit = $('input[type=submit]', self.$classifier);
var $submit = $('input[type=submit]', self.$modal);
$submit.removeClass("NB-disabled").removeAttr('disabled').attr('value', 'Save');
}
});
@ -245,8 +363,8 @@ var classifier = {
id: 'classifier_author_'+a
};
if (author in this.model.classifiers.authors
&& this.model.classifiers.authors[author] == this.score) {
if (author in this.user_classifiers.authors
&& this.user_classifiers.authors[author] == this.score) {
input_attrs['checked'] = 'checked';
}
@ -290,7 +408,7 @@ var classifier = {
id: 'classifier_tag_'+t
};
if (tag in this.model.classifiers.tags && this.model.classifiers.tags[tag] == this.score) {
if (tag in this.user_classifiers.tags && this.user_classifiers.tags[tag] == this.score) {
input_attrs['checked'] = 'checked';
}
@ -321,8 +439,8 @@ var classifier = {
id: 'classifier_publisher',
checked: false
};
if (this.feed.feed_link in this.model.classifiers.feeds
&& this.model.classifiers.feeds[this.feed.feed_link].score == this.score) {
if (this.feed.feed_link in this.user_classifiers.feeds
&& this.user_classifiers.feeds[this.feed.feed_link].score == this.score) {
input_attrs['checked'] = true;
}
@ -354,7 +472,7 @@ var classifier = {
var self = this;
var $holder = $.make('div', { className: 'NB-modal-holder' })
.append(this.$classifier)
.append(this.$modal)
.appendTo('body')
.css({'visibility': 'hidden', 'display': 'block', 'width': 600});
var height = $('.NB-classifier', $holder).outerHeight(true);
@ -364,11 +482,11 @@ var classifier = {
height = w[0] - 70;
}
this.$classifier.modal({
this.$modal.modal({
'minWidth': 600,
'maxHeight': height,
'overlayClose': true,
'autoResize': true,
'position': [40, 0],
'onOpen': function (dialog) {
dialog.overlay.fadeIn(200, function () {
dialog.container.fadeIn(200);
@ -377,7 +495,7 @@ var classifier = {
},
'onShow': function(dialog) {
$('#simplemodal-container').corner('6px').css({'width': 600, 'height': height});
$('.NB-classifier', self.$classifier).corner('14px');
$('.NB-classifier', self.$modal).corner('14px');
$.modal.impl.setPosition();
},
'onClose': function(dialog) {
@ -393,9 +511,9 @@ var classifier = {
},
handle_text_highlight: function() {
var $title_highlight = $('.NB-classifier-title-highlight', this.$classifier);
var $title = $('.NB-classifier-title-text', this.$classifier);
var $title_checkbox = $('#classifier_title', this.$classifier);
var $title_highlight = $('.NB-classifier-title-highlight', this.$modal);
var $title = $('.NB-classifier-title-text', this.$modal);
var $title_checkbox = $('#classifier_title', this.$modal);
var update = function() {
var text = $.trim($(this).getSelection().text);
@ -415,9 +533,9 @@ var classifier = {
},
handle_select_title: function() {
var $title_checkbox = $('#classifier_title', this.$classifier);
var $title = $('.NB-classifier-title-text', this.$classifier);
var $title_highlight = $('.NB-classifier-title-highlight', this.$classifier);
var $title_checkbox = $('#classifier_title', this.$modal);
var $title = $('.NB-classifier-title-text', this.$modal);
var $title_highlight = $('.NB-classifier-title-highlight', this.$modal);
$title_checkbox.change(function() {;
if ($title.parents('.NB-classifier-facet-disabled').length) {
@ -432,16 +550,22 @@ var classifier = {
handle_select_checkboxes: function() {
var self = this;
var $submit = $('input[type=submit]', this.$classifier);
var $save = $('.NB-modal-submit-save', this.$modal);
var $close = $('.NB-modal-submit-close', this.$modal);
var $back = $('.NB-modal-submit-back', this.$modal);
$('input', this.$classifier).change(function() {
// var count = $('input:checked', self.$classifier).length;
$submit.removeClass("NB-disabled").removeAttr('disabled').attr('value', 'Save');
$('input', this.$modal).change(function() {
// var count = $('input:checked', self.$modal).length;
if (self.options['training']) {
$close.val('Save & Close');
} else {
$submit.removeClass("NB-disabled").removeAttr('disabled').attr('value', 'Save');
}
});
},
handle_cancel: function() {
var $cancel = $('.NB-modal-cancel', this.$classifier);
var $cancel = $('.NB-modal-cancel', this.$modal);
$cancel.click(function(e) {
e.preventDefault();
@ -449,10 +573,44 @@ var classifier = {
});
},
handle_submit: function(elem, e) {
var self = this;
$.targetIs(e, { tagSelector: '.NB-modal-submit-save' }, function($t, $p){
e.preventDefault();
self.save_publisher();
});
},
handle_clicks: function(elem, e) {
var self = this;
$.targetIs(e, { tagSelector: '.NB-modal-submit-begin' }, function($t, $p){
e.preventDefault();
self.load_next_feed_in_trainer();
});
$.targetIs(e, { tagSelector: '.NB-modal-submit-save:not(.NB-modal-submit-begin)' }, function($t, $p){
e.preventDefault();
self.save_publisher(true);
self.load_next_feed_in_trainer();
});
$.targetIs(e, { tagSelector: '.NB-modal-submit-back' }, function($t, $p){
e.preventDefault();
self.load_next_feed_in_trainer(true);
});
$.targetIs(e, { tagSelector: '.NB-modal-submit-close' }, function($t, $p){
e.preventDefault();
self.save_publisher();
});
},
serialize_classifier: function() {
var checked_data = $('input', this.$classifier).serialize();
var checked_data = $('input', this.$modal).serialize();
var $unchecked = $('input[type=checkbox]:not(:checked)', this.$classifier);
var $unchecked = $('input[type=checkbox]:not(:checked)', this.$modal);
$unchecked.attr('checked', true);
$unchecked.each(function() {
$(this).attr('name', 'remove_' + $(this).attr('name'));
@ -468,26 +626,31 @@ var classifier = {
return data;
},
save_publisher: function() {
var $save = $('.NB-classifier input[type=submit]');
save_publisher: function(keep_modal_open) {
var $save = $('.NB-modal-submit-save', this.$modal);
var story_id = this.story_id;
var data = this.serialize_classifier();
NEWSBLUR.reader.update_opinions(this.$classifier, this.feed_id);
NEWSBLUR.reader.update_opinions(this.$modal, this.feed_id);
if (this.options['training']) {
this.cache[this.feed_id] = this.$modal.clone();
}
$save.text('Saving...').addClass('NB-disabled').attr('disabled', true);
this.model.save_classifier_publisher(data, function() {
NEWSBLUR.reader.force_feed_refresh();
$.modal.close();
if (!keep_modal_open) {
NEWSBLUR.reader.force_feed_refresh();
$.modal.close();
}
});
},
save_story: function() {
var $save = $('.NB-classifier input[type=submit]');
var $save = $('.NB-modal-submit-save', this.$modal);
var story_id = this.story_id;
var data = this.serialize_classifier();
NEWSBLUR.reader.update_opinions(this.$classifier, this.feed_id);
NEWSBLUR.reader.update_opinions(this.$modal, this.feed_id);
$save.text('Saving...').addClass('NB-disabled').attr('disabled', true);
this.model.save_classifier_story(story_id, data, function() {
@ -500,3 +663,4 @@ var classifier = {
NEWSBLUR.ReaderClassifierStory.prototype = classifier;
NEWSBLUR.ReaderClassifierFeed.prototype = classifier;
NEWSBLUR.ReaderClassifierTrainer.prototype = classifier;

View file

@ -255,19 +255,9 @@ NEWSBLUR.ReaderManageFeed.prototype = {
open_modal: function() {
var self = this;
var $holder = $.make('div', { className: 'NB-modal-holder' }).append(this.$manage).appendTo('body').css({'visibility': 'hidden', 'display': 'block', 'width': 600});
var height = $('.NB-manage', $holder).outerHeight(true);
$holder.css({'visibility': 'visible', 'display': 'none'});
var w = $.modal.impl.getDimensions();
if (height > w[0] - 70) {
height = w[0] - 70;
}
this.$manage.modal({
'minWidth': 600,
'maxHeight': height,
'overlayClose': true,
'onOpen': function (dialog) {
dialog.overlay.fadeIn(200, function () {

View file

@ -30,7 +30,7 @@ NEWSBLUR.ReaderMarkRead.prototype = {
$.make('div', { className: 'NB-markread-slider'}),
$.make('div', { className: 'NB-markread-explanation'}),
$.make('div', { className: 'NB-modal-submit' }, [
$.make('input', { type: 'submit', className: '', value: 'Do it' }),
$.make('input', { type: 'submit', className: 'NB-modal-submit-save', value: 'Do it' }),
' or ',
$.make('a', { href: '#', className: 'NB-modal-cancel' }, 'cancel')
])
@ -125,11 +125,15 @@ NEWSBLUR.ReaderMarkRead.prototype = {
var days = $slider.slider('option', 'value');
$save.attr('value', 'Marking as read...').addClass('NB-disabled').attr('disabled', true);
this.model.save_mark_read(days, function() {
NEWSBLUR.reader.force_feed_refresh(function() {
$.modal.close();
if (NEWSBLUR.Globals.is_authenticated) {
this.model.save_mark_read(days, function() {
NEWSBLUR.reader.force_feed_refresh(function() {
$.modal.close();
});
});
});
} else {
$.modal.close();
}
},
// ===========

View file

@ -28,8 +28,8 @@ NEWSBLUR.ReaderStatistics.prototype = {
$.make('div', { className: 'NB-modal-loading' }),
$.make('h2', { className: 'NB-modal-title' }, 'Statistics &amp; History'),
$.make('h2', { className: 'NB-modal-subtitle' }, [
$.make('img', { className: 'NB-modal-statistics-feed-image feed_favicon', src: this.google_favicon_url + this.feed.feed_link }),
$.make('span', { className: 'NB-modal-statistics-feed-title' }, this.feed.feed_title)
$.make('img', { className: 'NB-modal-feed-image feed_favicon', src: this.google_favicon_url + this.feed.feed_link }),
$.make('span', { className: 'NB-modal-feed-title' }, this.feed.feed_title)
]),
$.make('div', { className: 'NB-modal-statistics-info' }),
$.make('div', { className: 'NB-modal-feed-chooser-container'}, [
@ -42,8 +42,8 @@ NEWSBLUR.ReaderStatistics.prototype = {
this.feed_id = feed_id;
this.feed = this.model.get_feed(feed_id);
$('.NB-modal-subtitle .NB-modal-statistics-feed-image', this.$manage).attr('src', this.google_favicon_url + this.feed['feed_link']);
$('.NB-modal-subtitle .NB-modal-statistics-feed-title', this.$manage).html(this.feed['feed_title']);
$('.NB-modal-subtitle .NB-modal-feed-image', this.$modal).attr('src', this.google_favicon_url + this.feed['feed_link']);
$('.NB-modal-subtitle .NB-modal-feed-title', this.$modal).html(this.feed['feed_title']);
},
open_modal: function() {

View file

@ -11,13 +11,16 @@ graph_config = {
'graph_vlabel' : 'users',
'all.label': 'all',
'monthly.label': 'monthly',
'daily.label': 'daily',
}
last_month = datetime.datetime.now() - datetime.timedelta(days=30)
last_day = datetime.datetime.now() - datetime.timedelta(minutes=60*24)
metrics = {
'all': User.objects.count(),
'monthly': Profile.objects.filter(last_seen_on__gte=last_month).count()
'monthly': Profile.objects.filter(last_seen_on__gte=last_month).count(),
'daily': Profile.objects.filter(last_seen_on__gte=last_day).count(),
}
if __name__ == '__main__':