Story likes/dislike now in DB and respected in JS.

This commit is contained in:
Samuel Clay 2009-07-05 21:45:46 +00:00
parent 9f2d2018a5
commit 9ba207b987
6 changed files with 129 additions and 44 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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'),
)

View file

@ -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)

View file

@ -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
);
},

View file

@ -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();
}
},
// ==============