diff --git a/media/js/src/modules/snipt.js b/media/js/src/modules/snipt.js index d92b0a2..01dab2e 100644 --- a/media/js/src/modules/snipt.js +++ b/media/js/src/modules/snipt.js @@ -32,6 +32,8 @@ events: { 'click a.copy': 'copyFromClick', 'click a.edit': 'edit', + 'click a.favorite': 'favoriteToggle', + 'hover a.favorite': 'favoriteHover', 'click a.embed': 'embedFromClick', 'click a.expand': 'expand', 'click .container': 'selectFromClick', @@ -174,13 +176,52 @@ }); return false; }, - favorite: function() { - + favoriteHover: function(e) { + if (e.type === 'mouseenter') { + if (this.$el.hasClass('favorited')) { + this.$favorite.text('Remove?'); + } else { + this.$favorite.text('Favorite?'); + } + } else { + if (this.$el.hasClass('favorited')) { + this.$favorite.text('Favorited'); + } else { + this.$favorite.text('Favorite'); + } + } }, - initFavorite: function() { - this.$favorite.click(function() { - return false; - }); + favoriteToggle: function() { + + var that = this; + + if (this.$el.hasClass('favorited')) { + $.ajax('/api/private/favorite/' + this.model.get('favorite_id'), { + type: 'delete', + success: function() { + that.$el.removeClass('favorited'); + that.$favorite.text('Removed.'); + }, + headers: { + 'Authorization': 'ApiKey ' + window.user + ':' + window.api_key + } + }); + } else { + $.ajax('/api/private/favorite/', { + data: '{"snipt": ' + this.model.get('id') + '}', + contentType: 'application/json', + type: 'post', + success: function(resp) { + that.$el.addClass('favorited'); + that.model.set({'favorite_id': resp['id']}, {'silent': true}); + that.$favorite.text('Favorited.'); + }, + headers: { + 'Authorization': 'ApiKey ' + window.user + ':' + window.api_key + } + }); + } + return false; }, initLocalVars: function() { this.$aside = $('aside', this.$el); @@ -205,10 +246,6 @@ window.ui_halted = false; window.from_modal = true; }); - - if (this.$favorite.length) { - this.initFavorite(); - } }, next: function() { if (!window.ui_halted) { @@ -353,6 +390,7 @@ created_formatted: $created.text(), embed_url: $('div.embed-url', $el).text(), absolute_url: $h1.attr('href'), + favorite_id: $el.data('favorite-id'), id: parseInt($el.attr('id').replace('snipt-', ''), 0), key: $('div.key', $el).text(), lexer: $('div.lexer', $el).text(), diff --git a/snipts/api.py b/snipts/api.py index 0469022..e1b021b 100644 --- a/snipts/api.py +++ b/snipts/api.py @@ -5,9 +5,9 @@ from tastypie.validation import Validation from tastypie.resources import ModelResource from django.contrib.auth.models import User from tastypie.models import create_api_key +from snipts.models import Favorite, Snipt from tastypie.cache import SimpleCache from tastypie.fields import ListField -from snipts.models import Snipt from taggit.models import Tag from django.db import models from tastypie import fields @@ -15,6 +15,17 @@ from tastypie import fields models.signals.post_save.connect(create_api_key, sender=User) +class FavoriteValidation(Validation): + def is_valid(self, bundle, request=None): + errors = {} + snipt = bundle.data['snipt'] + + if Favorite.objects.filter(user=request.user, snipt=snipt).count(): + errors['duplicate'] = 'User has already favorited this snipt.' + + return errors + + class PublicUserResource(ModelResource): class Meta: queryset = User.objects.all() @@ -188,3 +199,30 @@ class PrivateSniptResource(ModelResource): tags = bundle.data.get('tags_list', []) if tags != '': bundle.obj.tags.set(*parse_tags(tags)) +class PrivateFavoriteResource(ModelResource): + user = fields.ForeignKey(PrivateUserResource, 'user', full=True) + snipt = fields.ForeignKey(PrivateSniptResource, 'snipt', full=False) + + class Meta: + queryset = Favorite.objects.all().order_by('-created') + resource_name = 'favorite' + fields = ['id',] + validation = FavoriteValidation() + detail_allowed_methods = ['get', 'post', 'delete'] + list_allowed_methods = ['get', 'post',] + authentication = ApiKeyAuthentication() + authorization = Authorization() + ordering = ['created',] + # TODO max_limit does not work. + max_limit = 200 + always_return_data = True + cache = SimpleCache() + + def obj_create(self, bundle, request=None, **kwargs): + bundle.data['user'] = request.user + bundle.data['snipt'] = Snipt.objects.get(pk=bundle.data['snipt']) + return super(PrivateFavoriteResource, self).obj_create(bundle, request, + user=request.user, **kwargs) + + def apply_authorization_limits(self, request, object_list): + return object_list.filter(user=request.user) diff --git a/snipts/templates/snipts/snipt-list.html b/snipts/templates/snipts/snipt-list.html index 7d8ded9..42eeb0c 100644 --- a/snipts/templates/snipts/snipt-list.html +++ b/snipts/templates/snipts/snipt-list.html @@ -1,6 +1,8 @@ {% load humanize snipt_tags %} -
+{% snipt_is_favorited_by_user as 'is_favorited' %} + +
#{{ snipt.pk }}
@@ -37,7 +39,7 @@ {% if snipt.user != request.user and request.user.is_authenticated %}
  • - {% if snipt|is_favorited_by:request.user %} + {% if is_favorited %} Favorited {% else %} Favorite diff --git a/snipts/templatetags/snipt_tags.py b/snipts/templatetags/snipt_tags.py index 69fe2c8..fc0f4a1 100644 --- a/snipts/templatetags/snipt_tags.py +++ b/snipts/templatetags/snipt_tags.py @@ -1,14 +1,28 @@ from django import template +from templatetag_sugar.register import tag +from templatetag_sugar.parser import Variable, Constant + from snipts.models import Favorite register = template.Library() -@register.filter -def is_favorited_by(snipt, user): - try: - Favorite.objects.get(snipt=snipt, user=user) - return True - except Favorite.DoesNotExist: - return False +@tag(register, [Constant('as'), Variable()]) +def snipt_is_favorited_by_user(context, asvar): + + user = context['request'].user + snipt = context['snipt'] + + is_favorited = False + + if user.is_authenticated(): + if snipt.user != user: + try: + is_favorited = Favorite.objects.get(snipt=snipt, user=user).id + except Favorite.DoesNotExist: + pass + + context[asvar] = is_favorited + + return '' diff --git a/snipts/views.py b/snipts/views.py index baff5bd..897eadf 100644 --- a/snipts/views.py +++ b/snipts/views.py @@ -47,12 +47,13 @@ def list_user(request, username, tag_slug=None): snipts = Snipt.objects if user == request.user: - tags = tags.filter(snipt__user=user) public = False favorites = Favorite.objects.filter(user=user).values('snipt') favorites = [f['snipt'] for f in favorites] snipts = snipts.filter(Q(user=user) | Q(pk__in=favorites)) + + tags = tags.filter(Q(snipt__user=user) | Q(snipt__pk__in=favorites)) else: tags = tags.filter(snipt__user=user, snipt__public=True) snipts = snipts.filter(user=user, public=True) diff --git a/urls.py b/urls.py index 80aa759..205eae1 100644 --- a/urls.py +++ b/urls.py @@ -3,7 +3,6 @@ from registration.forms import RegistrationFormUniqueEmail from django.http import HttpResponseRedirect from django.conf.urls.defaults import * from django.contrib import admin -from django.conf import settings from tastypie.api import Api from snipts.api import * @@ -20,6 +19,7 @@ private_api = Api(api_name='private') private_api.register(PrivateSniptResource()) private_api.register(PrivateTagResource()) private_api.register(PrivateUserResource()) +private_api.register(PrivateFavoriteResource()) urlpatterns = patterns('',