Skip to content
This repository
Browse code

Adding paging on recommendations. Also moved out of profile preferenc…

…es, since it needs to be used by the base template when setting up the middle column (the column where recommended feeds go). Now a first-order column on user profiles.
  • Loading branch information...
commit 4ab3904d52f2118862e06167a6472ef1ebc4382c 1 parent 7a4a651
Samuel Clay authored
5 apps/analyzer/views.py
@@ -25,7 +25,10 @@ def save_classifier(request):
25 25 payload = {}
26 26
27 27 # Mark subscription as dirty, so unread counts can be recalculated
28   - usersub = UserSubscription.objects.filter(user=request.user, feed=feed)
  28 + try:
  29 + usersub = UserSubscription.objects.get(user=request.user, feed=feed)
  30 + except UserSubscription.DoesNotExist:
  31 + usersub = None
29 32 if usersub and (not usersub.needs_unread_recalc or not usersub.is_trained):
30 33 usersub.needs_unread_recalc = True
31 34 usersub.is_trained = True
74 apps/profile/migrations/0011_feed_pane_size.py
... ... @@ -0,0 +1,74 @@
  1 +# encoding: utf-8
  2 +import datetime
  3 +from south.db import db
  4 +from south.v2 import SchemaMigration
  5 +from django.db import models
  6 +
  7 +class Migration(SchemaMigration):
  8 +
  9 + def forwards(self, orm):
  10 +
  11 + # Adding field 'Profile.feed_pane_size'
  12 + db.add_column('profile_profile', 'feed_pane_size', self.gf('django.db.models.fields.IntegerField')(default=240), keep_default=False)
  13 +
  14 +
  15 + def backwards(self, orm):
  16 +
  17 + # Deleting field 'Profile.feed_pane_size'
  18 + db.delete_column('profile_profile', 'feed_pane_size')
  19 +
  20 +
  21 + models = {
  22 + 'auth.group': {
  23 + 'Meta': {'object_name': 'Group'},
  24 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  25 + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
  26 + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
  27 + },
  28 + 'auth.permission': {
  29 + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
  30 + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  31 + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
  32 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  33 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
  34 + },
  35 + 'auth.user': {
  36 + 'Meta': {'object_name': 'User'},
  37 + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  38 + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
  39 + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  40 + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
  41 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  42 + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
  43 + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  44 + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  45 + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  46 + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  47 + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
  48 + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
  49 + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
  50 + },
  51 + 'contenttypes.contenttype': {
  52 + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
  53 + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  54 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  55 + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  56 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
  57 + },
  58 + 'profile.profile': {
  59 + 'Meta': {'object_name': 'Profile'},
  60 + 'collapsed_folders': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
  61 + 'feed_pane_size': ('django.db.models.fields.IntegerField', [], {'default': '240'}),
  62 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  63 + 'is_premium': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  64 + 'last_seen_ip': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
  65 + 'last_seen_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  66 + 'preferences': ('django.db.models.fields.TextField', [], {'default': "'{}'"}),
  67 + 'secret_token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
  68 + 'timezone': ('utils.timezones.fields.TimeZoneField', [], {'default': "'America/New_York'", 'max_length': '100'}),
  69 + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
  70 + 'view_settings': ('django.db.models.fields.TextField', [], {'default': "'{}'"})
  71 + }
  72 + }
  73 +
  74 + complete_apps = ['profile']
78 apps/profile/migrations/0012_feed_pane_size_json.py
... ... @@ -0,0 +1,78 @@
  1 +# encoding: utf-8
  2 +import datetime
  3 +from south.db import db
  4 +from south.v2 import DataMigration
  5 +from django.db import models
  6 +from utils import json_functions as json
  7 +class Migration(DataMigration):
  8 +
  9 + def forwards(self, orm):
  10 + for profile in orm.Profile.objects.all():
  11 + if 'feed_pane_size' in profile.preferences:
  12 + preferences = json.decode(profile.preferences)
  13 + feed_pane_size = int(preferences.get('feed_pane_size', 240))
  14 + del preferences['feed_pane_size']
  15 + print " --> User %s: %s" % (profile.user.username, feed_pane_size)
  16 + profile.feed_pane_size = feed_pane_size
  17 + profile.preferences = json.encode(preferences)
  18 + profile.save()
  19 +
  20 +
  21 + def backwards(self, orm):
  22 + "Write your backwards methods here."
  23 +
  24 +
  25 + models = {
  26 + 'auth.group': {
  27 + 'Meta': {'object_name': 'Group'},
  28 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  29 + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
  30 + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
  31 + },
  32 + 'auth.permission': {
  33 + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
  34 + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  35 + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
  36 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  37 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
  38 + },
  39 + 'auth.user': {
  40 + 'Meta': {'object_name': 'User'},
  41 + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  42 + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
  43 + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  44 + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
  45 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  46 + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
  47 + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  48 + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  49 + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  50 + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  51 + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
  52 + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
  53 + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
  54 + },
  55 + 'contenttypes.contenttype': {
  56 + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
  57 + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  58 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  59 + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  60 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
  61 + },
  62 + 'profile.profile': {
  63 + 'Meta': {'object_name': 'Profile'},
  64 + 'collapsed_folders': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
  65 + 'feed_pane_size': ('django.db.models.fields.IntegerField', [], {'default': '240'}),
  66 + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  67 + 'is_premium': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  68 + 'last_seen_ip': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
  69 + 'last_seen_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  70 + 'preferences': ('django.db.models.fields.TextField', [], {'default': "'{}'"}),
  71 + 'secret_token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
  72 + 'timezone': ('utils.timezones.fields.TimeZoneField', [], {'default': "'America/New_York'", 'max_length': '100'}),
  73 + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
  74 + 'view_settings': ('django.db.models.fields.TextField', [], {'default': "'{}'"})
  75 + }
  76 + }
  77 +
  78 + complete_apps = ['profile']
1  apps/profile/models.py
@@ -20,6 +20,7 @@ class Profile(models.Model):
20 20 preferences = models.TextField(default="{}")
21 21 view_settings = models.TextField(default="{}")
22 22 collapsed_folders = models.TextField(default="[]")
  23 + feed_pane_size = models.IntegerField(default=240)
23 24 last_seen_on = models.DateTimeField(default=datetime.datetime.now)
24 25 last_seen_ip = models.CharField(max_length=50, blank=True, null=True)
25 26 timezone = TimeZoneField(default="America/New_York")
2  apps/profile/views.py
@@ -12,7 +12,7 @@
12 12 from apps.profile.models import Profile, change_password
13 13 from apps.reader.models import UserSubscription
14 14
15   -SINGLE_FIELD_PREFS = ('timezone',)
  15 +SINGLE_FIELD_PREFS = ('timezone','feed_pane_size')
16 16 SPECIAL_PREFERENCES = ('old_password', 'new_password',)
17 17
18 18 @ajax_login_required
6 apps/reader/views.py
@@ -729,6 +729,10 @@ def delete_feed(request):
729 729 user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
730 730 user_sub_folders.delete_feed(feed_id, in_folder)
731 731
  732 + feed = Feed.objects.filter(pk=feed_id)
  733 + if feed:
  734 + feed[0].count_subscribers()
  735 +
732 736 return dict(code=1)
733 737
734 738 @ajax_login_required
@@ -793,7 +797,7 @@ def add_feature(request):
793 797 @json.json_view
794 798 def load_features(request):
795 799 page = int(request.POST.get('page', 0))
796   - logging.user(request.user, "~FBBrowse features: Page #%s" % (page+1))
  800 + logging.user(request.user, "~FBBrowse features: ~SBPage #%s" % (page+1))
797 801 features = Feature.objects.all()[page*3:(page+1)*3+1].values()
798 802 features = [{
799 803 'description': f['description'],
6 apps/recommendations/templatetags/recommendations_tags.py
@@ -7,7 +7,7 @@
7 7 @register.inclusion_tag('recommendations/render_recommended_feed.xhtml', takes_context=True)
8 8 def render_recommended_feed(context, recommended_feed):
9 9 user = get_user(context['user'])
10   -
  10 +
11 11 usersub = UserSubscription.objects.filter(user=user, feed=recommended_feed.feed)
12 12
13 13 if recommended_feed.feed:
@@ -15,4 +15,6 @@ def render_recommended_feed(context, recommended_feed):
15 15 'recommended_feed': recommended_feed,
16 16 'usersub': usersub,
17 17 'user': context['user'],
18   - }
  18 + 'has_next_page': True
  19 + }
  20 +
6 apps/recommendations/urls.py
... ... @@ -0,0 +1,6 @@
  1 +from django.conf.urls.defaults import *
  2 +from apps.recommendations import views
  3 +
  4 +urlpatterns = patterns('',
  5 + url(r'^load_recommended_feed', views.load_recommended_feed, name='load-recommended-feed'),
  6 +)
27 apps/recommendations/views.py
... ... @@ -1 +1,26 @@
1   -# Create your views here.
  1 +from utils import log as logging
  2 +from django.template import RequestContext
  3 +from django.shortcuts import render_to_response
  4 +from apps.recommendations.models import RecommendedFeed
  5 +from apps.reader.models import UserSubscription
  6 +# from utils import json_functions as json
  7 +from utils.user_functions import get_user
  8 +
  9 +
  10 +def load_recommended_feed(request):
  11 + user = get_user(request)
  12 + page = int(request.REQUEST.get('page', 0))
  13 + usersub = None
  14 +
  15 + recommended_feeds = RecommendedFeed.objects.all()[page:page+2]
  16 + if recommended_feeds:
  17 + usersub = UserSubscription.objects.filter(user=user, feed=recommended_feeds[0].feed)
  18 + print recommended_feeds, len(recommended_feeds)
  19 + logging.user(request.user, "~FBBrowse recommended feed: ~SBPage #%s" % (page+1))
  20 +
  21 + return render_to_response('recommendations/render_recommended_feed.xhtml', {
  22 + 'recommended_feed' : recommended_feeds and recommended_feeds[0],
  23 + 'usersub' : usersub,
  24 + 'has_next_page' : len(recommended_feeds) > 1,
  25 + 'has_previous_page' : page != 0,
  26 + }, context_instance=RequestContext(request))
59 media/css/reader.css
@@ -673,24 +673,24 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
673 673 text-shadow: none;
674 674 }
675 675
676   -.NB-feedlist-hide-read-feeds .feed {
  676 +.NB-feedlist-hide-read-feeds #feed_list .feed {
677 677 display: none;
678 678 }
679   -.NB-feedlist-hide-read-feeds .unread_view_positive .unread_positive {
  679 +.NB-feedlist-hide-read-feeds #feed_list.unread_view_positive .unread_positive {
680 680 display: block;
681 681 }
682   -.NB-feedlist-hide-read-feeds .unread_view_neutral .unread_positive,
683   -.NB-feedlist-hide-read-feeds .unread_view_neutral .unread_neutral {
  682 +.NB-feedlist-hide-read-feeds #feed_list.unread_view_neutral .unread_positive,
  683 +.NB-feedlist-hide-read-feeds #feed_list.unread_view_neutral .unread_neutral {
684 684 display: block;
685 685 }
686 686
687   -.NB-feedlist-hide-read-feeds .unread_view_negative .unread_positive,
688   -.NB-feedlist-hide-read-feeds .unread_view_negative .unread_neutral,
689   -.NB-feedlist-hide-read-feeds .unread_view_negative .unread_negative {
  687 +.NB-feedlist-hide-read-feeds #feed_list.unread_view_negative .unread_positive,
  688 +.NB-feedlist-hide-read-feeds #feed_list.unread_view_negative .unread_neutral,
  689 +.NB-feedlist-hide-read-feeds #feed_list.unread_view_negative .unread_negative {
690 690 display: block;
691 691 }
692 692
693   -.NB-feedlist-hide-read-feeds .feed.NB-empty {
  693 +.NB-feedlist-hide-read-feeds #feed_list .feed.NB-empty {
694 694 display: block;
695 695 }
696 696
@@ -1878,7 +1878,7 @@ background: transparent;
1878 1878 color: #FFF;
1879 1879 height: 15px;
1880 1880 font-size: 11px;
1881   - padding: 2px 6px 2px 0;
  1881 + padding: 0 0 2px 0;
1882 1882 text-transform: uppercase;
1883 1883 text-shadow: 0 1px 0 #303030;
1884 1884 border-bottom: 1px solid #E9E9E9;
@@ -1897,6 +1897,7 @@ background: transparent;
1897 1897 .NB-feeds-header .NB-feeds-header-left {
1898 1898 float: left;
1899 1899 color: #FFF;
  1900 + padding-top: 1px;
1900 1901 }
1901 1902
1902 1903 .NB-feeds-header .NB-feeds-header-count {
@@ -1922,6 +1923,12 @@ background: transparent;
1922 1923 .NB-feeds-header .NB-feeds-header-sites {
1923 1924 float: right;
1924 1925 cursor: pointer;
  1926 + padding-right: 16px;
  1927 + padding-top: 1px;
  1928 + background: transparent url('../img/icons/silk/bullet_orange.png') no-repeat right 0;
  1929 +}
  1930 +.NB-feedlist-hide-read-feeds .NB-feeds-header .NB-feeds-header-sites {
  1931 + background-image: url('../img/icons/silk/bullet_blue.png');
1925 1932 }
1926 1933 .NB-feeds-header .NB-feeds-header-sites:hover {
1927 1934 color: #5E7B88;
@@ -1931,7 +1938,7 @@ background: transparent;
1931 1938 }
1932 1939 .NB-feeds-header .NB-feeds-header-home {
1933 1940 display: none;
1934   - padding: 0 0 0 4px;
  1941 + padding: 1px 0 0 4px;
1935 1942 color: #7493C7;
1936 1943 }
1937 1944 .NB-feeds-header.NB-active:hover {
@@ -3230,10 +3237,11 @@ background: transparent;
3230 3237
3231 3238 .NB-module .NB-module-direction {
3232 3239 display: block;
3233   - width: 16px;
3234   - height: 16px;
  3240 + width: 24px;
  3241 + height: 32px;
3235 3242 float: right;
3236   - padding: 0 3px 0px;
  3243 + margin: -8px 0;
  3244 + padding: 0px;
3237 3245 }
3238 3246
3239 3247 .NB-module .NB-module-direction.NB-disabled {
@@ -3241,32 +3249,36 @@ background: transparent;
3241 3249 }
3242 3250
3243 3251 .NB-module .NB-module-next-page {
3244   - background: transparent url('../img/icons/silk/control_play_blue.png') no-repeat center center;
  3252 + margin-right: -12px;
  3253 + padding-right: 8px;
  3254 +
  3255 + background: transparent url('../img/icons/silk/control_play_blue.png') no-repeat 4px center;
3245 3256 }
3246 3257 .NB-module .NB-module-next-page.NB-javascript {
3247 3258 opacity: .2;
3248 3259 }
3249 3260 .NB-module .NB-module-next-page:link {
3250   - background: transparent url('../img/icons/silk/control_play.png') no-repeat center center;
  3261 + background: transparent url('../img/icons/silk/control_play.png') no-repeat 4px center;
3251 3262 }
3252 3263 .NB-module .NB-module-next-page:hover {
3253   - background: transparent url('../img/icons/silk/control_play_blue.png') no-repeat center center;
  3264 + background: transparent url('../img/icons/silk/control_play_blue.png') no-repeat 4px center;
3254 3265 }
3255 3266 .NB-module .NB-module-next-page.NB-disabled:hover {
3256   - background: transparent url('../img/icons/silk/control_play.png') no-repeat center center;
  3267 + background: transparent url('../img/icons/silk/control_play.png') no-repeat 4px center;
3257 3268 cursor: default;
3258 3269 }
3259 3270 .NB-module .NB-module-previous-page {
3260   - background: transparent url('../img/icons/silk/control_play_left_blue.png') no-repeat center center;
  3271 + padding-left: 4px;
  3272 + background: transparent url('../img/icons/silk/control_play_left_blue.png') no-repeat 8px center;
3261 3273 }
3262 3274 .NB-module .NB-module-previous-page:link {
3263   - background: transparent url('../img/icons/silk/control_play_left.png') no-repeat center center;
  3275 + background: transparent url('../img/icons/silk/control_play_left.png') no-repeat 8px center;
3264 3276 }
3265 3277 .NB-module .NB-module-previous-page:hover {
3266   - background: transparent url('../img/icons/silk/control_play_left_blue.png') no-repeat center center;
  3278 + background: transparent url('../img/icons/silk/control_play_left_blue.png') no-repeat 8px center;
3267 3279 }
3268 3280 .NB-module .NB-module-previous-page.NB-disabled:hover {
3269   - background: transparent url('../img/icons/silk/control_play_left.png') no-repeat center center;
  3281 + background: transparent url('../img/icons/silk/control_play_left.png') no-repeat 8px center;
3270 3282 cursor: default;
3271 3283 }
3272 3284
@@ -3551,9 +3563,8 @@ background: transparent;
3551 3563 /* ================== */
3552 3564
3553 3565 .NB-modules-center {
3554   - margin-left: 284px;
3555   - margin-right: 478px;
3556   - padding: 24px;
  3566 + margin: 55px 478px 0 284px;
  3567 + padding: 24px;
3557 3568 }
3558 3569
3559 3570 /* ============================ */
4 media/js/newsblur/assetmodel.js
@@ -656,6 +656,10 @@ NEWSBLUR.AssetModel.Reader.prototype = {
656 656 this.make_request('/reader/load_features', {'page': page}, callback);
657 657 },
658 658
  659 + load_recommended_feed: function(page, callback) {
  660 + this.make_request('/recommendations/load_recommended_feed', {'page': page}, callback);
  661 + },
  662 +
659 663 save_feed_order: function(folders, callback) {
660 664 this.make_request('/reader/save_feed_order', {'folders': $.toJSON(folders)}, callback);
661 665 },
49 media/js/newsblur/reader.js
@@ -43,7 +43,8 @@
43 43 'feature_page': 0,
44 44 'unfetched_feeds': 0,
45 45 'fetched_feeds': 0,
46   - 'page_fill_outs': 0
  46 + 'page_fill_outs': 0,
  47 + 'recommended_feed_page': 0
47 48 };
48 49 this.cache = {
49 50 'iframe_stories': {},
@@ -138,6 +139,10 @@
138 139 closable: false,
139 140 fxName: "scale",
140 141 fxSettings: { duration: 500, easing: "easeInOutQuint" },
  142 + north__paneSelector: ".left-north",
  143 + north__size: 18,
  144 + north__resizeable: false,
  145 + north__spacing_open: 0,
141 146 center__paneSelector: ".left-center",
142 147 center__resizable: false,
143 148 south__paneSelector: ".left-south",
@@ -3246,7 +3251,7 @@
3246 3251 $.make('div', { className: 'NB-feed-story-premium-only-divider'}),
3247 3252 $.make('div', { className: 'NB-feed-story-premium-only-text'}, [
3248 3253 'The full River of News is a ',
3249   - $.make('a', { href: '#' }, 'premium feature'),
  3254 + $.make('a', { href: '#', className: 'NB-splash-link' }, 'premium feature'),
3250 3255 '.'
3251 3256 ])
3252 3257 ]);
@@ -4122,10 +4127,10 @@
4122 4127
4123 4128 if (NEWSBLUR.Preferences['hide_read_feeds'] == 1) {
4124 4129 $hidereadfeeds_button.attr('title', 'Show all sites');
4125   - $feed_list.parent().addClass('NB-feedlist-hide-read-feeds');
  4130 + this.$s.$body.addClass('NB-feedlist-hide-read-feeds');
4126 4131 } else {
4127 4132 $hidereadfeeds_button.attr('title', 'Show only unread stories');
4128   - $feed_list.parent().removeClass('NB-feedlist-hide-read-feeds');
  4133 + this.$s.$body.removeClass('NB-feedlist-hide-read-feeds');
4129 4134 }
4130 4135 $hidereadfeeds_button.tipsy({
4131 4136 gravity: 'n',
@@ -4562,24 +4567,19 @@
4562 4567 var $next = $('.NB-module-features .NB-module-next-page');
4563 4568 var $previous = $('.NB-module-features .NB-module-previous-page');
4564 4569
4565   - $module.removeClass('NB-loaded');
4566   - _.delay(function() {
4567   - if (!$module.hasClass('NB-loaded')) {
4568   - $module.addClass('NB-loading');
4569   - }
4570   - }, 50);
  4570 + $module.addClass('NB-loading');
4571 4571
4572 4572 if (direction == -1 && !this.counts['feature_page']) {
4573   - $module.addClass('NB-loaded');
  4573 + $module.removeClass('NB-loading');
4574 4574 return;
4575 4575 }
4576 4576 if (direction == 1 && this.flags['features_last_page']) {
4577   - $module.addClass('NB-loaded');
  4577 + $module.removeClass('NB-loading');
4578 4578 return;
4579 4579 }
4580 4580
4581 4581 this.model.get_features_page(this.counts['feature_page']+direction, function(features) {
4582   - $('.NB-module-features').addClass('NB-loaded').removeClass('NB-loading');
  4582 + $module.removeClass('NB-loading');
4583 4583 self.counts['feature_page'] += direction;
4584 4584
4585 4585 var $table = $.make('table', { cellSpacing: 0, cellPadding: 0 });
@@ -4796,12 +4796,19 @@
4796 4796 this.open_add_feed_modal({url: feed.feed_address});
4797 4797 },
4798 4798
4799   - load_next_feed_in_recommended_feeds: function() {
4800   -
4801   - },
4802   -
4803   - load_previous_feed_in_recommended_feeds: function() {
  4799 + load_recommended_feed: function(direction) {
  4800 + var self = this;
  4801 + var $module = $('.NB-module-recommended');
  4802 + $module.addClass('NB-loading');
  4803 + direction = direction || 0;
4804 4804
  4805 + this.model.load_recommended_feed(this.counts['recommended_feed_page']+direction, function(resp) {
  4806 + self.counts['recommended_feed_page'] += direction;
  4807 +
  4808 + $module.removeClass('NB-loading');
  4809 + $module.replaceWith(resp);
  4810 + self.load_javascript_elements_on_page();
  4811 + });
4805 4812 },
4806 4813
4807 4814 // ==========
@@ -5234,13 +5241,15 @@
5234 5241
5235 5242 $.targetIs(e, { tagSelector: '.NB-module-recommended .NB-module-next-page' }, function($t, $p){
5236 5243 e.preventDefault();
5237   - self.load_next_feed_in_recommended_feeds();
  5244 + if (!$t.hasClass('NB-disabled')) {
  5245 + self.load_recommended_feed(1);
  5246 + }
5238 5247 });
5239 5248
5240 5249 $.targetIs(e, { tagSelector: '.NB-module-recommended .NB-module-previous-page' }, function($t, $p){
5241 5250 e.preventDefault();
5242 5251 if (!$t.hasClass('NB-disabled')) {
5243   - self.load_previous_feed_in_recommended_feeds();
  5252 + self.load_recommended_feed(-1);
5244 5253 }
5245 5254 });
5246 5255
2  media/js/newsblur/reader_add_feed.js
@@ -250,6 +250,7 @@ NEWSBLUR.ReaderAddFeed.prototype = {
250 250 {
251 251 $loading.removeClass('NB-active');
252 252 NEWSBLUR.reader.load_feeds();
  253 + NEWSBLUR.reader.load_recommended_feed();
253 254 $.modal.close();
254 255 },
255 256 error: function (data, status, e)
@@ -303,6 +304,7 @@ NEWSBLUR.ReaderAddFeed.prototype = {
303 304
304 305 if (data.code > 0) {
305 306 NEWSBLUR.reader.load_feeds();
  307 + NEWSBLUR.reader.load_recommended_feed();
306 308 NEWSBLUR.reader.handle_mouse_indicator_hover();
307 309 $.modal.close();
308 310 } else {
56 templates/base.html
@@ -9,41 +9,41 @@
9 9 <script type="text/javascript" charset="utf-8">
10 10 var NEWSBLUR = {};
11 11 NEWSBLUR.Globals = {
12   - 'is_authenticated': {{ user.is_authenticated|yesno:"true,false" }},
13   - 'is_anonymous': {{ user.is_anonymous|yesno:"true,false" }},
14   - 'is_premium': {{ user.profile.is_premium|yesno:"true,false" }},
15   - 'secret_token': "{{ user.profile.secret_token }}",
16   - 'username': "{{ user.username|safe }}",
17   - 'google_favicon_url': 'http://www.google.com/s2/favicons?domain_url=',
18   - 'MEDIA_URL': "{{ MEDIA_URL }}"
  12 + 'is_authenticated' : {{ user.is_authenticated|yesno:"true,false" }},
  13 + 'is_anonymous' : {{ user.is_anonymous|yesno:"true,false" }},
  14 + 'is_premium' : {{ user.profile.is_premium|yesno:"true,false" }},
  15 + 'secret_token' : "{{ user.profile.secret_token }}",
  16 + 'username' : "{{ user.username|safe }}",
  17 + 'google_favicon_url' : 'http://www.google.com/s2/favicons?domain_url=',
  18 + 'MEDIA_URL' : "{{ MEDIA_URL }}"
19 19 };
20 20 NEWSBLUR.Flags = {
21 21 'start_import_from_google_reader': {{ start_import_from_google_reader|yesno:"true,false" }}
22 22 };
23 23 NEWSBLUR.Preferences = {
24   - 'unread_view': 0,
25   - 'lock_mouse_indicator': 0,
26   - 'feed_pane_size': 240,
27   - 'story_titles_pane_size': 168,
28   - 'new_window': 1,
29   - 'default_view': 'page',
30   - 'hide_read_feeds': 0,
31   - 'feed_view_single_story': 0,
32   - 'view_settings': {},
33   - 'collapsed_folders': [],
34   - 'story_styling': 'sans-serif',
35   - 'timezone': "{{ user_profile.timezone }}",
36   - 'story_share_twitter': true,
37   - 'story_share_facebook': true,
38   - 'story_share_readitlater': false,
39   - 'story_share_instapaper': true,
40   - 'story_share_readability': true
  24 + 'unread_view' : 0,
  25 + 'lock_mouse_indicator' : 0,
  26 + 'feed_pane_size' : {{ user_profile.feed_pane_size }},
  27 + 'story_titles_pane_size' : 168,
  28 + 'new_window' : 1,
  29 + 'default_view' : 'page',
  30 + 'hide_read_feeds' : 0,
  31 + 'feed_view_single_story' : 0,
  32 + 'view_settings' : {},
  33 + 'collapsed_folders' : [],
  34 + 'story_styling' : 'sans-serif',
  35 + 'timezone' : "{{ user_profile.timezone }}",
  36 + 'story_share_twitter' : true,
  37 + 'story_share_facebook' : true,
  38 + 'story_share_readitlater' : false,
  39 + 'story_share_instapaper' : true,
  40 + 'story_share_readability' : true
41 41 };
42 42 NEWSBLUR.URLs = {
43   - 'google-reader-authorize': "{% url google-reader-authorize %}",
44   - 'opml-upload': "{% url opml-upload %}",
45   - 'opml-export': "{% url opml-export %}",
46   - 'domain': "{% current_domain %}"
  43 + 'google-reader-authorize' : "{% url google-reader-authorize %}",
  44 + 'opml-upload' : "{% url opml-upload %}",
  45 + 'opml-export' : "{% url opml-export %}",
  46 + 'domain' : "{% current_domain %}"
47 47 };
48 48 </script>
49 49
27 templates/reader/feeds.xhtml
@@ -26,7 +26,7 @@ $(document).ready(function() {
26 26 </ul>
27 27 </div>
28 28
29   - <div class="NB-modules-center">
  29 + <div class="NB-modules-center" style="margin-left: {{ user.profile.feed_pane_size }}px">
30 30 {% if recommended_feed %}
31 31 {% render_recommended_feed recommended_feed %}
32 32 {% endif %}
@@ -329,23 +329,26 @@ $(document).ready(function() {
329 329
330 330
331 331 <div class="left-pane">
  332 +
  333 + <div class="left-north">
  334 + <div class="NB-feeds-header">
  335 + <div class="NB-feeds-header-right">
  336 + <div class="NB-feeds-header-sites">&nbsp;</div>
  337 + </div>
  338 + <div class="NB-feeds-header-left">
  339 + <span class="NB-feeds-header-count NB-feeds-header-negative NB-empty">0</span>
  340 + <span class="NB-feeds-header-count NB-feeds-header-neutral NB-empty">0</span>
  341 + <span class="NB-feeds-header-count NB-feeds-header-positive NB-empty">0</span>
  342 + </div>
  343 + <div class="NB-feeds-header-home">Dashboard</div>
  344 + </div>
  345 + </div>
332 346
333 347 <div class="left-center">
334 348
335 349 <div class="left-center-content NB-feedlist">
336 350 <div id="NB-feeds-list-loader">Everything is on its way...</div>
337 351 <div class="NB-feeds-header-container">
338   - <div class="NB-feeds-header">
339   - <div class="NB-feeds-header-right">
340   - <div class="NB-feeds-header-sites">&nbsp;</div>
341   - </div>
342   - <div class="NB-feeds-header-left">
343   - <span class="NB-feeds-header-count NB-feeds-header-negative NB-empty">0</span>
344   - <span class="NB-feeds-header-count NB-feeds-header-neutral NB-empty">0</span>
345   - <span class="NB-feeds-header-count NB-feeds-header-positive NB-empty">0</span>
346   - </div>
347   - <div class="NB-feeds-header-home">Dashboard</div>
348   - </div>
349 352 <div class="NB-feeds-header-river-container">
350 353 <div class="NB-feeds-header-river NB-empty">
351 354 <div class="NB-feeds-header-river-count unread_count"></div>
4 templates/recommendations/render_recommended_feed.xhtml
@@ -2,8 +2,8 @@
1  urls.py
@@ -10,6 +10,7 @@
10 10 (r'^profile/', include('apps.profile.urls')),
11 11 (r'^import/', include('apps.feed_import.urls')),
12 12 (r'^api/', include('apps.api.urls')),
  13 + (r'^recommendations/', include('apps.recommendations.urls')),
13 14 )
14 15
15 16 if settings.DEVELOPMENT:

0 comments on commit 4ab3904

Please sign in to comment.
Something went wrong with that request. Please try again.