From b2f94dc52c4330c1dd67be856a5221f8d93490b6 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Sun, 1 Jul 2012 20:51:34 -0700 Subject: [PATCH] Adding sharing and unsharing, with all the bells and whistle, directly to blurblogs. Still needs error handling, a view for unauthenticated users, and starring. --- apps/social/views.py | 48 ++++++-- assets.yml | 8 +- media/css/social/social_page.css | 3 +- media/js/newsblur/common/assetmodel.js | 3 +- media/js/newsblur/social_page/social_page.js | 1 + .../social_page/social_page_assets.js | 114 ++++++++++++++++++ .../newsblur/social_page/social_page_story.js | 26 +++- media/js/newsblur/views/story_share_view.js | 41 +++++-- templates/social/social_page.xhtml | 33 +++-- templates/social/story_share.xhtml | 75 ++++++------ 10 files changed, 275 insertions(+), 77 deletions(-) create mode 100644 media/js/newsblur/social_page/social_page_assets.js diff --git a/apps/social/views.py b/apps/social/views.py index 6a747033c..f3ffa7515 100644 --- a/apps/social/views.py +++ b/apps/social/views.py @@ -201,18 +201,21 @@ def load_social_page(request, user_id, username=None): check_all=True) for story in stories: - print user.pk, story['shared_by_friends'], story['shared_by_public'] if user.pk in story['shared_by_friends'] or user.pk in story['shared_by_public']: story['shared_by_user'] = True + shared_story = MSharedStory.objects.get(user_id=user.pk, + story_feed_id=story['story_feed_id'], + story_guid=story['id']) + story['user_comments'] = shared_story.comments stories = MSharedStory.attach_users_to_stories(stories, profiles) params = { - 'user': user, - 'social_user': social_user, - 'stories': stories, + 'social_user' : social_user, + 'stories' : stories, 'social_profile': social_profile.page(), - 'feeds': feeds, + 'feeds' : feeds, + 'user_profile' : hasattr(user, 'profile') and user.profile, } return params @@ -230,10 +233,10 @@ def story_public_comments(request): stories = Feed.format_stories(stories) stories, profiles = MSharedStory.stories_with_comments_and_profiles(stories, relative_user_id, check_all=True, - public=True, - attach_users=True) + public=True) if format == 'html': + stories = MSharedStory.attach_users_to_stories(stories, profiles) return render_to_response('social/story_comments.xhtml', { 'story': stories[0], }, context_instance=RequestContext(request)) @@ -244,7 +247,6 @@ def story_public_comments(request): }) @ajax_login_required -@json.json_view def mark_story_as_shared(request): code = 1 feed_id = int(request.POST['feed_id']) @@ -252,6 +254,7 @@ def mark_story_as_shared(request): comments = request.POST.get('comments', '') source_user_id = request.POST.get('source_user_id') post_to_services = request.POST.getlist('post_to_services') + format = request.REQUEST.get('format', 'json') story = MStory.objects(story_feed_id=feed_id, story_guid=story_id).limit(1).first() if not story: @@ -296,14 +299,24 @@ def mark_story_as_shared(request): for service in post_to_services: if service not in shared_story.posted_to_services: PostToService.delay(shared_story_id=shared_story.id, service=service) - - return {'code': code, 'story': story, 'user_profiles': profiles} + + if format == 'html': + stories = MSharedStory.attach_users_to_stories(stories, profiles) + return render_to_response('social/story_share.xhtml', { + 'story': story, + }, context_instance=RequestContext(request)) + else: + return json.json_response(request, { + 'code': code, + 'story': story, + 'user_profiles': profiles, + }) @ajax_login_required -@json.json_view def mark_story_as_unshared(request): feed_id = int(request.POST['feed_id']) story_id = request.POST['story_id'] + format = request.REQUEST.get('format', 'json') story = MStory.objects(story_feed_id=feed_id, story_guid=story_id).limit(1).first() if not story: @@ -332,7 +345,18 @@ def mark_story_as_unshared(request): check_all=True) story = stories[0] - return {'code': 1, 'message': "Story unshared.", 'story': story, 'user_profiles': profiles} + if format == 'html': + stories = MSharedStory.attach_users_to_stories(stories, profiles) + return render_to_response('social/story_share.xhtml', { + 'story': story, + }, context_instance=RequestContext(request)) + else: + return json.json_response(request, { + 'code': 1, + 'message': "Story unshared.", + 'story': story, + 'user_profiles': profiles, + }) @ajax_login_required @json.json_view diff --git a/assets.yml b/assets.yml index c0a8daadd..9e18a2254 100644 --- a/assets.yml +++ b/assets.yml @@ -27,7 +27,7 @@ javascripts: - media/js/vendor/jquery.easing.js - media/js/vendor/jquery.newsblur.js - media/js/vendor/jquery.scrollTo.js - - media/js/vendor/jquery.corners.js + # - media/js/vendor/jquery.corners.js - media/js/vendor/jquery.hotkeys.js - media/js/vendor/jquery.ajaxupload.js - media/js/vendor/jquery.ajaxmanager.3.js @@ -98,6 +98,11 @@ javascripts: - media/js/vendor/jquery.tipsy.js - media/js/vendor/inflector.js - media/js/newsblur/social_page/*.js + - media/js/newsblur/views/story_share_view.js + - media/js/vendor/jquery.easing.js + - media/js/vendor/jquery.newsblur.js + - media/js/vendor/jquery.scrollTo.js + - media/js/vendor/jquery.hotkeys.js stylesheets: common: @@ -116,3 +121,4 @@ stylesheets: blurblog: - media/css/jquery.tipsy.css - media/css/social/social_page.css + - media/css/modals.css diff --git a/media/css/social/social_page.css b/media/css/social/social_page.css index 0fda4a07b..32b2b5ccc 100644 --- a/media/css/social/social_page.css +++ b/media/css/social/social_page.css @@ -770,7 +770,8 @@ header { .NB-sideoption.NB-feed-story-train .NB-sideoption-icon { background-image: url('/media/embed/icons/silk/bricks.png'); } -.NB-sideoption.NB-feed-story-share .NB-sideoption-icon { +.NB-sideoption.NB-feed-story-share .NB-sideoption-icon, +.NB-sideoption.NB-feed-story-login .NB-sideoption-icon { background-image: url('/media/embed/icons/silk/rainbow.png'); } diff --git a/media/js/newsblur/common/assetmodel.js b/media/js/newsblur/common/assetmodel.js index a83df77e8..ee282e9a9 100644 --- a/media/js/newsblur/common/assetmodel.js +++ b/media/js/newsblur/common/assetmodel.js @@ -217,8 +217,7 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({ }, callback); }, - mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, post_to_services, - callback, error_callback) { + mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, post_to_services, callback, error_callback) { var pre_callback = _.bind(function(data) { if (data.user_profiles) { this.add_user_profiles(data.user_profiles); diff --git a/media/js/newsblur/social_page/social_page.js b/media/js/newsblur/social_page/social_page.js index c17f1da4d..2edc58313 100644 --- a/media/js/newsblur/social_page/social_page.js +++ b/media/js/newsblur/social_page/social_page.js @@ -3,6 +3,7 @@ NEWSBLUR.Views.SocialPage = Backbone.View.extend({ el: 'body', initialize: function() { + NEWSBLUR.assets = new NEWSBLUR.SocialPageAssets(); this.initialize_stories(); }, diff --git a/media/js/newsblur/social_page/social_page_assets.js b/media/js/newsblur/social_page/social_page_assets.js new file mode 100644 index 000000000..a12ed1bec --- /dev/null +++ b/media/js/newsblur/social_page/social_page_assets.js @@ -0,0 +1,114 @@ +NEWSBLUR.SocialPageAssets = Backbone.Router.extend({ + + initialize: function() { + this.social_services = { + twitter: {}, + facebook: {} + }; + }, + + make_request: function(url, data, callback, error_callback, options) { + var self = this; + var options = $.extend({ + 'traditional': true + }, options); + var request_type = options.request_type || 'GET'; + + $.ajax(_.extend({ + url: url, + data: data, + type: request_type, + cache: false, + cacheResponse: false, + beforeSend: function() { + $.isFunction(options['beforeSend']) && options['beforeSend'](); + return true; + }, + success: function(o) { + if (o && o.code < 0 && error_callback) { + error_callback(o); + } else if ($.isFunction(callback)) { + callback(o); + } + }, + error: function(e, textStatus, errorThrown) { + if (errorThrown == 'abort') { + return; + } + + if (error_callback) { + error_callback(); + } else if ($.isFunction(callback)) { + var message = "Please create an account. Not much to do without an account."; + if (NEWSBLUR.Globals.is_authenticated) { + message = "Sorry, there was an unhandled error."; + } + callback({'message': message}); + } + } + }, options)); + + }, + + preference: function(preference, value) { + if (typeof value == 'undefined') { + var pref = NEWSBLUR.Preferences[preference]; + if ((/\d+/).test(pref)) return parseInt(pref, 10); + return pref; + } + + NEWSBLUR.Preferences[preference] = value; + var preferences = {}; + preferences[preference] = value; + this.make_request('/profile/set_preference', preferences, callback, null); + }, + + mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, post_to_services, callback, error_callback) { + if (NEWSBLUR.Globals.is_authenticated) { + this.make_request('/social/share_story', { + story_id: story_id, + feed_id: feed_id, + comments: comments, + source_user_id: source_user_id, + post_to_services: post_to_services, + format: 'html' + }, callback, error_callback, { + request_type: 'POST' + }); + } else { + error_callback(); + } + }, + + mark_story_as_unshared: function(story_id, feed_id, callback, error_callback) { + if (NEWSBLUR.Globals.is_authenticated) { + this.make_request('/social/unshare_story', { + story_id: story_id, + feed_id: feed_id, + format: 'html' + }, callback, error_callback, { + request_type: 'POST' + }); + } else { + error_callback(); + } + }, + + save_comment_reply: function(story_id, story_feed_id, comment_user_id, reply_comments, original_message, callback, error_callback) { + var pre_callback = _.bind(function(data) { + if (data.user_profiles) { + this.add_user_profiles(data.user_profiles); + } + callback(data); + }, this); + + this.make_request('/social/save_comment_reply', { + story_id: story_id, + story_feed_id: story_feed_id, + comment_user_id: comment_user_id, + reply_comments: reply_comments, + original_message: original_message + }, pre_callback, error_callback); + } + +}); \ No newline at end of file diff --git a/media/js/newsblur/social_page/social_page_story.js b/media/js/newsblur/social_page/social_page_story.js index 8901304cf..ee61c70a7 100644 --- a/media/js/newsblur/social_page/social_page_story.js +++ b/media/js/newsblur/social_page/social_page_story.js @@ -1,12 +1,34 @@ NEWSBLUR.Views.SocialPageStory = Backbone.View.extend({ initialize: function() { + var story_id = this.$el.data("storyId"); + var feed_id = this.$el.data("feedId"); + var user_comments = this.$el.data("userComments"); + this.comments_view = new NEWSBLUR.Views.SocialPageComments({ el: this.$('.NB-story-comments'), - story_id: this.$el.data("storyId"), - feed_id: this.$el.data("feedId") + story_id: story_id, + feed_id: feed_id }); + var story = new Backbone.Model({ + story_feed_id: feed_id, + id: story_id, + shared_comments: user_comments, + shared: !!user_comments + }); + _.delay(_.bind(function() { + this.share_view = new NEWSBLUR.Views.StoryShareView({ + el: this.el, + model: story, + on_social_page: true + }); + this.$('.NB-feed-story-sideoptions-container').append($(this.share_view.template({ + story: story, + social_services: NEWSBLUR.assets.social_services + }))); + }, this), 50); + this.$('.NB-user-avatar').tipsy({ delayIn: 50, gravity: 's', diff --git a/media/js/newsblur/views/story_share_view.js b/media/js/newsblur/views/story_share_view.js index 6c2aa43aa..0d5809bb2 100644 --- a/media/js/newsblur/views/story_share_view.js +++ b/media/js/newsblur/views/story_share_view.js @@ -148,8 +148,12 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({ var $comments_sideoptions = this.$('.NB-sideoption-share-comments'); var $comments_menu = $('.NB-sideoption-share-comments', $share_menu); var comments = _.string.trim((options.source == 'menu' ? $comments_menu : $comments_sideoptions).val()); - var feed = NEWSBLUR.assets.get_feed(NEWSBLUR.reader.active_feed); - var source_user_id = feed && feed.get('user_id'); + if (this.options.on_social_page) { + var source_user_id = NEWSBLUR.Globals.blurblog_user_id; + } else { + var feed = NEWSBLUR.assets.get_feed(NEWSBLUR.reader.active_feed); + var source_user_id = feed && feed.get('user_id'); + } var post_to_services = _.compact([ NEWSBLUR.assets.preference('post_to_twitter') && 'twitter', NEWSBLUR.assets.preference('post_to_facebook') && 'facebook' @@ -161,7 +165,9 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({ this.post_share_error(data, true); }, this)); - NEWSBLUR.reader.blur_to_page(); + if (NEWSBLUR.reader) { + NEWSBLUR.reader.blur_to_page(); + } }, mark_story_as_unshared: function(options) { @@ -175,28 +181,35 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({ this.post_share_error(data, false); }, this)); - NEWSBLUR.reader.blur_to_page(); + if (NEWSBLUR.reader) { + NEWSBLUR.reader.blur_to_page(); + } }, - post_share_story: function(shared) { + post_share_story: function(shared, data) { this.model.set("shared", shared); - - var $share_star = this.model.story_title_view.$('.NB-storytitles-share'); + + var $share_star = this.model.story_title_view && this.model.story_title_view.$('.NB-storytitles-share'); var $share_button = this.$('.NB-sideoption-share-save'); var $unshare_button = this.$('.NB-sideoption-share-unshare'); - var $share_sideoption = this.model.story_view.$('.NB-feed-story-share .NB-sideoption-title'); + var $share_sideoption = this.$('.NB-feed-story-share .NB-sideoption-title'); var $comments_sideoptions = this.$('.NB-sideoption-share-comments'); var shared_text = this.model.get('shared') ? 'Shared' : 'Unshared'; this.toggle_feed_story_share_dialog({'close': true}); - NEWSBLUR.reader.hide_confirm_story_share_menu_item(true); $share_button.removeClass('NB-saving').removeClass('NB-disabled').text('Share'); $unshare_button.removeClass('NB-saving').removeClass('NB-disabled').text('Delete Share'); $share_sideoption.text(shared_text).closest('.NB-sideoption'); - this.model.story_view.$el.toggleClass('NB-story-shared', this.model.get('shared')); - this.model.story_view.render_comments(); - if (this.model.get('shared')) { + if (this.options.on_social_page) { + this.$('.NB-story-comments').replaceWith(data); + } else { + this.model.story_view.$el.toggleClass('NB-story-shared', this.model.get('shared')); + this.model.story_view.render_comments(); + NEWSBLUR.reader.hide_confirm_story_share_menu_item(true); + } + + if (this.model.get('shared') && $share_star) { $share_star.attr({'title': shared_text + '!'}); $share_star.tipsy({ gravity: 'sw', @@ -216,7 +229,9 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({ }, 850); } - NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view(); + if (NEWSBLUR.app.story_list) { + NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view(); + } }, post_share_error: function(data, shared) { diff --git a/templates/social/social_page.xhtml b/templates/social/social_page.xhtml index 514394f42..3d14ec468 100644 --- a/templates/social/social_page.xhtml +++ b/templates/social/social_page.xhtml @@ -32,6 +32,7 @@ 'email' : "{{ user.email|safe }}", 'MEDIA_URL' : "{{ MEDIA_URL }}", }; + NEWSBLUR.Preferences = {}; NEWSBLUR.Models = {}; NEWSBLUR.Collections = {}; NEWSBLUR.Views = {}; @@ -125,21 +126,27 @@ -
+
{{ story.story_content|safe }} - {% if user.is_authenticated %}
-
-
 
-
{% if story.saved %}Saved{% else %}Save this story{% endif %}
-
-
-
 
-
{% if story.shared_by_user %}Shared{% else %}Post to Blurblog{% endif %}
-
+ {% if user.is_authenticated %} +
+
 
+
{% if story.saved %}Saved{% else %}Save this story{% endif %}
+
+
+
 
+
{% if story.shared_by_user %}Shared{% else %}Post to Blurblog{% endif %}
+
+
+ {% else %} + + {% endif %}
- {% endif %}
{% if story.share_count %} @@ -153,6 +160,10 @@ {% include_javascripts "blurblog" %} + + \ No newline at end of file diff --git a/templates/social/story_share.xhtml b/templates/social/story_share.xhtml index 9eb37116a..36fcf2ea2 100644 --- a/templates/social/story_share.xhtml +++ b/templates/social/story_share.xhtml @@ -1,46 +1,51 @@ {% load social_tags %} +
-
-
- {% if story.share_count %} -
- Shared by - {{ story.share_count }} - {{ story.share_count|pluralize:"person, people" }} -
- {% if story.share_count_public %} -
- {% for share_user in story.shared_by_public %} - - - - {% endfor %} + {% if story.share_count %} +
+
+ {% if story.share_count %} +
+ Shared by + {{ story.share_count }} + {{ story.share_count|pluralize:"person, people" }}
+ {% if story.share_count_public %} +
+ {% for share_user in story.shared_by_public %} + + + + {% endfor %} +
+ {% endif %} {% endif %} - {% endif %} - {% if story.share_count %} - {% if story.share_count_friends %} -
Shared by:
-
- {% for share_user in story.shared_by_friends %} - - - - {% endfor %} -
+ {% if story.share_count %} + {% if story.share_count_friends %} +
Shared by:
+
+ {% for share_user in story.shared_by_friends %} + + + + {% endfor %} +
+ {% endif %} {% endif %} - {% endif %} +
-
- {% render_story_comments story %} + {% render_story_comments story %} - {% if story.comment_count_public %} -
-
- There {{ story.comment_count_public|pluralize:"is,are" }} {{ story.comment_count_public}} public comment{{ story.comment_count_public|pluralize }} + {% if story.comment_count_public %} +
+
+ There {{ story.comment_count_public|pluralize:"is,are" }} {{ story.comment_count_public}} public comment{{ story.comment_count_public|pluralize }} +
-
+ {% endif %} + {% endif %} -
\ No newline at end of file +
+