mirror of
https://github.com/viq/NewsBlur.git
synced 2025-08-31 14:11:05 +00:00
Showing interactions in module. Adding interactivity.
This commit is contained in:
parent
6916aa179b
commit
b9d8b91f6d
9 changed files with 212 additions and 40 deletions
|
@ -179,41 +179,55 @@ NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()}
|
|||
|
||||
class MInteraction(mongo.Document):
|
||||
user_id = mongo.IntField()
|
||||
activity_date = mongo.DateTimeField(default=datetime.datetime.now)
|
||||
activity_type = mongo.StringField()
|
||||
activity_content = mongo.StringField()
|
||||
date = mongo.DateTimeField(default=datetime.datetime.now)
|
||||
activity = mongo.StringField()
|
||||
title = mongo.StringField()
|
||||
content = mongo.StringField()
|
||||
activity_user_id = mongo.IntField()
|
||||
feed_id = mongo.IntField()
|
||||
content_id = mongo.StringField()
|
||||
|
||||
meta = {
|
||||
'collection': 'interactions',
|
||||
'indexes': [('user_id', 'activity_date')],
|
||||
'indexes': [('user_id', 'date'), 'activity'],
|
||||
'allow_inheritance': False,
|
||||
'index_drop_dups': True,
|
||||
'ordering': ['-date'],
|
||||
}
|
||||
|
||||
def __unicode__(self):
|
||||
user = User.objects.get(pk=self.user_id)
|
||||
return "%s on %s: %s - %s" % (user.username, self.activity_date,
|
||||
self.activity_type, self.activity_content[:20])
|
||||
activity_user = self.activity_user_id and User.objects.get(pk=self.activity_user_id)
|
||||
return "<%s> %s on %s: %s - %s" % (user.username, activity_user and activity_user.username, self.date,
|
||||
self.activity, self.content and self.content[:20])
|
||||
|
||||
@classmethod
|
||||
def new_follow(cls, follower_user_id, followee_user_id):
|
||||
cls.objects.create(user_id=followee_user_id,
|
||||
activity_user_id=follower_user_id,
|
||||
activity_type='follow')
|
||||
activity='follow')
|
||||
|
||||
@classmethod
|
||||
def new_reply(cls, user_id, reply_user_id, reply_content):
|
||||
def new_comment_reply(cls, user_id, reply_user_id, reply_content):
|
||||
cls.objects.create(user_id=user_id,
|
||||
activity_user_id=reply_user_id,
|
||||
activity_type='reply',
|
||||
activity_content=reply_content)
|
||||
activity='comment_reply',
|
||||
content=reply_content)
|
||||
|
||||
@classmethod
|
||||
def new_starred_story(cls, user_id, story_title, story_feed_id):
|
||||
feed = Feed.objects.get(pk=story_feed_id)
|
||||
def new_reply_reply(cls, user_id, reply_user_id, reply_content):
|
||||
cls.objects.create(user_id=user_id,
|
||||
activity_type='star',
|
||||
activity_content=story_title)
|
||||
activity_user_id=reply_user_id,
|
||||
activity='reply_reply',
|
||||
content=reply_content)
|
||||
|
||||
@classmethod
|
||||
def new_starred_story(cls, user_id, story_title, story_feed_id, story_id):
|
||||
cls.objects.create(user_id=user_id,
|
||||
activity='star',
|
||||
content=story_title,
|
||||
feed_id=story_feed_id,
|
||||
content_id=story_id)
|
||||
|
||||
|
||||
def create_profile(sender, instance, created, **kwargs):
|
||||
|
|
|
@ -22,9 +22,10 @@ from collections import defaultdict
|
|||
from operator import itemgetter
|
||||
from apps.recommendations.models import RecommendedFeed
|
||||
from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifierFeed, MClassifierTag
|
||||
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds, apply_classifier_authors, apply_classifier_tags
|
||||
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds
|
||||
from apps.analyzer.models import apply_classifier_authors, apply_classifier_tags
|
||||
from apps.analyzer.models import get_classifiers_for_user
|
||||
from apps.profile.models import Profile
|
||||
from apps.profile.models import Profile, MInteraction
|
||||
from apps.reader.models import UserSubscription, UserSubscriptionFolders, MUserStory, Feature
|
||||
from apps.reader.forms import SignupForm, LoginForm, FeatureForm
|
||||
from apps.rss_feeds.models import MFeedIcon
|
||||
|
@ -1199,6 +1200,10 @@ def mark_story_as_starred(request):
|
|||
defaults=story_values)
|
||||
if created:
|
||||
logging.user(request, "~FCStarring: ~SB%s" % (story[0].story_title[:50]))
|
||||
MInteraction.new_starred_story(user_id=request.user.pk,
|
||||
story_title=story[0].story_title,
|
||||
story_feed_id=feed_id,
|
||||
content_id=starred_story.story_guid)
|
||||
else:
|
||||
logging.user(request, "~FC~BRAlready stared:~SN~FC ~SB%s" % (story[0].story_title[:50]))
|
||||
else:
|
||||
|
|
|
@ -12,6 +12,7 @@ from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifie
|
|||
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds, apply_classifier_authors, apply_classifier_tags
|
||||
from apps.analyzer.models import get_classifiers_for_user
|
||||
from apps.reader.models import MUserStory, UserSubscription
|
||||
from apps.profile.models import MInteraction
|
||||
from utils import json_functions as json
|
||||
from utils import log as logging
|
||||
from utils import PyRSS2Gen as RSS
|
||||
|
@ -252,14 +253,25 @@ def save_comment_reply(request):
|
|||
reply.comments = reply_comments
|
||||
shared_story.replies.append(reply)
|
||||
shared_story.save()
|
||||
|
||||
logging.user(request, "~FCReplying to comment in: ~SB~FM%s (~FB%s~FM)" % (story.story_title[:50], reply_comments[:100]))
|
||||
|
||||
comment = shared_story.comments_with_author()
|
||||
profile_user_ids = set([comment['user_id']])
|
||||
profile_user_ids = profile_user_ids.union([reply['user_id'] for reply in comment['replies']])
|
||||
reply_user_ids = [reply['user_id'] for reply in comment['replies']]
|
||||
profile_user_ids = profile_user_ids.union(reply_user_ids)
|
||||
profiles = MSocialProfile.objects.filter(user_id__in=list(profile_user_ids))
|
||||
profiles = [profile.to_json(compact=True) for profile in profiles]
|
||||
|
||||
# Interaction for every other replier and original commenter
|
||||
MInteraction.new_comment_reply(user_id=comment['user_id'],
|
||||
reply_user_id=request.user.pk,
|
||||
reply_content=reply_comments)
|
||||
for user_id in reply_user_ids.difference([comment['user_id']]):
|
||||
MInteraction.new_reply_reply(user_id=user_id,
|
||||
reply_user_id=request.user.pk,
|
||||
reply_content=reply_comments)
|
||||
|
||||
return {'code': code, 'comment': comment, 'user_profiles': profiles}
|
||||
|
||||
def shared_stories_public(request, username):
|
||||
|
@ -299,7 +311,7 @@ def profile(request):
|
|||
def load_user_profile(request):
|
||||
social_profile, _ = MSocialProfile.objects.get_or_create(user_id=request.user.pk)
|
||||
social_services, _ = MSocialServices.objects.get_or_create(user_id=request.user.pk)
|
||||
|
||||
|
||||
return {
|
||||
'services': social_services,
|
||||
'user_profile': social_profile.to_json(full=True),
|
||||
|
|
|
@ -7707,3 +7707,60 @@ background: transparent;
|
|||
color: #909090;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* ======================= */
|
||||
/* = Interactions Module = */
|
||||
/* ======================= */
|
||||
|
||||
.NB-interactions {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.NB-interaction {
|
||||
list-style: none;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 6px 12px 6px 36px;
|
||||
border-bottom: 1px solid #F0F0F0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-interaction:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.NB-interaction-photo {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 3px;
|
||||
left: 12px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-interaction-date {
|
||||
color: #B0B0B0;
|
||||
font-size: 11px;
|
||||
float: right;
|
||||
text-transform: uppercase;
|
||||
padding: 4px 0 4px 4px;
|
||||
}
|
||||
.NB-interaction-title {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
color: #404040;
|
||||
padding: 2px 0 0 0;
|
||||
}
|
||||
.NB-interaction-content {
|
||||
font-size: 11px;
|
||||
padding-top: 2px;
|
||||
line-height: 14px;
|
||||
color: #808080;
|
||||
}
|
||||
.NB-interaction-username {
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-interaction-starred-story-title {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -1123,7 +1123,10 @@ NEWSBLUR.AssetModel.Reader.prototype = {
|
|||
},
|
||||
|
||||
fetch_user_profile: function(user_id, callback) {
|
||||
this.make_request('/social/profile', {'user_id': user_id}, callback, callback, {
|
||||
this.make_request('/social/profile', {'user_id': user_id}, _.bind(function(data) {
|
||||
this.add_user_profiles(data.profiles);
|
||||
callback(data);
|
||||
}, this), callback, {
|
||||
request_type: 'GET'
|
||||
});
|
||||
},
|
||||
|
|
|
@ -7567,6 +7567,23 @@
|
|||
self.save_social_comment_reply($comment);
|
||||
});
|
||||
|
||||
// = Interactions Module ==========================================
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-interaction-username' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var user_id = $t.data('userId');
|
||||
var username = $t.text();
|
||||
self.model.add_user_profiles([{user_id: user_id, username: username}]);
|
||||
self.open_social_profile_modal(user_id);
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.NB-interaction-profile-photo' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var user_id = $t.data('userId');
|
||||
var username = $t.closest('.NB-interaction').find('.NB-interaction-username').text();
|
||||
self.model.add_user_profiles([{user_id: user_id, username: username}]);
|
||||
self.open_social_profile_modal(user_id);
|
||||
});
|
||||
|
||||
// = One-offs =====================================================
|
||||
|
||||
var clicked = false;
|
||||
|
|
|
@ -6,7 +6,8 @@ NEWSBLUR.ReaderSocialProfile = function(user_id, options) {
|
|||
this.options = $.extend({}, defaults, options);
|
||||
this.model = NEWSBLUR.AssetModel.reader();
|
||||
this.profiles = new NEWSBLUR.Collections.Users();
|
||||
user_id = _.string.ltrim(user_id, 'social:');
|
||||
user_id = parseInt(_.string.ltrim(user_id, 'social:'), 10);
|
||||
console.log(["user_id", user_id]);
|
||||
this.runner(user_id);
|
||||
};
|
||||
|
||||
|
@ -19,7 +20,7 @@ _.extend(NEWSBLUR.ReaderSocialProfile.prototype, {
|
|||
this.make_modal();
|
||||
this.open_modal();
|
||||
_.defer(_.bind(this.fetch_profile, this, user_id));
|
||||
|
||||
|
||||
this.$modal.bind('click', $.rescope(this.handle_click, this));
|
||||
},
|
||||
|
||||
|
|
|
@ -1,18 +1,60 @@
|
|||
{% load utils_tags typogrify_tags statistics_tags %}
|
||||
|
||||
{% if interactions %}
|
||||
<div class="NB-module NB-module-features">
|
||||
|
||||
<h5 class="NB-module-header">
|
||||
<div class="NB-module-header-right">
|
||||
<div class="NB-spinner NB-left"></div>
|
||||
<a href="#" class="NB-module-direction NB-module-next-page NB-javascript"></a>
|
||||
<a href="#" class="NB-module-direction NB-module-previous-page NB-disabled"></a>
|
||||
</div>
|
||||
Interactions
|
||||
</h5>
|
||||
|
||||
<div class="NB-interactions">
|
||||
Follow, comments, replies, starred stories.
|
||||
</div>
|
||||
<h5 class="NB-module-header">
|
||||
<div class="NB-module-header-right">
|
||||
<div class="NB-spinner NB-left"></div>
|
||||
<a href="#" class="NB-module-direction NB-module-next-page NB-javascript"></a>
|
||||
<a href="#" class="NB-module-direction NB-module-previous-page NB-disabled"></a>
|
||||
</div>
|
||||
Interactions
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
<ul class="NB-interactions">
|
||||
{% for interaction in interactions %}
|
||||
<li class="NB-interaction NB-interaction-{{ interaction.activity }}"
|
||||
{% if interaction.content_id %}data-content-id="{{ interaction.content_id }}"{% endif %}>
|
||||
{% if interaction.activity == 'follow' %}
|
||||
<img class="NB-interaction-photo NB-interaction-profile-photo" src="{{ interaction.photo_url }}" data-user-id="{{ interaction.activity_user_id }}">
|
||||
<div class="NB-interaction-date">
|
||||
{{ interaction.date }} ago
|
||||
</div>
|
||||
<div class="NB-interaction-title">
|
||||
<span class="NB-interaction-username NB-splash-link" data-user-id="{{ interaction.activity_user_id }}">
|
||||
{{ interaction.activity_user.username }}
|
||||
</span> started following you.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if interaction.activity == 'star' %}
|
||||
<img class="NB-interaction-photo" src="/rss_feeds/icon/{{ interaction.feed_id }}">
|
||||
<div class="NB-interaction-date">
|
||||
{{ interaction.date }} ago
|
||||
</div>
|
||||
<div class="NB-interaction-title">
|
||||
You starred "<span class="NB-interaction-starred-story-title NB-splash-link">{{ interaction.content|truncatewords:8 }}</span>".
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if interaction.activity == 'comment_reply' or interaction.activity == 'reply_reply' %}
|
||||
<img class="NB-interaction-photo NB-interaction-profile-photo" src="{{ interaction.photo_url }}" data-user-id="{{ interaction.activity_user_id }}">
|
||||
<div class="NB-interaction-date">
|
||||
{{ interaction.date }} ago
|
||||
</div>
|
||||
<div class="NB-interaction-title">
|
||||
<span class="NB-interaction-username NB-splash-link" data-user-id="{{ interaction.activity_user_id }}">
|
||||
{{ interaction.activity_user.username }}
|
||||
</span> replied to your {% if interaction.activity == 'comment_reply' %}comment{% else %}reply{% endif %}:
|
||||
</div>
|
||||
<div class="NB-interaction-content">
|
||||
"<span class="NB-interaction-starred-story-title NB-splash-link">{{ interaction.content|truncatewords:16 }}</span>"
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
|
@ -1,11 +1,14 @@
|
|||
from django.contrib.sites.models import Site
|
||||
from django import template
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
from utils.user_functions import get_user
|
||||
from vendor.timezones.utilities import localtime_for_timezone
|
||||
from django import template
|
||||
from apps.reader.forms import FeatureForm
|
||||
from apps.reader.models import Feature
|
||||
from apps.profile.models import MInteraction
|
||||
from apps.social.models import MSocialProfile
|
||||
from vendor.timezones.utilities import localtime_for_timezone
|
||||
from utils.feed_functions import relative_timesince
|
||||
from utils.user_functions import get_user
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -34,14 +37,32 @@ def render_features_module(context):
|
|||
|
||||
@register.inclusion_tag('reader/interactions_module.xhtml', takes_context=True)
|
||||
def render_interactions_module(context):
|
||||
user = get_user(context['user'])
|
||||
interactions = MInteraction.objects.filter(user_id=user.pk)[0:5]
|
||||
user = get_user(context['user'])
|
||||
interactions_db = MInteraction.objects.filter(user_id=user.pk)[0:5]
|
||||
user_ids = [i.activity_user_id for i in interactions_db if i.activity_user_id]
|
||||
users = dict((u.pk, u) for u in User.objects.filter(pk__in=user_ids))
|
||||
social_profiles = dict((p.user_id, p) for p in MSocialProfile.objects.filter(user_id__in=user_ids))
|
||||
|
||||
interactions = []
|
||||
for interaction_db in interactions_db:
|
||||
interaction = interaction_db.to_mongo()
|
||||
interaction['photo_url'] = getattr(social_profiles.get(interaction_db.activity_user_id), 'photo_url', None)
|
||||
interaction['activity_user'] = social_profiles.get(interaction_db.activity_user_id)
|
||||
interaction['date'] = relative_timesince(interaction_db.date)
|
||||
interactions.append(interaction)
|
||||
|
||||
return {
|
||||
'user': user,
|
||||
'interactions': interactions,
|
||||
'users': users,
|
||||
'social_profiles': social_profiles,
|
||||
}
|
||||
|
||||
|
||||
@register.filter
|
||||
def get(h, key):
|
||||
print h, key
|
||||
return h[key]
|
||||
|
||||
@register.filter
|
||||
def get_range( value ):
|
||||
"""
|
||||
|
|
Loading…
Add table
Reference in a new issue