Rearranging javascript. Also backbonizing user models for follower and following collections.

This commit is contained in:
Samuel Clay 2012-01-04 09:42:35 -08:00
parent 648281c634
commit 9ea6ee9086
32 changed files with 300 additions and 171 deletions

View file

@ -46,6 +46,110 @@ class MSharedStory(mongo.Document):
super(MSharedStory, self).save(*args, **kwargs)
class MSocialProfile(mongo.Document):
user_id = mongo.IntField()
username = mongo.StringField(max_length=30)
email = mongo.StringField()
bio = mongo.StringField(max_length=80)
photo_url = mongo.StringField()
photo_service = mongo.StringField()
location = mongo.StringField(max_length=40)
website = mongo.StringField(max_length=200)
subscription_count = mongo.IntField(default=0)
shared_stories_count = mongo.IntField(default=0)
following_count = mongo.IntField(default=0)
follower_count = mongo.IntField(default=0)
following_user_ids = mongo.ListField(mongo.IntField())
follower_user_ids = mongo.ListField(mongo.IntField())
unfollowed_user_ids = mongo.ListField(mongo.IntField())
meta = {
'collection': 'social_profile',
'indexes': ['user_id', 'following_user_ids', 'follower_user_ids', 'unfollowed_user_ids'],
'allow_inheritance': False,
}
def __unicode__(self):
return "%s [%s] %s/%s" % (self.username, self.user_id,
self.subscription_count, self.shared_stories_count)
def save(self, *args, **kwargs):
if not self.username:
self.update_user(skip_save=True)
if not self.subscription_count:
self.count(skip_save=True)
super(MSocialProfile, self).save(*args, **kwargs)
@classmethod
def profiles(cls, user_ids):
profiles = cls.objects.filter(user_id__in=user_ids)
return profiles
def to_json(self, full=False):
params = {
'user_id': self.user_id,
'username': self.username,
'photo_url': self.photo_url,
'bio': self.bio,
'location': self.location,
'website': self.website,
'subscription_count': self.subscription_count,
'shared_stories_count': self.shared_stories_count,
'following_count': self.following_count,
'follower_count': self.follower_count,
}
if full:
params['photo_service'] = self.photo_service
params['following_user_ids'] = self.following_user_ids
params['follower_user_ids'] = self.follower_user_ids
params['unfollowed_user_ids'] = self.unfollowed_user_ids
return params
def update_user(self, skip_save=False):
user = User.objects.get(pk=self.user_id)
self.username = user.username
self.email = user.email
if not skip_save:
self.save()
def count(self, skip_save=False):
self.subscription_count = UserSubscription.objects.filter(user__pk=self.user_id).count()
self.shared_stories_count = MSharedStory.objects.filter(user_id=self.user_id).count()
self.following_count = len(self.following_user_ids)
self.follower_count = len(self.follower_user_ids)
if not skip_save:
self.save()
def follow_user(self, user_id, check_unfollowed=False):
if check_unfollowed and user_id in self.unfollowed_user_ids:
return
if user_id not in self.following_user_ids:
self.following_user_ids.append(user_id)
if user_id in self.unfollowed_user_ids:
self.unfollowed_user_ids.remove(user_id)
self.save()
followee, _ = MSocialProfile.objects.get_or_create(user_id=user_id)
if self.user_id not in followee.follower_user_ids:
followee.follower_user_ids.append(self.user_id)
followee.save()
self.count()
def unfollow_user(self, user_id):
if user_id in self.following_user_ids:
self.following_user_ids.remove(user_id)
if user_id not in self.unfollowed_user_ids:
self.unfollowed_user_ids.append(user_id)
self.save()
followee = MSocialProfile.objects.get(user_id=user_id)
if self.user_id in followee.follower_user_ids:
followee.follower_user_ids.remove(self.user_id)
followee.save()
self.count()
class MSocialServices(mongo.Document):
user_id = mongo.IntField()
autofollow = mongo.BooleanField(default=True)
@ -235,100 +339,3 @@ class MSocialServices(mongo.Document):
profile.photo_url = "http://www.gravatar.com/avatar/" + \
hashlib.md5(user.email).hexdigest()
profile.save()
class MSocialProfile(mongo.Document):
user_id = mongo.IntField()
username = mongo.StringField(max_length=30)
email = mongo.StringField()
bio = mongo.StringField(max_length=80)
photo_url = mongo.StringField()
photo_service = mongo.StringField()
location = mongo.StringField(max_length=40)
website = mongo.StringField(max_length=200)
subscription_count = mongo.IntField()
shared_stories_count = mongo.IntField()
following_count = mongo.IntField()
follower_count = mongo.IntField()
following_user_ids = mongo.ListField(mongo.IntField())
follower_user_ids = mongo.ListField(mongo.IntField())
unfollowed_user_ids = mongo.ListField(mongo.IntField())
meta = {
'collection': 'social_profile',
'indexes': ['user_id', 'following_user_ids', 'follower_user_ids', 'unfollowed_user_ids'],
'allow_inheritance': False,
}
def __unicode__(self):
return "%s [%s] %s/%s" % (self.username, self.user_id,
self.subscription_count, self.shared_stories_count)
def save(self, *args, **kwargs):
if not self.username:
self.update_user(skip_save=True)
if not self.subscription_count:
self.count(skip_save=True)
super(MSocialProfile, self).save(*args, **kwargs)
def to_json(self, full=False):
params = {
'user_id': self.user_id,
'username': self.username,
'photo_url': self.photo_url,
'bio': self.bio,
'location': self.location,
'website': self.website,
'subscription_count': self.subscription_count or 0,
'shared_stories_count': self.shared_stories_count or 0,
'following_count': self.following_count or 0,
'follower_count': self.follower_count or 0,
}
if full:
params['photo_service'] = self.photo_service
params['following_user_ids'] = self.following_user_ids
params['follower_user_ids'] = self.follower_user_ids
params['unfollowed_user_ids'] = self.unfollowed_user_ids
return params
def update_user(self, skip_save=False):
user = User.objects.get(pk=self.user_id)
self.username = user.username
self.email = user.email
if not skip_save:
self.save()
def count(self, skip_save=False):
self.subscription_count = UserSubscription.objects.filter(user__pk=self.user_id).count()
self.shared_stories_count = MSharedStory.objects.filter(user_id=self.user_id).count()
self.following_count = len(self.following_user_ids)
self.follower_count = len(self.follower_user_ids)
if not skip_save:
self.save()
def follow_user(self, user_id, check_unfollowed=False):
if not check_unfollowed or user_id not in self.following_user_ids:
if user_id not in self.following_user_ids:
self.following_user_ids.append(user_id)
self.save()
followee, _ = MSocialProfile.objects.get_or_create(user_id=user_id)
if self.user_id not in followee.follower_user_ids:
followee.follower_user_ids.append(self.user_id)
followee.save()
self.count()
def unfollow_user(self, user_id):
self.following_user_ids.remove(user_id)
self.save()
followee = MSocialProfile.objects.get(user_id=user_id)
followee.follower_user_ids.remove(self.user_id)
followee.save()
self.count()
@classmethod
def profiles(cls, user_ids):
profiles = cls.objects.filter(user_id__in=user_ids)
return profiles

View file

@ -9,6 +9,8 @@ urlpatterns = patterns('',
url(r'^facebook_disconnect/?$', views.facebook_disconnect, name='facebook-disconnect'),
url(r'^friends/?$', views.friends, name='friends'),
url(r'^profile/?$', views.profile, name='profile'),
url(r'^follow/?$', views.follow, name='social-follow'),
url(r'^unfollow/?$', views.unfollow, name='social-unfollow'),
url(r'^(?P<user_id>\d+)/(?P<username>\w+)/?$', views.shared_story_feed, name='shared-story-feed'),
url(r'^(?P<username>\w+)/?$', views.shared_stories_public, name='shared-stories-public'),
)

View file

@ -105,7 +105,7 @@ def friends(request):
return {
'services': social_services,
'autofollow': social_services.autofollow,
'social_profile': social_profile.to_json(full=True),
'user_profile': social_profile.to_json(full=True),
'following_profiles': following_profiles,
'follower_profiles': follower_profiles,
}
@ -115,7 +115,9 @@ def friends(request):
def profile(request):
if request.method == 'POST':
return save_profile(request)
return dict(code=0)
profile = MSocialProfile.objects.get(user_id=request.user.pk)
return dict(code=1, user_profile=profile)
def save_profile(request):
data = request.POST
@ -129,7 +131,27 @@ def save_profile(request):
social_services = MSocialServices.objects.get(user_id=request.user.pk)
social_services.set_photo(data['photo_service'])
return dict(code=1)
return dict(code=1, user_profile=profile)
@ajax_login_required
@json.json_view
def follow(request):
follow_user_id = int(request.POST['user_id'])
profile = MSocialProfile.objects.get(user_id=request.user.pk)
profile.follow_user(follow_user_id)
follow_profile = MSocialProfile.objects.get(user_id=follow_user_id)
return dict(user_profile=profile, follow_profile=follow_profile)
@ajax_login_required
@json.json_view
def unfollow(request):
unfollow_user_id = int(request.POST['user_id'])
profile = MSocialProfile.objects.get(user_id=request.user.pk)
profile.unfollow_user(unfollow_user_id)
return dict(user_profile=profile)
@login_required
@render_to('social/social_connect.xhtml')

View file

@ -53,11 +53,12 @@ javascripts:
- media/js/vendor/underscore.js
- media/js/vendor/underscore.string.js
- media/js/vendor/backbone-*.js
- media/js/newsblur/reader_utils.js
- media/js/newsblur/assetmodel.js
- media/js/newsblur/reader.js
- media/js/newsblur/modal.js
- media/js/newsblur/reader_*.js
- media/js/newsblur/common/*.js
- media/js/newsblur/models/*.js
- media/js/newsblur/reader/reader_utils.js
- media/js/newsblur/reader/reader.js
- media/js/newsblur/reader/*.js
- media/js/newsblur/static/*.js
# mobile:
# - media/js/jquery-1.7.js
# - media/js/mobile/jquery.mobile-1.0b1.js
@ -72,7 +73,7 @@ javascripts:
# - media/js/newsblur/assetmodel.js
# - media/js/mobile/newsblur/mobile_workspace.js
paypal:
- media/js/newsblur/paypal_return.js
- media/js/newsblur/paypal/paypal_return.js
bookmarklet:
- media/js/vendor/jquery-1.5.1.min.js
- media/js/vendor/jquery.noConflict.js

View file

@ -215,7 +215,8 @@
color: #909090;
}
.NB-modal-submit-close {
.NB-modal-submit-close,
.NB-modal-submit-grey {
background-color: #d5d4dB;
color: #909090;
font-weight: bold;
@ -225,7 +226,11 @@
font-weight: bold;
color: #FCFCFC;
}
.NB-modal-submit-red {
background-color: #911C31;
color: #E4E4E4;
font-weight: bold;
}
.NB-modal-submit-delete {
background-color: #7E020D;
font-weight: bold;

View file

@ -6675,6 +6675,6 @@ background: transparent;
margin-top: 10px;
}
.NB-modal-friends .NB-profile-badge-actions .NB-modal-submit-button {
width: 80px;
width: 90px;
text-align: center;
}

View file

@ -919,7 +919,9 @@ NEWSBLUR.AssetModel.Reader.prototype = {
fetch_friends: function(callback) {
var pre_callback = _.bind(function(data) {
// this.profile =
this.user_profile = new NEWSBLUR.Models.User(data.user_profile);
this.follower_profiles = new NEWSBLUR.Collections.Users(data.follower_profiles);
this.following_profiles = new NEWSBLUR.Collections.Users(data.following_profiles);
callback(data);
}, this);
this.make_request('/social/friends', null, pre_callback);
@ -929,10 +931,37 @@ NEWSBLUR.AssetModel.Reader.prototype = {
this.make_request('/social/'+service+'_disconnect/', null, callback);
},
save_social_profile: function(data, callback) {
save_user_profile: function(data, callback) {
this.make_request('/social/profile/', data, callback);
},
follow_user: function(user_id, callback) {
var pre_callback = _.bind(function(data) {
this.user_profile.set(data.user_profile);
var following_profile = this.following_profiles.detect(function(profile) {
return profile.get('user_id') == data.follow_profile.user_id;
});
if (following_profile) {
following_profile.set(data.follow_profile);
} else {
this.following_profiles.add(data.follow_profile);
}
callback(data);
}, this);
this.make_request('/social/follow', {'user_id': user_id}, pre_callback);
},
unfollow_user: function(user_id, callback) {
var pre_callback = _.bind(function(data) {
this.user_profile.set(data.user_profile);
this.following_profiles.remove(function(profile) {
return profile.get('user_id') == data.follow_profile.user_id;
});
callback(data);
}, this);
this.make_request('/social/unfollow', {'user_id': user_id}, pre_callback);
},
recalculate_story_scores: function(feed_id) {
_.each(this.stories, _.bind(function(story, i) {
if (story.story_feed_id != feed_id) return;

View file

@ -0,0 +1,11 @@
NEWSBLUR.Models.User = Backbone.Model.extend({
idAttribute: 'user_id'
});
NEWSBLUR.Collections.Users = Backbone.Collection.extend({
model : NEWSBLUR.Models.User
});

View file

@ -3010,7 +3010,7 @@
$story_tags
]),
$.make('span', { className: 'story_date' }, story.short_parsed_date),
$.make('span', { className: 'story_id' }, ''+story.id),
$.make('span', { className: 'story_id' }, story.id),
$.make('div', { className: 'NB-story-manage-icon' })
]).data('story_id', story.id).data('feed_id', story.story_feed_id);
@ -3354,7 +3354,7 @@
// $.make('div', { className: 'NB-feed-sentiment NB-feed-like', title: 'What I like about this site...' }),
// $.make('div', { className: 'NB-feed-sentiment NB-feed-dislike', title: 'What I dislike about this site...' })
// ]),
$.make('span', { className: 'feed_id' }, ''+feed.id)
$.make('span', { className: 'feed_id' }, feed.id)
]).hover(function() {
$(this).addClass('NB-feedbar-hover');
},function() {
@ -5419,7 +5419,6 @@
this.flags.feed_refresh = setInterval(function() {
if (!self.flags['pause_feed_refreshing']) {
console.log(["setup feed refresh", self.flags['has_unfetched_feeds']]);
self.model.refresh_feeds(_.bind(function(updated_feeds) {
self.post_feed_refresh(updated_feeds);
}, self), self.flags['has_unfetched_feeds']);

View file

@ -79,26 +79,28 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
]);
},
fetch_friends: function() {
fetch_friends: function(callback) {
$('.NB-modal-loading', this.$modal).addClass('NB-active');
this.model.fetch_friends(_.bind(function(data) {
this.make_find_friends_and_services(data);
this.make_profile_section(data);
this.make_profile_tab(data);
this.make_followers_tab(data);
this.make_following_tab(data);
this.profile = this.model.user_profile;
this.services = data.services;
this.autofollow = data.autofollow;
this.make_find_friends_and_services();
this.make_profile_section();
this.make_profile_tab();
this.make_followers_tab();
this.make_following_tab();
callback && callback();
}, this));
},
make_find_friends_and_services: function(data) {
console.log(["data", data]);
this.profile = data.social_profile;
make_find_friends_and_services: function() {
$('.NB-modal-loading', this.$modal).removeClass('NB-active');
var $services = $('.NB-friends-services', this.$modal).empty();
_.each(['twitter', 'facebook'], function(service) {
_.each(['twitter', 'facebook'], _.bind(function(service) {
var $service;
if (data.services[service][service+'_uid']) {
if (this.services && this.services[service][service+'_uid']) {
$service = $.make('div', { className: 'NB-friends-service NB-connected NB-friends-service-'+service }, [
$.make('div', { className: 'NB-friends-service-title' }, _.capitalize(service)),
$.make('div', { className: 'NB-friends-service-connect NB-modal-submit-button NB-modal-submit-close' }, 'Disconnect')
@ -113,10 +115,10 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
]);
}
$services.append($service);
});
}, this));
$autofollow = $.make('div', { className: 'NB-friends-service NB-friends-autofollow'}, [
$.make('input', { type: 'checkbox', className: 'NB-friends-autofollow-checkbox', id: 'NB-friends-autofollow-checkbox', checked: data.autofollow ? 'checked' : null }),
$.make('input', { type: 'checkbox', className: 'NB-friends-autofollow-checkbox', id: 'NB-friends-autofollow-checkbox', checked: this.autofollow ? 'checked' : null }),
$.make('label', { className: 'NB-friends-autofollow-label', 'for': 'NB-friends-autofollow-checkbox' }, [
'Auto-follow',
$.make('br'),
@ -127,12 +129,12 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
this.resize();
},
make_profile_section: function(data) {
make_profile_section: function() {
var $badge = $('.NB-friends-findfriends-profile', this.$modal).empty();
var $profile_badge;
var profile = data.social_profile;
if (!profile.location && !profile.bio && !profile.website && !profile.photo_url) {
var profile = this.profile;
if (!profile.get('location') && !profile.get('bio') && !profile.get('website') && !profile.get('photo_url')) {
$profile_badge = $.make('a', {
className: 'NB-friends-profile-link NB-modal-submit-button NB-modal-submit-green',
href: '#'
@ -148,7 +150,7 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
$badge.append($profile_badge);
},
make_profile_tab: function(data) {
make_profile_tab: function() {
var $profile_container = $('.NB-friends-profile', this.$modal).empty();
var $profile = $.make('form', [
$.make('label', 'Username'),
@ -157,24 +159,24 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
$.make('a', { className: 'NB-splash-link NB-account-link', href: '#' }, 'Change')
]),
$.make('label', { 'for': 'NB-profile-location' }, 'Location'),
$.make('input', { id: 'NB-profile-location', name: 'location', type: 'text', className: 'NB-input', style: 'width: 220px', value: data.social_profile.location, "data-max": 40 }),
$.make('input', { id: 'NB-profile-location', name: 'location', type: 'text', className: 'NB-input', style: 'width: 220px', value: this.profile.get('location'), "data-max": 40 }),
$.make('span', { className: 'NB-count NB-count-location' }),
$.make('label', { 'for': 'NB-profile-website' }, 'Website'),
$.make('input', { id: 'NB-profile-website', name: 'website', type: 'text', className: 'NB-input', style: 'width: 300px', value: data.social_profile.website, "data-max": 200 }),
$.make('input', { id: 'NB-profile-website', name: 'website', type: 'text', className: 'NB-input', style: 'width: 300px', value: this.profile.get('website'), "data-max": 200 }),
$.make('span', { className: 'NB-count NB-count-website' }),
$.make('label', { 'for': 'NB-profile-bio' }, 'Bio'),
$.make('input', { id: 'NB-profile-bio', name: 'bio', type: 'text', className: 'NB-input', style: 'width: 380px', value: data.social_profile.bio, "data-max": 80 }),
$.make('input', { id: 'NB-profile-bio', name: 'bio', type: 'text', className: 'NB-input', style: 'width: 380px', value: this.profile.get('bio'), "data-max": 80 }),
$.make('span', { className: 'NB-count NB-count-bio' })
]);
$profile_container.html($profile);
this.make_profile_photo_chooser(data);
this.make_profile_photo_chooser();
this.disable_save();
},
make_profile_photo_chooser: function(data) {
make_profile_photo_chooser: function() {
var $profiles = $('.NB-friends-profilephoto', this.$modal).empty();
_.each(['twitter', 'facebook', 'gravatar'], function(service) {
_.each(['twitter', 'facebook', 'gravatar'], _.bind(function(service) {
var $profile = $.make('div', { className: 'NB-friends-profile-photo-group NB-friends-photo-'+service }, [
$.make('div', { className: 'NB-friends-photo-title' }, [
$.make('input', { type: 'radio', name: 'profile_photo_service', value: service, id: 'NB-profile-photo-service-'+service }),
@ -183,7 +185,7 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
$.make('div', { className: 'NB-friends-photo-image' }, [
$.make('label', { 'for': 'NB-profile-photo-service-'+service }, [
$.make('div', { className: 'NB-photo-loader' }),
$.make('img', { src: data.services[service][service+'_picture_url'] })
$.make('img', { src: this.services[service][service+'_picture_url'] })
])
]),
(service == 'upload' && $.make('div', { className: 'NB-photo-link' }, [
@ -194,32 +196,32 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
$.make('a', { href: 'http://www.gravatar.com', className: 'NB-splash-link', target: '_blank' }, 'gravatar.com')
]))
]);
if (service == data.social_profile.photo_service) {
if (service == this.profile.get('photo_service')) {
$('input[type=radio]', $profile).attr('checked', true);
}
$profiles.append($profile);
});
}, this));
},
make_followers_tab: function(data) {
make_followers_tab: function() {
var $tab = $('.NB-tab-followers', this.$modal).empty();
if (!data.follower_profiles || !data.follower_profiles.length) {
if (!this.model.follower_profiles || !this.model.follower_profiles.size()) {
var $ghost = $.make('div', { className: 'NB-ghost NB-modal-section' }, 'Nobody has yet subscribed to your shared stories.');
$tab.append($ghost);
} else {
_.each(data.follower_profiles, _.bind(function(profile) {
this.model.follower_profiles.each(_.bind(function(profile) {
$tab.append(this.make_profile_badge(profile));
}, this));
}
},
make_following_tab: function(data) {
make_following_tab: function() {
var $tab = $('.NB-tab-following', this.$modal).empty();
if (!data.following_profiles || !data.following_profiles.length) {
if (!this.model.following_profiles || !this.model.following_profiles.size()) {
var $ghost = $.make('div', { className: 'NB-ghost NB-modal-section' }, 'You have not yet subscribed to anybody\'s shared stories.');
$tab.append($ghost);
} else {
_.each(data.following_profiles, _.bind(function(profile) {
this.model.following_profiles.each(_.bind(function(profile) {
$tab.append(this.make_profile_badge(profile));
}, this));
}
@ -229,31 +231,31 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
var $badge = $.make('div', { className: "NB-profile-badge" }, [
$.make('div', { className: 'NB-profile-badge-actions' }),
$.make('div', { className: 'NB-profile-badge-photo' }, [
$.make('img', { src: profile.photo_url })
$.make('img', { src: profile.get('photo_url') })
]),
$.make('div', { className: 'NB-profile-badge-username' }, profile.username),
$.make('div', { className: 'NB-profile-badge-location' }, profile.location),
$.make('div', { className: 'NB-profile-badge-bio' }, profile.bio),
$.make('div', { className: 'NB-profile-badge-username' }, profile.get('username')),
$.make('div', { className: 'NB-profile-badge-location' }, profile.get('location')),
$.make('div', { className: 'NB-profile-badge-bio' }, profile.get('bio')),
$.make('div', { className: 'NB-profile-badge-stats' }, [
$.make('span', { className: 'NB-count' }, profile.shared_stories_count),
$.make('span', { className: 'NB-count' }, profile.get('shared_stories_count')),
'stories shared',
' &middot; ',
$.make('span', { className: 'NB-count' }, profile.following_count),
$.make('span', { className: 'NB-count' }, profile.get('following_count')),
'following',
' &middot; ',
$.make('span', { className: 'NB-count' }, profile.follower_count),
$.make('span', { className: 'NB-count' }, profile.get('follower_count')),
'followers'
])
]);
]).data('user_id', profile.get('user_id'));
var $actions;
if (_.contains(this.profile.following_user_ids, profile.user_id)) {
if (_.contains(this.profile.get('following_user_ids'), profile.get('user_id'))) {
$actions = $.make('div', {
className: 'NB-profile-badge-action-unfollow NB-modal-submit-button NB-modal-submit-close'
}, 'Following');
} else {
$actions = $.make('div', {
className: 'NB-profile-badge-action-unfollow NB-modal-submit-button NB-modal-submit-green'
className: 'NB-profile-badge-action-follow NB-modal-submit-button NB-modal-submit-green'
}, 'Follow');
}
$('.NB-profile-badge-actions', $badge).append($actions);
@ -322,6 +324,12 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
$modal_tabs.filter('.NB-modal-tab-'+newtab).addClass('NB-active');
$tabs.filter('.NB-tab-'+newtab).addClass('NB-active');
if (newtab == 'following') {
this.make_following_tab();
} else if (newtab == 'followers') {
this.make_followers_tab();
}
this.resize_modal();
},
@ -335,9 +343,10 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
var $service = $('.NB-friends-service-'+service, this.$modal);
$('.NB-friends-service-connect', $service).text('Disconnecting...');
this.model.disconnect_social_service(service, _.bind(function(data) {
this.make_find_friends_and_services(data);
this.make_profile_section(data);
this.make_profile_tab(data);
this.services = data.services;
this.make_find_friends_and_services();
this.make_profile_section();
this.make_profile_tab();
}, this));
},
@ -370,10 +379,11 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
'website': $('input[name=website]', this.$modal).val(),
'bio': $('input[name=bio]', this.$modal).val()
};
this.model.save_social_profile(data, _.bind(function() {
this.fetch_friends();
this.model.save_user_profile(data, _.bind(function() {
this.fetch_friends(_.bind(function() {
this.animate_profile_badge();
}, this));
this.switch_tab('findfriends');
this.animate_profile_badge();
}, this));
this.disable_save();
$('.NB-profile-save-button', this.$modal).text('Saving...');
@ -381,27 +391,51 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
animate_profile_badge: function($badge) {
$badge = $badge || $('.NB-friends-findfriends-profile .NB-profile-badge', this.$modal);
console.log(["$badge", $badge]);
_.delay(_.bind(function() {
$badge.css('backgroundColor', 'white').animate({
'backgroundColor': 'orange'
'backgroundColor': 'gold'
}, {
'queue': false,
'duration': 1200,
'easing': 'easeInQuad',
'duration': 600,
'easing': 'linear',
'complete': function() {
$badge.animate({
'backgroundColor': 'white'
}, {
'queue': false,
'duration': 650,
'duration': 1250,
'easing': 'easeOutQuad'
});
}
});
}, this), 200);
},
follow_user: function(user_id, $badge) {
this.model.follow_user(user_id, _.bind(function(data) {
this.make_profile_section();
var $button = $('.NB-modal-submit-button', $badge);
$button.text('Following');
$button.removeClass('NB-modal-submit-green')
.removeClass('NB-modal-submit-red')
.addClass('NB-modal-submit-close');
$button.removeClass('NB-profile-badge-action-follow')
.addClass('NB-profile-badge-action-unfollow');
}, this));
},
unfollow_user: function(user_id, $badge) {
this.model.unfollow_user(user_id, _.bind(function(data) {
this.make_profile_section();
var $button = $('.NB-modal-submit-button', $badge);
$button.text('Unfollowed');
$button.removeClass('NB-modal-submit-close')
.addClass('NB-modal-submit-red');
$button.removeClass('NB-profile-badge-action-unfollow')
.addClass('NB-profile-badge-action-follow');
}, this));
},
// ===========
// = Actions =
// ===========
@ -443,6 +477,18 @@ _.extend(NEWSBLUR.ReaderFriends.prototype, {
self.switch_tab('profile');
});
$.targetIs(e, { tagSelector: '.NB-profile-badge-action-follow' }, function($t, $p) {
e.preventDefault();
var $badge = $t.closest('.NB-profile-badge');
var user_id = $badge.data('user_id');
self.follow_user(user_id, $badge);
});
$.targetIs(e, { tagSelector: '.NB-profile-badge-action-unfollow' }, function($t, $p) {
e.preventDefault();
var $badge = $t.closest('.NB-profile-badge');
var user_id = $badge.data('user_id');
self.unfollow_user(user_id, $badge);
});
$.targetIs(e, { tagSelector: '.NB-profile-save-button' }, function($t, $p) {
e.preventDefault();

View file

@ -312,7 +312,7 @@ NEWSBLUR.log = function(msg) {
}
// Third argument can be TextNode or an array of additional $.make
if (args[2]) {
if (args[2] != null) {
if (typeof args[2] == 'string' || typeof args[2] == 'number') {
text = args[2];
} else if (typeof args[1] == 'object' && args[2].push) {
@ -339,7 +339,7 @@ NEWSBLUR.log = function(msg) {
}
}
}
if (text) {
if (text != null) {
$elem.html(text);
}
return $elem;

View file

@ -59,6 +59,8 @@
'opml-export' : "{% url opml-export %}",
'domain' : "{% current_domain %}"
};
NEWSBLUR.Models = {};
NEWSBLUR.Collections = {};
</script>
{% include_stylesheets "common" %}
@ -67,6 +69,7 @@
{% endblock head_js %}
{% block extra_head_js %}
{% endblock extra_head_js %}
{% block head %}{% endblock %}
<script type="text/javascript" charset="utf-8">
$.extend(NEWSBLUR.Preferences, {% if user_profile.preferences %}{{ user_profile.preferences|safe }}{% else %}{}{% endif %});

View file

@ -4,6 +4,10 @@
{% block title %}About NewsBlur{% endblock %}
{% block head %}
{% endblock %}
{% block content %}
<div class="NB-static-title">