mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
Adding moderation queue to recommended feeds (finally!)
This commit is contained in:
parent
8d46754c99
commit
ae7f79b3a0
14 changed files with 189 additions and 6822 deletions
|
@ -63,6 +63,7 @@ def index(request):
|
|||
active_count = UserSubscription.objects.filter(user=request.user, active=True).count() if authed else 0
|
||||
train_count = UserSubscription.objects.filter(user=request.user, active=True, is_trained=False, feed__stories_last_month__gte=1).count() if authed else 0
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=True, approved_date__lte=datetime.datetime.now()).select_related('feed')[:2]
|
||||
unmoderated_feeds = RecommendedFeed.objects.filter(is_public=False, declined_date__isnull=True).select_related('feed')[:2]
|
||||
statistics = MStatistics.all()
|
||||
feedbacks = MFeedback.all()
|
||||
|
||||
|
@ -77,6 +78,7 @@ def index(request):
|
|||
'train_count' : active_count - train_count,
|
||||
'account_images' : range(1, 4),
|
||||
'recommended_feeds' : recommended_feeds,
|
||||
'unmoderated_feeds' : unmoderated_feeds,
|
||||
'statistics' : statistics,
|
||||
'feedbacks' : feedbacks,
|
||||
'start_import_from_google_reader': request.session.get('import_from_google_reader', False),
|
||||
|
|
|
@ -7,7 +7,7 @@ from apps.rss_feeds.models import MFeedIcon
|
|||
register = template.Library()
|
||||
|
||||
@register.inclusion_tag('recommendations/render_recommended_feed.xhtml', takes_context=True)
|
||||
def render_recommended_feed(context, recommended_feeds):
|
||||
def render_recommended_feed(context, recommended_feeds, unmoderated=False):
|
||||
user = get_user(context['user'])
|
||||
|
||||
usersub = None
|
||||
|
@ -18,11 +18,12 @@ def render_recommended_feed(context, recommended_feeds):
|
|||
|
||||
if recommended_feed:
|
||||
return {
|
||||
'recommended_feed': recommended_feed,
|
||||
'description': recommended_feed.description or recommended_feed.feed.data.feed_tagline,
|
||||
'usersub': usersub,
|
||||
'feed_icon': feed_icon and feed_icon[0],
|
||||
'user': context['user'],
|
||||
'has_next_page': len(recommended_feeds) > 1
|
||||
'recommended_feed' : recommended_feed,
|
||||
'description' : recommended_feed.description or recommended_feed.feed.data.feed_tagline,
|
||||
'usersub' : usersub,
|
||||
'feed_icon' : feed_icon and feed_icon[0],
|
||||
'user' : context['user'],
|
||||
'has_next_page' : len(recommended_feeds) > 1,
|
||||
'unmoderated' : unmoderated
|
||||
}
|
||||
|
|
@ -4,5 +4,7 @@ from apps.recommendations import views
|
|||
urlpatterns = patterns('',
|
||||
url(r'^load_recommended_feed', views.load_recommended_feed, name='load-recommended-feed'),
|
||||
url(r'^save_recommended_feed', views.save_recommended_feed, name='save-recommended-feed'),
|
||||
url(r'^approve_feed', views.approve_feed, name='approve-recommended-feed'),
|
||||
url(r'^decline_feed', views.decline_feed, name='decline-recommended-feed'),
|
||||
url(r'^load_feed_info/(?P<feed_id>\d+)', views.load_feed_info, name='load-recommended-feed-info'),
|
||||
)
|
||||
|
|
|
@ -7,17 +7,21 @@ from apps.recommendations.models import RecommendedFeed
|
|||
from apps.reader.models import UserSubscription
|
||||
from apps.rss_feeds.models import Feed, MFeedIcon
|
||||
from utils import json_functions as json
|
||||
from utils.user_functions import get_user, ajax_login_required
|
||||
from utils.user_functions import get_user, ajax_login_required, admin_only
|
||||
|
||||
|
||||
def load_recommended_feed(request):
|
||||
user = get_user(request)
|
||||
page = int(request.REQUEST.get('page', 0))
|
||||
usersub = None
|
||||
refresh = request.REQUEST.get('refresh')
|
||||
now = datetime.datetime.now
|
||||
user = get_user(request)
|
||||
page = int(request.REQUEST.get('page', 0))
|
||||
usersub = None
|
||||
refresh = request.REQUEST.get('refresh')
|
||||
now = datetime.datetime.now
|
||||
unmoderated = request.REQUEST.get('unmoderated', False) == 'true'
|
||||
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=True, approved_date__lte=now)[page:page+2]
|
||||
if unmoderated:
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=False, declined_date__isnull=True)[page:page+2]
|
||||
else:
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=True, approved_date__lte=now)[page:page+2]
|
||||
if recommended_feeds and request.user.is_authenticated():
|
||||
usersub = UserSubscription.objects.filter(user=user, feed=recommended_feeds[0].feed)
|
||||
if refresh != 'true' and page > 0:
|
||||
|
@ -34,6 +38,7 @@ def load_recommended_feed(request):
|
|||
'feed_icon' : feed_icon and feed_icon[0],
|
||||
'has_next_page' : len(recommended_feeds) > 1,
|
||||
'has_previous_page' : page != 0,
|
||||
'unmoderated' : unmoderated,
|
||||
}, context_instance=RequestContext(request))
|
||||
else:
|
||||
return HttpResponse("")
|
||||
|
@ -71,4 +76,31 @@ def save_recommended_feed(request):
|
|||
)
|
||||
)
|
||||
|
||||
return dict(code=code if created else -1)
|
||||
return dict(code=code if created else -1)
|
||||
|
||||
@admin_only
|
||||
@ajax_login_required
|
||||
def approve_feed(request):
|
||||
feed_id = request.POST['feed_id']
|
||||
feed = get_object_or_404(Feed, pk=int(feed_id))
|
||||
recommended_feed = RecommendedFeed.objects.filter(feed=feed)[0]
|
||||
|
||||
recommended_feed.is_public = True
|
||||
recommended_feed.approved_date = datetime.datetime.now()
|
||||
recommended_feed.save()
|
||||
|
||||
return load_recommended_feed(request)
|
||||
|
||||
@admin_only
|
||||
@ajax_login_required
|
||||
def decline_feed(request):
|
||||
feed_id = request.POST['feed_id']
|
||||
feed = get_object_or_404(Feed, pk=int(feed_id))
|
||||
recommended_feeds = RecommendedFeed.objects.filter(feed=feed)
|
||||
|
||||
for recommended_feed in recommended_feeds:
|
||||
recommended_feed.is_public = False
|
||||
recommended_feed.declined_date = datetime.datetime.now()
|
||||
recommended_feed.save()
|
||||
|
||||
return load_recommended_feed(request)
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,9 @@
|
|||
/* ========== */
|
||||
/* = Global = */
|
||||
/* ========== */
|
||||
|
||||
body {
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
.NB-favicon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -49,7 +49,7 @@
|
|||
|
||||
load_feeds: function() {
|
||||
this.flags.active_view = 'feeds';
|
||||
$.mobile.pageLoading();
|
||||
$.mobile.showPageLoadingMsg();
|
||||
|
||||
this.pages.feeds.unbind('pagebeforeshow').bind('pagebeforeshow', _.bind(function(e) {
|
||||
$('ul', this.$s.$feed_list).listview('refresh');
|
||||
|
@ -84,7 +84,7 @@
|
|||
this.flags.feeds_loaded = true;
|
||||
$feed_list.html($feeds);
|
||||
$('ul', $feed_list).listview();
|
||||
$.mobile.pageLoading(true);
|
||||
$.mobile.hidePageLoadingMsg();
|
||||
},
|
||||
|
||||
make_feed_title: function(feed_id) {
|
||||
|
@ -135,7 +135,7 @@
|
|||
|
||||
load_stories: function(feed_id) {
|
||||
this.flags.active_view = 'stories';
|
||||
$.mobile.pageLoading();
|
||||
$.mobile.showPageLoadingMsg();
|
||||
this.active_feed = feed_id;
|
||||
this.model.load_feed(feed_id, this.page, this.page == 1, _.bind(this.build_stories, this));
|
||||
},
|
||||
|
@ -163,7 +163,7 @@
|
|||
}
|
||||
|
||||
$('ul', $story_list).listview();
|
||||
$.mobile.pageLoading(true);
|
||||
$.mobile.hidePageLoadingMsg();
|
||||
},
|
||||
|
||||
load_next_page_of_stories: function() {
|
||||
|
@ -219,7 +219,7 @@
|
|||
|
||||
load_story_detail: function(story_id) {
|
||||
this.flags.active_view = 'story_detail';
|
||||
$.mobile.pageLoading();
|
||||
$.mobile.showPageLoadingMsg();
|
||||
|
||||
var $story_detail_view = this.$s.$story_detail;
|
||||
var story = this.model.get_story(story_id);
|
||||
|
@ -229,7 +229,7 @@
|
|||
this.colorize_story_title(story);
|
||||
$('.ul-li-right', this.pages.story).jqmData('icon', 'NB-'+score_color);
|
||||
$story_detail_view.html($story);
|
||||
$.mobile.pageLoading(true);
|
||||
$.mobile.hidePageLoadingMsg();
|
||||
this.mark_story_as_read(story);
|
||||
},
|
||||
|
||||
|
@ -301,12 +301,16 @@
|
|||
},
|
||||
|
||||
mark_story_as_read: function(story) {
|
||||
var story_id = story.id;
|
||||
var feed_id = story.story_feed_id;
|
||||
var story_id = story.id;
|
||||
var feed_id = story.story_feed_id;
|
||||
|
||||
this.model.mark_story_as_read(story_id, feed_id, _.bind(function(read) {
|
||||
this.update_read_count(story_id, feed_id, false, read);
|
||||
}, this));
|
||||
this.model.mark_story_as_read(story_id, feed_id, _.bind(function(read) {
|
||||
this.update_read_count(story_id, feed_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
update_read_count: function(story_id, feed_id) {
|
||||
|
||||
},
|
||||
|
||||
// ==========
|
||||
|
@ -319,7 +323,7 @@
|
|||
this.$s.$feed_list.delegate('li a', 'tap', function(e) {
|
||||
e.preventDefault();
|
||||
var feed_id = $(e.currentTarget).jqmData('feed-id');
|
||||
$.mobile.changePage('stories');
|
||||
$.mobile.changePage(self.pages.stories);
|
||||
self.reset_feed();
|
||||
self.load_stories(feed_id);
|
||||
});
|
||||
|
@ -327,16 +331,16 @@
|
|||
this.$s.$story_list.delegate('li a', 'tap', function(e) {
|
||||
e.preventDefault();
|
||||
var story_id = $(e.currentTarget).jqmData('story-id');
|
||||
$.mobile.pageLoading();
|
||||
$.mobile.changePage('story');
|
||||
$.mobile.showPageLoadingMsg();
|
||||
$.mobile.changePage(self.pages.story);
|
||||
self.load_story_detail(story_id);
|
||||
});
|
||||
|
||||
this.$s.$story_detail.delegate('li a', 'tap', function(e) {
|
||||
e.preventDefault();
|
||||
var story_id = $(e.currentTarget).jqmData('story-id');
|
||||
$.mobile.pageLoading();
|
||||
$.mobile.changePage('story');
|
||||
$.mobile.showPageLoadingMsg();
|
||||
$.mobile.changePage(self.pages.story);
|
||||
self.load_story_detail(story_id);
|
||||
});
|
||||
|
||||
|
|
|
@ -725,13 +725,28 @@ NEWSBLUR.AssetModel.Reader.prototype = {
|
|||
this.make_request('/reader/features', {'page': page}, callback, callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
load_recommended_feed: function(page, refresh, callback, error_callback) {
|
||||
load_recommended_feed: function(page, refresh, unmoderated, callback, error_callback) {
|
||||
this.make_request('/recommendations/load_recommended_feed', {
|
||||
'page': page,
|
||||
'refresh': refresh
|
||||
'page' : page,
|
||||
'refresh' : refresh,
|
||||
'unmoderated' : unmoderated
|
||||
}, callback, error_callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
approve_feed_in_moderation_queue: function(feed_id, callback) {
|
||||
this.make_request('/recommendations/approve_feed', {
|
||||
'feed_id' : feed_id,
|
||||
'unmoderated' : true
|
||||
}, callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
decline_feed_in_moderation_queue: function(feed_id, callback) {
|
||||
this.make_request('/recommendations/decline_feed', {
|
||||
'feed_id' : feed_id,
|
||||
'unmoderated' : true
|
||||
}, callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
load_dashboard_graphs: function(callback, error_callback) {
|
||||
this.make_request('/statistics/dashboard_graphs', {}, callback, error_callback, {request_type: 'GET'});
|
||||
},
|
||||
|
|
|
@ -5042,13 +5042,43 @@
|
|||
this.open_add_feed_modal({url: feed_address});
|
||||
},
|
||||
|
||||
load_recommended_feed: function(direction, refresh) {
|
||||
approve_feed_in_moderation_queue: function(feed_id) {
|
||||
var self = this;
|
||||
var $module = $('.NB-module-recommended');
|
||||
var $module = $('.NB-module-recommended.NB-recommended-unmoderated');
|
||||
$module.addClass('NB-loading');
|
||||
|
||||
this.model.approve_feed_in_moderation_queue(feed_id, function(resp) {
|
||||
if (!resp) return;
|
||||
$module.removeClass('NB-loading');
|
||||
$module.replaceWith(resp);
|
||||
self.load_javascript_elements_on_page();
|
||||
});
|
||||
},
|
||||
|
||||
decline_feed_in_moderation_queue: function(feed_id) {
|
||||
var self = this;
|
||||
var $module = $('.NB-module-recommended.NB-recommended-unmoderated');
|
||||
$module.addClass('NB-loading');
|
||||
|
||||
this.model.decline_feed_in_moderation_queue(feed_id, function(resp) {
|
||||
if (!resp) return;
|
||||
$module.removeClass('NB-loading');
|
||||
$module.replaceWith(resp);
|
||||
self.load_javascript_elements_on_page();
|
||||
});
|
||||
},
|
||||
|
||||
load_recommended_feed: function(direction, refresh, unmoderated) {
|
||||
var self = this;
|
||||
var $module = unmoderated ?
|
||||
$('.NB-module-recommended.NB-recommended-unmoderated') :
|
||||
$('.NB-module-recommended:not(.NB-recommended-unmoderated)');
|
||||
|
||||
$module.addClass('NB-loading');
|
||||
direction = direction || 0;
|
||||
|
||||
this.model.load_recommended_feed(this.counts['recommended_feed_page']+direction, !!refresh, function(resp) {
|
||||
this.model.load_recommended_feed(this.counts['recommended_feed_page']+direction,
|
||||
!!refresh, unmoderated, function(resp) {
|
||||
if (!resp) return;
|
||||
self.counts['recommended_feed_page'] += direction;
|
||||
|
||||
|
@ -5561,17 +5591,33 @@
|
|||
});
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-recommended-decline' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var feed_id = $t.closest('.NB-recommended').attr('data-feed-id');
|
||||
self.decline_feed_in_moderation_queue(feed_id);
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-recommended-approve' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var feed_id = $t.closest('.NB-recommended').attr('data-feed-id');
|
||||
self.approve_feed_in_moderation_queue(feed_id);
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-module-recommended .NB-module-next-page' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
if (!$t.hasClass('NB-disabled')) {
|
||||
self.load_recommended_feed(1);
|
||||
console.log(['parent', $t.closest('.NB-module-recommended'), $t.closest('.NB-module-recommended').hasClass('NB-recommended-unmoderated')]);
|
||||
var unmoderated = $t.closest('.NB-module-recommended').hasClass('NB-recommended-unmoderated');
|
||||
self.load_recommended_feed(1, false, unmoderated);
|
||||
}
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-module-recommended .NB-module-previous-page' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
if (!$t.hasClass('NB-disabled')) {
|
||||
self.load_recommended_feed(-1);
|
||||
var unmoderated = $t.closest('.NB-module-recommended').hasClass('NB-recommended-unmoderated');
|
||||
console.log(['parent', $t.closest('.NB-module-recommended')]);
|
||||
self.load_recommended_feed(-1, false, unmoderated);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ COMPRESS_JS = {
|
|||
'mobile': {
|
||||
'source_filenames': (
|
||||
'js/jquery-1.6.1.js',
|
||||
'js/mobile/jquery.mobile-1.0a4.js',
|
||||
'js/mobile/jquery.mobile-1.0b1.js',
|
||||
'js/jquery.ajaxmanager.3.js',
|
||||
'js/underscore.js',
|
||||
'js/inflector.js',
|
||||
|
@ -253,7 +253,7 @@ COMPRESS_CSS = {
|
|||
},
|
||||
'mobile': {
|
||||
'source_filenames': (
|
||||
'css/mobile/jquery.mobile-1.0a4.css',
|
||||
'css/mobile/jquery.mobile-1.0b1.css',
|
||||
'css/mobile/mobile.css',
|
||||
),
|
||||
'output_filename': 'css/mobile/mobile-compressed-?.css',
|
||||
|
|
|
@ -83,6 +83,11 @@ $(document).ready(function() {
|
|||
{% if recommended_feeds %}
|
||||
{% render_recommended_feed recommended_feeds %}
|
||||
{% endif %}
|
||||
|
||||
{% if user.is_staff and unmoderated_feeds %}
|
||||
{% render_recommended_feed unmoderated_feeds 1 %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<div class="NB-module-recommended NB-module">
|
||||
<div class="NB-module-recommended NB-module {% if unmoderated %}NB-recommended-unmoderated{% endif %}">
|
||||
<h5 class="NB-module-header">
|
||||
Recommended Site
|
||||
{% if unmoderated %}
|
||||
Moderation Queue
|
||||
{% else %}
|
||||
Recommended Site
|
||||
{% endif %}
|
||||
<div class="NB-module-header-right">
|
||||
{% if has_next_page or has_previous_page %}
|
||||
<a href="#" class="NB-module-direction NB-module-next-page NB-javascript {% if not has_next_page %}NB-disabled{% endif %}"></a>
|
||||
|
@ -8,9 +12,15 @@
|
|||
{% endif %}
|
||||
<div class="NB-spinner NB-left"></div>
|
||||
<div class="NB-module-recommended-date">
|
||||
{{ recommended_feed.approved_date|date:"M j" }}
|
||||
<span>{{ recommended_feed.approved_date|date:"S" }}</span>,
|
||||
{{ recommended_feed.approved_date|date:"Y" }}
|
||||
{% if unmoderated %}
|
||||
{{ recommended_feed.created_date|date:"M j" }}
|
||||
<span>{{ recommended_feed.created_date|date:"S" }}</span>,
|
||||
{{ recommended_feed.created_date|date:"Y" }}
|
||||
{% else %}
|
||||
{{ recommended_feed.approved_date|date:"M j" }}
|
||||
<span>{{ recommended_feed.approved_date|date:"S" }}</span>,
|
||||
{{ recommended_feed.approved_date|date:"Y" }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</h5>
|
||||
|
@ -34,6 +44,10 @@
|
|||
<div class="NB-recommended-try NB-modal-submit-green NB-modal-submit-button NB-javascript">Try</div>
|
||||
<div class="NB-recommended-add NB-modal-submit-close NB-modal-submit-button NB-javascript">Add</div>
|
||||
{% endif %}
|
||||
{% if unmoderated %}
|
||||
<div class="NB-recommended-approve NB-modal-submit-green NB-modal-submit-button NB-javascript">Approve</div>
|
||||
<div class="NB-recommended-decline NB-modal-submit-close NB-modal-submit-button NB-javascript">Decline</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -27,6 +27,25 @@ def ajax_login_required(function=None):
|
|||
else:
|
||||
return _dec(function)
|
||||
|
||||
def admin_only(function=None):
|
||||
def _dec(view_func):
|
||||
def _view(request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
return HttpResponseForbidden()
|
||||
else:
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
_view.__name__ = view_func.__name__
|
||||
_view.__dict__ = view_func.__dict__
|
||||
_view.__doc__ = view_func.__doc__
|
||||
|
||||
return _view
|
||||
|
||||
if function is None:
|
||||
return _dec
|
||||
else:
|
||||
return _dec(function)
|
||||
|
||||
def get_user(request):
|
||||
if not hasattr(request, 'user'):
|
||||
user = request
|
||||
|
|
Loading…
Add table
Reference in a new issue