mirror of
				https://github.com/samuelclay/NewsBlur.git
				synced 2025-11-01 09:09:51 +00:00 
			
		
		
		
	Story likes/dislike now in DB and respected in JS.
This commit is contained in:
		
							parent
							
								
									9f2d2018a5
								
							
						
					
					
						commit
						9ba207b987
					
				
					 6 changed files with 129 additions and 44 deletions
				
			
		| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
from apps.reader.models import UserSubscription, ReadStories, UserSubscriptionFolders
 | 
			
		||||
from apps.reader.models import UserSubscription, ReadStories, UserSubscriptionFolders, StoryOpinions
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
admin.site.register(UserSubscription)
 | 
			
		||||
admin.site.register(ReadStories)
 | 
			
		||||
admin.site.register(UserSubscriptionFolders)
 | 
			
		||||
admin.site.register(UserSubscriptionFolders)
 | 
			
		||||
admin.site.register(StoryOpinions)
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +97,21 @@ class ReadStories(models.Model):
 | 
			
		|||
        verbose_name = "read story"
 | 
			
		||||
        unique_together = ("user", "story")
 | 
			
		||||
        
 | 
			
		||||
class StoryOpinions(models.Model):
 | 
			
		||||
    user = models.ForeignKey(User)
 | 
			
		||||
    feed = models.ForeignKey(Feed)
 | 
			
		||||
    story = models.ForeignKey(Story)
 | 
			
		||||
    opinion = models.IntegerField(default=0)
 | 
			
		||||
    
 | 
			
		||||
    def __unicode__(self):
 | 
			
		||||
        return ("%s [%s]: %s - %s" %
 | 
			
		||||
                    (self.user.username, self.feed.feed_title, self.story.story_title, self.opinion))
 | 
			
		||||
        
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name_plural = "opinions"
 | 
			
		||||
        verbose_name = "opinion"
 | 
			
		||||
        unique_together = ("user", "story")
 | 
			
		||||
        
 | 
			
		||||
class UserSubscriptionFolders(models.Model):
 | 
			
		||||
    user = models.ForeignKey(User)
 | 
			
		||||
    user_sub = models.ForeignKey(UserSubscription)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@ urlpatterns = patterns('apps.reader.views',
 | 
			
		|||
    (r'^refresh_all_feeds', 'refresh_all_feeds'),
 | 
			
		||||
    (r'^refresh_feed', 'refresh_feed'),
 | 
			
		||||
    (r'^mark_story_as_read', 'mark_story_as_read'),
 | 
			
		||||
    (r'^mark_story_as_like', 'mark_story_as_like'),
 | 
			
		||||
    (r'^mark_story_as_dislike', 'mark_story_as_dislike'),
 | 
			
		||||
    (r'^mark_feed_as_read', 'mark_feed_as_read'),
 | 
			
		||||
    (r'^get_read_feed_items', 'get_read_feed_items'),
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ from django.shortcuts import render_to_response, get_list_or_404, get_object_or_
 | 
			
		|||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.template import RequestContext
 | 
			
		||||
from apps.rss_feeds.models import Feed, Story
 | 
			
		||||
from apps.reader.models import UserSubscription, ReadStories, UserSubscriptionFolders
 | 
			
		||||
from apps.reader.models import UserSubscription, ReadStories, UserSubscriptionFolders, StoryOpinions
 | 
			
		||||
from utils.json import json_encode
 | 
			
		||||
from utils.story_functions import format_story_link_date__short, format_story_link_date__long
 | 
			
		||||
from utils.user_functions import get_user
 | 
			
		||||
| 
						 | 
				
			
			@ -105,11 +105,15 @@ def load_single_feed(request):
 | 
			
		|||
    
 | 
			
		||||
    offset = int(request.REQUEST.get('offset', 0))
 | 
			
		||||
    limit = int(request.REQUEST.get('limit', 25))
 | 
			
		||||
    page = int(request.REQUEST.get('page', 0))
 | 
			
		||||
    if page:
 | 
			
		||||
        offset = limit * page
 | 
			
		||||
    feed_id = request.REQUEST['feed_id']
 | 
			
		||||
    stories=Story.objects.filter(story_feed=feed_id)[offset:offset+limit]
 | 
			
		||||
    feed = Feed.objects.get(id=feed_id)
 | 
			
		||||
    force_update = request.GET.get('force', False)
 | 
			
		||||
    
 | 
			
		||||
        
 | 
			
		||||
    if force_update:
 | 
			
		||||
        fetch_feeds(force_update, [feed])
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -122,12 +126,21 @@ def load_single_feed(request):
 | 
			
		|||
                user=user, 
 | 
			
		||||
                feed=feed
 | 
			
		||||
            )
 | 
			
		||||
            story_opinions = StoryOpinions.objects.filter(
 | 
			
		||||
                user=user,
 | 
			
		||||
                feed=feed
 | 
			
		||||
            )
 | 
			
		||||
            for story in stories:
 | 
			
		||||
                story.short_parsed_date = format_story_link_date__short(story.story_date)
 | 
			
		||||
                story.long_parsed_date = format_story_link_date__long(story.story_date)
 | 
			
		||||
                story.story_feed_title = feed.feed_title
 | 
			
		||||
                story.story_feed_link = mark_safe(feed.feed_link)
 | 
			
		||||
                story.story_permalink = mark_safe(story.story_permalink)
 | 
			
		||||
                if story in [o.story for o in story_opinions]:
 | 
			
		||||
                    for o in story_opinions:
 | 
			
		||||
                        if o.story == story:
 | 
			
		||||
                            story.opinion = o.opinion
 | 
			
		||||
                            break
 | 
			
		||||
                if story.story_date < sub.mark_read_date:
 | 
			
		||||
                    story.read_status = 1
 | 
			
		||||
                elif story.story_date > sub.last_read_date:
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +150,6 @@ def load_single_feed(request):
 | 
			
		|||
                        print "READ: "
 | 
			
		||||
                        story.read_status = 1
 | 
			
		||||
                    else: 
 | 
			
		||||
                        print "unread: "
 | 
			
		||||
                        story.read_status = 0
 | 
			
		||||
    
 | 
			
		||||
    context = stories
 | 
			
		||||
| 
						 | 
				
			
			@ -186,6 +198,35 @@ def mark_feed_as_read(request):
 | 
			
		|||
        data = json_encode(dict(code=1))
 | 
			
		||||
    return HttpResponse(data)
 | 
			
		||||
    
 | 
			
		||||
@login_required
 | 
			
		||||
def mark_story_as_like(request):
 | 
			
		||||
    return mark_story_with_opinion(request, 1)
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
def mark_story_as_dislike(request):
 | 
			
		||||
    return mark_story_with_opinion(request, -1)
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
def mark_story_with_opinion(request, opinion):
 | 
			
		||||
    story_id = request.REQUEST['story_id']
 | 
			
		||||
    story = Story.objects.select_related("story_feed").get(id=story_id)
 | 
			
		||||
    
 | 
			
		||||
    previous_opinion = StoryOpinions.objects.get(story=story, user=request.user, feed=story.story_feed)
 | 
			
		||||
    if previous_opinion and previous_opinion.opinion != opinion:
 | 
			
		||||
        previous_opinion.opinion = opinion
 | 
			
		||||
        data = json_encode(dict(code=0))
 | 
			
		||||
        previous_opinion.save()
 | 
			
		||||
        print "Changed Opinion: " + str(previous_opinion.opinion) + ' ' + str(opinion)    
 | 
			
		||||
    else:
 | 
			
		||||
        print "Marked Opinion: " + str(story_id) + ' ' + str(opinion)    
 | 
			
		||||
        m = StoryOpinions(story=story, user=request.user, feed=story.story_feed, opinion=opinion)
 | 
			
		||||
        data = json_encode(dict(code=0))
 | 
			
		||||
        try:
 | 
			
		||||
            m.save()
 | 
			
		||||
        except:
 | 
			
		||||
            data = json_encode(dict(code=2))
 | 
			
		||||
    return HttpResponse(data)
 | 
			
		||||
    
 | 
			
		||||
@login_required
 | 
			
		||||
def get_read_feed_items(request, username):
 | 
			
		||||
    feeds = get_list_or_404(Feed)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,17 +71,18 @@ NEWSBLUR.AssetModel.Reader.prototype = {
 | 
			
		|||
    
 | 
			
		||||
    mark_story_as_like: function(story_id, callback) {
 | 
			
		||||
        var self = this;
 | 
			
		||||
        var like = false;
 | 
			
		||||
        var opinion;
 | 
			
		||||
        
 | 
			
		||||
        for (s in this.stories) {
 | 
			
		||||
            if (this.stories[s].id == story_id) {
 | 
			
		||||
                like = this.stories[s].like;
 | 
			
		||||
                this.stories[s].like = 1;
 | 
			
		||||
                opinion = this.stories[s].opinion;
 | 
			
		||||
                this.stories[s].opinion = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (!like) {
 | 
			
		||||
        NEWSBLUR.log(['Like', opinion, this.stories[s].opinion]);
 | 
			
		||||
        if (opinion != 1) {
 | 
			
		||||
            this.make_request('/reader/mark_story_as_like',
 | 
			
		||||
                {
 | 
			
		||||
                    story_id: story_id
 | 
			
		||||
| 
						 | 
				
			
			@ -92,17 +93,17 @@ NEWSBLUR.AssetModel.Reader.prototype = {
 | 
			
		|||
    
 | 
			
		||||
    mark_story_as_dislike: function(story_id, callback) {
 | 
			
		||||
        var self = this;
 | 
			
		||||
        var dislike = false;
 | 
			
		||||
        var opinion;
 | 
			
		||||
        
 | 
			
		||||
        for (s in this.stories) {
 | 
			
		||||
            if (this.stories[s].id == story_id) {
 | 
			
		||||
                dislike = this.stories[s].dislike;
 | 
			
		||||
                this.stories[s].dislike = 1;
 | 
			
		||||
                opinion = this.stories[s].opinion;
 | 
			
		||||
                this.stories[s].opinion = -1;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (!dislike) {
 | 
			
		||||
        NEWSBLUR.log(['Dislike', opinion, this.stories[s].opinion]);
 | 
			
		||||
        if (opinion != -1) {
 | 
			
		||||
            this.make_request('/reader/mark_story_as_dislike',
 | 
			
		||||
                {
 | 
			
		||||
                    story_id: story_id
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +133,7 @@ NEWSBLUR.AssetModel.Reader.prototype = {
 | 
			
		|||
        this.make_request('/reader/load_feeds', {}, pre_callback);
 | 
			
		||||
    },
 | 
			
		||||
    
 | 
			
		||||
    load_feed: function(feed_id, callback) {
 | 
			
		||||
    load_feed: function(feed_id, page, callback) {
 | 
			
		||||
        var self = this;
 | 
			
		||||
        
 | 
			
		||||
        var pre_callback = function(stories) {
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +143,8 @@ NEWSBLUR.AssetModel.Reader.prototype = {
 | 
			
		|||
        
 | 
			
		||||
        this.make_request('/reader/load_single_feed',
 | 
			
		||||
            {
 | 
			
		||||
                feed_id: feed_id
 | 
			
		||||
                feed_id: feed_id,
 | 
			
		||||
                page: page
 | 
			
		||||
            }, pre_callback
 | 
			
		||||
        );
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
        this.$story_titles = $('#story_titles');
 | 
			
		||||
        this.$story_pane = $('#story_pane');
 | 
			
		||||
        this.$account_menu = $('.menu_button');
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        this.model = NEWSBLUR.AssetModel.reader();
 | 
			
		||||
        this.options = {};
 | 
			
		||||
        this.google_favicon_url = 'http://www.google.com/s2/favicons?domain_url=';
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,24 @@
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    NEWSBLUR.reader.prototype = {
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        // =================
 | 
			
		||||
        // = Node Creation =
 | 
			
		||||
        // =================
 | 
			
		||||
        
 | 
			
		||||
        make_story_title: function(story) {
 | 
			
		||||
            var read = story.read_status
 | 
			
		||||
                ? ' read'
 | 
			
		||||
                : '';
 | 
			
		||||
            var $story_title = $.make('div', { className: 'story' + read }, [
 | 
			
		||||
                $.make('a', { href: story.story_permalink, className: 'story_title' }, story.story_title),
 | 
			
		||||
                $.make('span', { className: 'story_date' }, story.short_parsed_date),
 | 
			
		||||
                $.make('span', { className: 'story_id' }, ''+story.id)
 | 
			
		||||
            ]);
 | 
			
		||||
            
 | 
			
		||||
            return $story_title;
 | 
			
		||||
        },
 | 
			
		||||
        
 | 
			
		||||
        // ========
 | 
			
		||||
        // = Page =
 | 
			
		||||
        // ========
 | 
			
		||||
| 
						 | 
				
			
			@ -242,31 +259,35 @@
 | 
			
		|||
            var self = this;
 | 
			
		||||
            var $story_titles = this.$story_titles;
 | 
			
		||||
            $story_titles.empty().scrollTop('0px');
 | 
			
		||||
            
 | 
			
		||||
            var callback = function() {
 | 
			
		||||
                var stories = self.model.stories;
 | 
			
		||||
                NEWSBLUR.log(['Sample story: ', stories[0]]);
 | 
			
		||||
                for (s in stories) {
 | 
			
		||||
                    var read = stories[s].read_status
 | 
			
		||||
                        ? ' read'
 | 
			
		||||
                        : '';
 | 
			
		||||
                    var $story_title = $.make('div', { className: 'story' + read }, [
 | 
			
		||||
                        $.make('a', { href: stories[s].story_permalink, className: 'story_title' }, stories[s].story_title),
 | 
			
		||||
                        $.make('span', { className: 'story_date' }, stories[s].short_parsed_date),
 | 
			
		||||
                        $.make('span', { className: 'story_id' }, ''+stories[s].id)
 | 
			
		||||
                    ]);
 | 
			
		||||
                    if (!stories[s].read_status) {
 | 
			
		||||
                        var $mark_read = $.make('a', { className: 'mark_story_as_read', href: '#'+stories[s].id }, '[Mark Read]');
 | 
			
		||||
                        $story_title.find('.title').append($mark_read);
 | 
			
		||||
                    }
 | 
			
		||||
                    $story_titles.append($story_title);
 | 
			
		||||
                }
 | 
			
		||||
                self.hover_over_story_titles($story_titles);
 | 
			
		||||
            };
 | 
			
		||||
            this.$story_titles.data('page', 0);
 | 
			
		||||
            this.$story_titles.data('feed_id', feed_id);
 | 
			
		||||
            
 | 
			
		||||
            this.show_feed_title_in_stories($story_titles, feed_id);
 | 
			
		||||
            this.mark_feed_as_selected(feed_id, $feed_link);
 | 
			
		||||
            this.model.load_feed(feed_id, callback);
 | 
			
		||||
            this.model.load_feed(feed_id, 0, $.rescope(this.create_story_titles, this));
 | 
			
		||||
        },
 | 
			
		||||
        
 | 
			
		||||
        create_story_titles: function() {
 | 
			
		||||
            var $story_titles = this.$story_titles;
 | 
			
		||||
            var stories = this.model.stories;
 | 
			
		||||
            NEWSBLUR.log(['Sample story: ', stories[0]]);
 | 
			
		||||
            for (s in stories) {
 | 
			
		||||
                var story = stories[s];
 | 
			
		||||
                var $story_title = this.make_story_title(story);
 | 
			
		||||
                if (!stories[s].read_status) {
 | 
			
		||||
                    var $mark_read = $.make('a', { className: 'mark_story_as_read', href: '#'+stories[s].id }, '[Mark Read]');
 | 
			
		||||
                    $story_title.find('.title').append($mark_read);
 | 
			
		||||
                }
 | 
			
		||||
                $story_titles.append($story_title);
 | 
			
		||||
            }
 | 
			
		||||
            this.hover_over_story_titles($story_titles);
 | 
			
		||||
        },
 | 
			
		||||
        
 | 
			
		||||
        load_page_of_feed_stories: function() {
 | 
			
		||||
            var feed_id = this.$story_titles.data('feed_id');
 | 
			
		||||
            var page = this.$story_titles.data('page');
 | 
			
		||||
            this.$story_titles.data('page', page+1);
 | 
			
		||||
            this.model.load_feed(feed_id, page+1, $.rescope(this.create_story_titles, this));
 | 
			
		||||
        },
 | 
			
		||||
        
 | 
			
		||||
        hover_over_story_titles: function($story_titles) {
 | 
			
		||||
| 
						 | 
				
			
			@ -507,7 +528,6 @@
 | 
			
		|||
            $.targetIs(e, { tagSelector: '#feed_list .feed' }, function($t, $p){
 | 
			
		||||
                e.preventDefault();
 | 
			
		||||
                NEWSBLUR.log(['Feed dblclick', $('.feed_id', $t), $t]);
 | 
			
		||||
                var feed_id = $('.feed_id', $t).text();
 | 
			
		||||
                self.open_feed_link(feed_id, $t);
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -515,10 +535,14 @@
 | 
			
		|||
        handle_scroll: function(elem, e) {
 | 
			
		||||
            var self = this;
 | 
			
		||||
            
 | 
			
		||||
                var full_height = $('#story_titles .story:last').offset().top + $('#story_titles .story:last').height();
 | 
			
		||||
                var visible_height = $('#story_titles').height();
 | 
			
		||||
                var scroll_y = $('#story_titles').scrollTop();
 | 
			
		||||
                NEWSBLUR.log(['Story_titles Scroll', full_height, visible_height, scroll_y]);
 | 
			
		||||
            var full_height = $('#story_titles .story:last').offset().top + $('#story_titles .story:last').height();
 | 
			
		||||
            var visible_height = $('#story_titles').height();
 | 
			
		||||
            // var scroll_y = $('#story_titles').scrollTop();
 | 
			
		||||
            // NEWSBLUR.log(['Story_titles Scroll', full_height, visible_height, scroll_y]);
 | 
			
		||||
            
 | 
			
		||||
            if (full_height <= visible_height) {
 | 
			
		||||
                this.load_page_of_feed_stories();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        
 | 
			
		||||
        // ==============
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue