mirror of
https://github.com/fergalmoran/dss.git
synced 2026-01-06 08:54:12 +00:00
Added follow button to user list
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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: ->
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user