Moving forward.
[wolnelektury.git] / src / social / views.py
1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
3 #
4 from django.shortcuts import render, get_object_or_404, redirect
5 from django.http import HttpResponseForbidden, JsonResponse
6 from django.contrib.auth.decorators import login_required
7 from django.views.decorators.cache import never_cache
8 from django.views.decorators.http import require_POST
9 from django.views.generic.edit import FormView
10
11 from ajaxable.utils import AjaxableFormView
12
13 from catalogue.models import Book, Tag
14 import catalogue.models.tag
15 from social import forms
16 from wolnelektury.utils import is_ajax
17
18
19 # ====================
20 # = Shelf management =
21 # ====================
22
23
24 @require_POST
25 def like_book(request, slug):
26     if not request.user.is_authenticated:
27         return HttpResponseForbidden('Login required.')
28     book = get_object_or_404(Book, slug=slug)
29
30     book.like(request.user)
31
32     if is_ajax(request):
33         return JsonResponse({"success": True, "msg": "ok", "like": True})
34     else:
35         return redirect(book)
36
37
38 class AddSetView(FormView):
39     form_class = forms.AddSetForm
40     template_name = 'forms/form_detail.html'
41
42     def form_valid(self, form):
43         book, tag = form.save(self.request.user)
44
45         if is_ajax(self.request):
46             return JsonResponse(get_sets_for_book_ids([book.id], self.request.user))
47         else:
48             return redirect(book)
49
50
51 class RemoveSetView(AddSetView):
52     form_class = forms.RemoveSetForm
53
54
55 @require_POST
56 def unlike_book(request, slug):
57     if not request.user.is_authenticated:
58         return HttpResponseForbidden('Login required.')
59     book = get_object_or_404(Book, slug=slug)
60
61     book.unlike(request.user)
62
63     if is_ajax(request):
64         return JsonResponse({"success": True, "msg": "ok", "like": False})
65     else:
66         return redirect(book)
67
68
69 @login_required
70 def my_shelf(request):
71     if request.EXPERIMENTS['layout'].value:
72         template_name = 'social/2022/my_shelf.html'
73     else:
74         template_name = 'social/my_shelf.html'
75
76     tags = list(request.user.tag_set.all())
77     suggest = [t for t in tags if t.name]
78     print(suggest)
79         
80     return render(request, template_name, {
81         'tags': tags,
82         'books': Book.tagged.with_any(tags),
83         'suggest': suggest,
84     })
85
86
87 def get_sets_for_book_ids(book_ids, user):
88     data = {}
89     tagged = catalogue.models.tag.TagRelation.objects.filter(
90         tag__user=user,
91         #content_type= # for books,
92         object_id__in=book_ids
93     ).order_by('tag__sort_key')
94     for t in tagged:
95         # related?
96         item = data.setdefault(t.object_id, [])
97         if t.tag.name:
98             item.append({
99                 "slug": t.tag.slug,
100                 "url": t.tag.get_absolute_url(),
101                 "name": t.tag.name,
102             })
103     for b in book_ids:
104         if b not in data:
105             data[b] = None
106     return data
107     
108     
109
110
111 @never_cache
112 def my_liked(request):
113     if not request.user.is_authenticated:
114         return JsonResponse({})
115     try:
116         ids = [int(x) for x in request.GET.get('ids', '').split(',')]
117     except:
118         return JsonResponse({})
119     return JsonResponse(get_sets_for_book_ids(ids, request.user))
120
121
122 @never_cache
123 @login_required
124 def my_tags(request):
125     term = request.GET.get('term', '')
126     tags =             Tag.objects.filter(user=request.user).order_by('sort_key')
127     if term:
128         tags = tags.filter(name__icontains=term)
129     return JsonResponse(
130         [
131             t.name for t in tags
132         ], safe=False
133     )
134
135
136 class ObjectSetsFormView(AjaxableFormView):
137     form_class = forms.ObjectSetsForm
138     placeholdize = True
139     template = 'social/sets_form.html'
140     ajax_redirect = True
141     POST_login = True
142
143     def get_object(self, request, slug):
144         return get_object_or_404(Book, slug=slug)
145
146     def context_description(self, request, obj):
147         return obj.pretty_title()
148
149     def form_args(self, request, obj):
150         return (obj, request.user), {}