Added follow button to user list

This commit is contained in:
Fergal Moran
2013-07-04 21:45:58 +01:00
parent 94c5bf8e0e
commit 758772b331
7 changed files with 117 additions and 139 deletions

View File

@@ -14,44 +14,67 @@ from spa.models.userprofile import UserProfile
from spa.models.mix import Mix
class UserProfileResource(BackboneCompatibleResource):
mix_count = fields.IntegerField(readonly=True)
class UserResource(BackboneCompatibleResource):
class Meta:
queryset = UserProfile.objects.all()
resource_name = 'profile'
include_resource_uri = False
include_absolute_url = False
always_return_data = True
queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count')
resource_name = 'user'
excludes = ['is_active', 'is_staff', 'is_superuser', 'password']
ordering = ['mix_count']
authorization = DjangoAuthorization()
authentication = Authentication()
def get_object_list(self, request):
return super(UserProfileResource, self).get_object_list(request).annotate(mix_count=Count('mixes'))
favourites = fields.ToManyField(MixResource, 'favourites')
def _hydrateBitmapOption(self, source, comparator):
return True if (source & comparator) != 0 else False
def hydrate(self, bundle):
if 'activity_sharing_likes' in bundle.data:
likes = UserProfile.ACTIVITY_SHARE_LIKES if bundle.data['activity_sharing_likes'] else 0
favourites = UserProfile.ACTIVITY_SHARE_FAVOURITES if bundle.data['activity_sharing_favourites'] else 0
comments = UserProfile.ACTIVITY_SHARE_COMMENTS if bundle.data['activity_sharing_comments'] else 0
bundle.data['activity_sharing'] = (likes | favourites | comments)
del bundle.data['activity_sharing_likes']
del bundle.data['activity_sharing_favourites']
del bundle.data['activity_sharing_comments']
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d_.-]+)/favourites%s$" % (
self._meta.resource_name, trailing_slash()),
self.wrap_view('get_user_favourites'), name="api_get_user_favourites"),
url(r"^(?P<resource_name>%s)/(?P<pk>\d+)/$" % self._meta.resource_name,
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d_.-]+)/$" % self._meta.resource_name,
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
if 'activity_sharing_networks_facebook' in bundle.data:
facebook = UserProfile.ACTIVITY_SHARE_NETWORK_FACEBOOK if bundle.data[
'activity_sharing_networks_facebook'] else 0
twitter = UserProfile.ACTIVITY_SHARE_NETWORK_TWITTER if bundle.data[
'activity_sharing_networks_twitter'] else 0
bundle.data['activity_sharing_networks'] = (facebook | twitter)
del bundle.data['activity_sharing_networks_facebook']
del bundle.data['activity_sharing_networks_twitter']
"""
Stub method, not actually needed just yet
but take heed of note below when implementing in the future
def apply_sorting(self, obj_list, options=None):
#apply the sort to the obj_list, not the super call
"""
def apply_filters(self, request, applicable_filters):
semi_filtered = super(UserResource, self).apply_filters(request, applicable_filters)
q = request.GET.get('q', None)
if q is not None:
semi_filtered = semi_filtered.filter(
Q(user_first_name__icontains=q) |
Q(user_last_name__icontains=q)
)
return semi_filtered
def get_user_favourites(self, request, **kwargs):
try:
obj = self.cached_obj_get(bundle=self.build_bundle(request=request),
**self.remove_api_resource_names(kwargs))
except ObjectDoesNotExist:
return HttpGone()
except MultipleObjectsReturned:
return HttpMultipleChoices("More than one resource is found at this URI.")
mixes = MixResource()
return mixes.get_list(request, favourites__user=obj.get_profile())
def _patch_resource(self, bundle):
#Handle the patched items from backbone
if bundle.data['following']:
bundle.obj.add_follower(bundle.request.user.get_profile())
else:
bundle.obj.remove_follower(bundle.request.user.get_profile())
return bundle
def obj_update(self, bundle, skip_errors=False, **kwargs):
"""
@@ -64,7 +87,9 @@ class UserProfileResource(BackboneCompatibleResource):
if 'activity_sharing_favourites' in kwargs: del kwargs['activity_sharing_favourites']
if 'activity_sharing_comments' in kwargs: del kwargs['activity_sharing_comments']
return super(UserProfileResource, self).obj_update(bundle, skip_errors, **kwargs)
self._patch_resource(bundle)
return super(UserResource, self).obj_update(bundle, skip_errors, **kwargs)
def dehydrate(self, bundle):
del bundle.data['activity_sharing']
@@ -92,75 +117,29 @@ class UserProfileResource(BackboneCompatibleResource):
bundle.data['following_count'] = bundle.obj.following.count()
bundle.data['following'] = bundle.obj.is_follower(bundle.request.user)
bundle.data['url'] = bundle.obj.get_profile_url()
bundle.data['date_joined'] = bundle.obj.user.date_joined
bundle.data['last_login'] = bundle.obj.user.last_login
bundle.data['mix_count'] = bundle.obj.mix_count
return bundle
def dehydrate_mix_count(self, bundle):
return bundle.obj.mixes.count()
def hydrate(self, bundle):
if 'activity_sharing_likes' in bundle.data:
likes = UserProfile.ACTIVITY_SHARE_LIKES if bundle.data['activity_sharing_likes'] else 0
favourites = UserProfile.ACTIVITY_SHARE_FAVOURITES if bundle.data['activity_sharing_favourites'] else 0
comments = UserProfile.ACTIVITY_SHARE_COMMENTS if bundle.data['activity_sharing_comments'] else 0
bundle.data['activity_sharing'] = (likes | favourites | comments)
del bundle.data['activity_sharing_likes']
del bundle.data['activity_sharing_favourites']
del bundle.data['activity_sharing_comments']
if 'activity_sharing_networks_facebook' in bundle.data:
facebook = UserProfile.ACTIVITY_SHARE_NETWORK_FACEBOOK if bundle.data[
'activity_sharing_networks_facebook'] else 0
twitter = UserProfile.ACTIVITY_SHARE_NETWORK_TWITTER if bundle.data[
'activity_sharing_networks_twitter'] else 0
bundle.data['activity_sharing_networks'] = (facebook | twitter)
del bundle.data['activity_sharing_networks_facebook']
del bundle.data['activity_sharing_networks_twitter']
class UserResource(BackboneCompatibleResource):
profile = fields.ToOneField(UserProfileResource, attribute='userprofile', related_name='user', full=True)
class Meta:
queryset = User.objects.all()
resource_name = 'user'
excludes = ['is_active', 'is_staff', 'is_superuser', 'password']
ordering = ['mix_count']
authorization = DjangoAuthorization()
authentication = Authentication()
favourites = fields.ToManyField(MixResource, 'favourites')
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<userprofile__slug>[\w\d_.-]+)/favourites%s$" % (
self._meta.resource_name, trailing_slash()),
self.wrap_view('get_user_favourites'), name="api_get_user_favourites"),
url(r"^(?P<resource_name>%s)/(?P<pk>\d+)/$" % self._meta.resource_name,
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
url(r"^(?P<resource_name>%s)/(?P<userprofile__slug>[\w\d_.-]+)/$" % self._meta.resource_name,
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
def apply_filters(self, request, applicable_filters):
semi_filtered = super(UserResource, self).apply_filters(request, applicable_filters)
q = request.GET.get('q', None)
if q is not None:
semi_filtered = semi_filtered.filter(
Q(first_name__icontains=q) |
Q(last_name__icontains=q)
)
return semi_filtered
def apply_sorting(self, obj_list, options=None):
return super(UserResource, self).apply_sorting(obj_list, options)
def get_object_list(self, request):
return super(UserResource, self).get_object_list(request)
def get_user_favourites(self, request, **kwargs):
try:
obj = self.cached_obj_get(bundle=self.build_bundle(request=request),
**self.remove_api_resource_names(kwargs))
except ObjectDoesNotExist:
return HttpGone()
except MultipleObjectsReturned:
return HttpMultipleChoices("More than one resource is found at this URI.")
mixes = MixResource()
return mixes.get_list(request, favourites__user=obj.get_profile())
def dehydrate(self, bundle):
if bundle.obj.id != bundle.request.user.id:
del bundle.data['email']
del bundle.data['username']
return bundle
def obj_update(self, bundle, skip_errors=False, **kwargs):
#Handle the patched items from backbone
if bundle.data['following']:
bundle.obj.get_profile().add_follower(bundle.request.user.get_profile())
else:
bundle.obj.get_profile().remove_follower(bundle.request.user.get_profile())
return super(UserResource, self).obj_update(bundle, skip_errors, **kwargs)

View File

@@ -4,6 +4,7 @@ import urlparse
from django.contrib.auth.models import User
from django.core.exceptions import SuspiciousOperation
from django.db import models
from django.db.models import Count
from django_gravatar.helpers import has_gravatar, get_gravatar_url
from sorl.thumbnail import get_thumbnail
@@ -23,7 +24,7 @@ def avatar_name(instance, filename):
class UserProfileManager(models.Manager):
def get_query_set(self):
return super(UserProfileManager, self).get_query_set()
return super(UserProfileManager, self).get_query_set().annotate(mix_count=Count('mixes'))
class UserProfile(_BaseModel):

View File

@@ -44,6 +44,10 @@ define ['backbone', 'marionette', 'vent', 'utils'
true
App.addInitializer ->
@listenTo vent, "app:login", ->
utils.modal "/dlg/LoginView"
true
@listenTo vent, "mix:favourite", (model) ->
console.log "App(vent): mix:favourite"
model.save 'favourited', !model.get('favourited'), patch: true
@@ -54,6 +58,11 @@ define ['backbone', 'marionette', 'vent', 'utils'
model.save 'liked', !model.get('liked'), patch: true
true
@listenTo vent, "user:follow", (model)->
console.log "App(vent): user:follow"
model.save 'following', !model.get('following'), patch: true
true
@listenTo vent, "mix:share", (mode, model) ->
console.log "App(vent): mix:share"
if (mode == "facebook")
@@ -62,15 +71,6 @@ define ['backbone', 'marionette', 'vent', 'utils'
social.sharePageToTwitter(model);
true
@listenTo vent, "user:follow", (model)->
console.log "App(vent): user:follow"
model.save 'following', !model.get('following'), patch: true
true
@listenTo vent, "app:login", ->
utils.modal "/dlg/LoginView"
true
App.headerRegion.show(new HeaderView());
sidebarView = new SidebarView();
App.sidebarRegion.show(sidebarView)

View File

@@ -1,15 +1,14 @@
// Generated by CoffeeScript 1.6.2
// Generated by CoffeeScript 1.3.3
(function() {
define(['backbone', 'marionette', 'vent', 'utils', 'app.lib/router', 'app.lib/panningRegion', 'app.lib/realtimeController', 'app.lib/audioController', 'views/widgets/headerView', 'views/sidebar/sidebarView', 'models/mix/mixCollection'], function(Backbone, Marionette, vent, utils, DssRouter, PanningRegion, RealtimeController, AudioController, HeaderView, SidebarView, MixCollection) {
var App, sidebarView;
App = new Marionette.Application();
App.audioController = new AudioController();
App.realtimeController = new RealtimeController();
App.realtimeController.startSocketIO();
App.vent.on("routing:started", function() {
var enablePushState, pushState;
console.log("App(vent): routing:started");
enablePushState = true;
pushState = !!(enablePushState && window.history && window.history.pushState);
@@ -35,7 +34,6 @@
App.addInitializer(function() {
$(document).on("click", "a[href]:not([data-bypass])", function(evt) {
var href, root;
href = {
prop: $(this).prop("href"),
attr: $(this).attr("href")
@@ -50,6 +48,10 @@
return true;
});
App.addInitializer(function() {
this.listenTo(vent, "app:login", function() {
utils.modal("/dlg/LoginView");
return true;
});
this.listenTo(vent, "mix:favourite", function(model) {
console.log("App(vent): mix:favourite");
model.save('favourited', !model.get('favourited'), {
@@ -64,15 +66,6 @@
});
return true;
});
this.listenTo(vent, "mix:share", function(mode, model) {
console.log("App(vent): mix:share");
if (mode === "facebook") {
social.sharePageToFacebook(model);
} else if (mode === "twitter") {
social.sharePageToTwitter(model);
}
return true;
});
this.listenTo(vent, "user:follow", function(model) {
console.log("App(vent): user:follow");
model.save('following', !model.get('following'), {
@@ -80,8 +73,13 @@
});
return true;
});
return this.listenTo(vent, "app:login", function() {
utils.modal("/dlg/LoginView");
return this.listenTo(vent, "mix:share", function(mode, model) {
console.log("App(vent): mix:share");
if (mode === "facebook") {
social.sharePageToFacebook(model);
} else if (mode === "twitter") {
social.sharePageToTwitter(model);
}
return true;
});
});

View File

@@ -12,8 +12,8 @@ define ['app', 'moment', 'marionette', 'vent', 'text!/tpl/UserListItemView'],
humanise: (date)->
moment(date).fromNow()
intialize: =>
@listenTo(@model, 'change:profile.following', @render)
initialize: =>
@listenTo(@model, 'change:following', @render)
followUser: ->

View File

@@ -1,18 +1,18 @@
// Generated by CoffeeScript 1.6.2
// Generated by CoffeeScript 1.3.3
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['app', 'moment', 'marionette', 'vent', 'text!/tpl/UserListItemView'], function(App, moment, Marionette, vent, Template) {
var UserItemView, _ref;
var UserItemView;
UserItemView = (function(_super) {
__extends(UserItemView, _super);
function UserItemView() {
this.intialize = __bind(this.intialize, this); _ref = UserItemView.__super__.constructor.apply(this, arguments);
return _ref;
this.initialize = __bind(this.initialize, this);
return UserItemView.__super__.constructor.apply(this, arguments);
}
UserItemView.prototype.template = _.template(Template);
@@ -30,8 +30,8 @@
}
};
UserItemView.prototype.intialize = function() {
return this.listenTo(this.model, 'change:profile.following', this.render);
UserItemView.prototype.initialize = function() {
return this.listenTo(this.model, 'change:following', this.render);
};
UserItemView.prototype.followUser = function() {

View File

@@ -1,19 +1,19 @@
<td>
<a href="<%= profile.url %>"><%= profile.display_name %></a>
<a href="<%= url %>"><%= display_name %></a>
</td>
<td>
<a href="/user/<%= profile.slug %>"><%= profile.mix_count%></a>
<a href="/user/<%= slug %>"><%= mix_count%></a>
</td>
<td>
<a href="/user/<%= profile.slug %>/likes"><%= profile.like_count%></a>
<a href="/user/<%= slug %>/likes"><%= like_count%></a>
</td>
<td>
<a href="/user/<%= profile.slug %>/favourites"><%= profile.favourite_count%></a>
<a href="/user/<%= slug %>/favourites"><%= favourite_count%></a>
</td>
<td>
<a href="/user/<%= profile.slug %>/followers"><%= profile.follower_count %></a>
<a href="/user/<%= slug %>/followers"><%= follower_count %></a>
</td>
<td><%= profile.following_count %></td>
<td><%= following_count %></td>
<td><%= humanise(date_joined) %></td>
<td><%= humanise(last_login) %></td>
@@ -21,13 +21,13 @@
{% if user.is_authenticated %}
<button href="#"
id="follow-button"
class="follow-button btn btn-mini <% if (profile.following) { %> disabled <% } %>">
class="follow-button btn btn-mini <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% else %}
<button href="#"
id="follow-button-login"
class="follow-button btn btn-mini <% if (profile.following) { %> disabled <% } %>">
class="follow-button btn btn-mini <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% endif %}