diff --git a/fedireads/forms.py b/fedireads/forms.py index 75bc56ab2..dc59a8a9e 100644 --- a/fedireads/forms.py +++ b/fedireads/forms.py @@ -54,3 +54,9 @@ class EditUserForm(ModelForm): fields = ['avatar', 'name', 'summary'] help_texts = {f: None for f in fields} +class TagForm(ModelForm): + class Meta: + model = models.Tag + fields = ['name'] + help_texts = {f: None for f in fields} + diff --git a/fedireads/models/activity.py b/fedireads/models/activity.py index 58789dc58..93e70313a 100644 --- a/fedireads/models/activity.py +++ b/fedireads/models/activity.py @@ -47,6 +47,13 @@ class Review(Status): super().save(*args, **kwargs) +class Tag(FedireadsModel): + ''' freeform tags for books ''' + users = models.ManyToManyField('User') + books = models.ManyToManyField('Book') + name = models.CharField(max_length=140, unique=True) + + class Favorite(FedireadsModel): ''' fav'ing a post ''' user = models.ForeignKey('User', on_delete=models.PROTECT) diff --git a/fedireads/outgoing.py b/fedireads/outgoing.py index a87cc6f3b..e75e75767 100644 --- a/fedireads/outgoing.py +++ b/fedireads/outgoing.py @@ -7,7 +7,7 @@ from urllib.parse import urlencode from fedireads import activitypub from fedireads import models -from fedireads.status import create_review, create_status +from fedireads.status import create_review, create_status, create_tag from fedireads.remote_user import get_or_create_remote_user from fedireads.broadcast import get_recipients, broadcast @@ -160,6 +160,11 @@ def handle_review(user, book, name, content, rating): other_recipients = get_recipients(user, 'public', limit='other') broadcast(user, article_create_activity, other_recipients) +def handle_tag(user, book, name): + tag = create_tag(user, book, name) + + tag_activity = activitypub.get_tag(tag) + book_object = activitypub.get_book(book) def handle_comment(user, review, content): ''' respond to a review or status ''' diff --git a/fedireads/status.py b/fedireads/status.py index 2114e94d7..190167e9b 100644 --- a/fedireads/status.py +++ b/fedireads/status.py @@ -45,6 +45,21 @@ def create_status(user, content, reply_parent=None, mention_books=None): return status +def create_tag(user, possible_book, name): + ''' add a tag to a book ''' + book = get_or_create_book(possible_book) + + try: + # check for an existing tag with this text + tag = models.Tag.objects.get(name=name) + except models.Tag.DoesNotExist(): + # create a new one if there isn't an existing one + tag = models.Tag.objects.create(name=name) + tag.users.add(user) + tag.books.add(book) + return tag + + def sanitize(content): ''' remove invalid html from free text ''' parser = InputHtmlParser() diff --git a/fedireads/templates/book.html b/fedireads/templates/book.html index 624a3bb58..b62929453 100644 --- a/fedireads/templates/book.html +++ b/fedireads/templates/book.html @@ -12,6 +12,12 @@ {% if not reviews %}

No reviews yet!

{% endif %} +
+ {% csrf_token %} + + {{ tag_form.as_p }} + +
{% csrf_token %} diff --git a/fedireads/urls.py b/fedireads/urls.py index a2bbaf8f2..fb694461b 100644 --- a/fedireads/urls.py +++ b/fedireads/urls.py @@ -51,6 +51,7 @@ urlpatterns = [ # internal action endpoints re_path(r'^review/?$', views.review), + re_path(r'^tag/?$', views.tag), re_path(r'^comment/?$', views.comment), re_path(r'^favorite/(?P\d+)/?$', views.favorite), re_path( diff --git a/fedireads/utils/models.py b/fedireads/utils/models.py index 10a86aaff..f7cb8e955 100644 --- a/fedireads/utils/models.py +++ b/fedireads/utils/models.py @@ -11,7 +11,7 @@ class FedireadsModel(models.Model): def absolute_id(self): ''' constructs the absolute reference to any db object ''' base_path = 'https://%s' % DOMAIN - if self.user: + if hasattr(self, 'user'): base_path = self.user.absolute_id model_name = type(self).__name__.lower() return '%s/%s/%d' % (base_path, model_name, self.id) diff --git a/fedireads/views.py b/fedireads/views.py index e8af812e5..d0a8161c4 100644 --- a/fedireads/views.py +++ b/fedireads/views.py @@ -50,7 +50,8 @@ def home_tab(request, tab): if tab == 'home': # people you follow and direct mentions activities = activities.filter( - Q(user__in=following, privacy='public') | Q(mention_users=request.user) + Q(user__in=following, privacy='public') | \ + Q(mention_users=request.user) ) elif tab == 'local': # everyone on this instance @@ -272,6 +273,19 @@ def review(request): return redirect('/book/%s' % book_identifier) +@login_required +def tag(request): + ''' tag a book ''' + form = forms.ReviewForm(request.POST) + book_identifier = request.POST.get('book') + if not form.is_valid(): + return redirect('/book/%s' % book_identifier) + + name = form.data.get('name') + outgoing.handle_tag(request.user, book_identifier, name) + return redirect('/book/%s' % book_identifier) + + @login_required def comment(request): ''' respond to a book review '''