486a2d6a7a30a11faf576449aab43ce4cdc8b410
[redakcja.git] / src / documents / templatetags / wall.py
1 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
3 #
4 from datetime import timedelta
5 from django.db.models import Q
6 from django.urls import reverse
7 from django import template
8 from django.utils.translation import gettext as _
9
10 from documents.models import Chunk, BookPublishRecord, Image, ImagePublishRecord
11
12 register = template.Library()
13
14
15 class WallItem(object):
16     title = ''
17     summary = ''
18     url = ''
19     timestamp = ''
20     user = None
21     user_name = ''
22     email = ''
23
24     def __init__(self, tag):
25         self.tag = tag
26
27     def get_email(self):
28         if self.user:
29             return self.user.email
30         else:
31             return self.email
32
33
34 def changes_wall(user=None, max_len=None, day=None):
35     qs = Chunk.change_model.objects.order_by('-created_at')
36     qs = qs.select_related('author', 'tree', 'tree__book')
37     if user is not None:
38         qs = qs.filter(Q(author=user) | Q(tree__user=user))
39     if max_len is not None:
40         qs = qs[:max_len]
41     if day is not None:
42         next_day = day + timedelta(1)
43         qs = qs.filter(created_at__gte=day, created_at__lt=next_day)
44     for item in qs:
45         tag = 'stage' if item.tags.count() else 'change'
46         chunk = item.tree
47         w = WallItem(tag)
48         if user and item.author != user:
49             w.header = _('Related edit')
50         else:
51             w.header = _('Edit')
52         w.title = chunk.pretty_name()
53         w.summary = item.description
54         w.url = reverse('wiki_editor', 
55                 args=[chunk.book.slug, chunk.slug]) + '?diff=%d' % item.revision
56         w.timestamp = item.created_at
57         w.user = item.author
58         w.user_name = item.author_name
59         w.email = item.author_email
60         yield w
61
62
63 def image_changes_wall(user=None, max_len=None, day=None):
64     qs = Image.change_model.objects.order_by('-created_at')
65     qs = qs.select_related('author', 'tree')
66     if user is not None:
67         qs = qs.filter(Q(author=user) | Q(tree__user=user))
68     if max_len is not None:
69         qs = qs[:max_len]
70     if day is not None:
71         next_day = day + timedelta(1)
72         qs = qs.filter(created_at__gte=day, created_at__lt=next_day)
73     for item in qs:
74         tag = 'stage' if item.tags.count() else 'change'
75         image = item.tree
76         w  = WallItem(tag)
77         if user and item.author != user:
78             w.header = _('Related edit')
79         else:
80             w.header = _('Edit')
81         w.title = image.title
82         w.summary = item.description
83         w.url = reverse('wiki_img_editor', 
84                 args=[image.slug]) + '?diff=%d' % item.revision
85         w.timestamp = item.created_at
86         w.user = item.author
87         w.user_name = item.author_name
88         w.email = item.author_email
89         yield w
90
91
92
93 # TODO: marked for publishing
94
95
96 def published_wall(user=None, max_len=None, day=None):
97     qs = BookPublishRecord.objects.select_related('book')
98     if user:
99         # TODO: published my book
100         qs = qs.filter(Q(user=user))
101     if max_len is not None:
102         qs = qs[:max_len]
103     if day is not None:
104         next_day = day + timedelta(1)
105         qs = qs.filter(timestamp__gte=day, timestamp__lt=next_day)
106     for item in qs:
107         w = WallItem('publish')
108         w.header = _('Publication')
109         w.title = item.book.title
110         w.timestamp = item.timestamp
111         w.url = item.book.get_absolute_url()
112         w.user = item.user
113         w.email = item.user.email
114         yield w
115
116
117 def image_published_wall(user=None, max_len=None, day=None):
118     qs = ImagePublishRecord.objects.select_related('image')
119     if user:
120         # TODO: published my book
121         qs = qs.filter(Q(user=user))
122     if max_len is not None:
123         qs = qs[:max_len]
124     if day is not None:
125         next_day = day + timedelta(1)
126         qs = qs.filter(timestamp__gte=day, timestamp__lt=next_day)
127     for item in qs:
128         w = WallItem('publish')
129         w.header = _('Publication')
130         w.title = item.image.title
131         w.timestamp = item.timestamp
132         w.url = item.image.get_absolute_url()
133         w.user = item.user
134         w.email = item.user.email
135         yield w
136
137
138 def big_wall(walls, max_len=None):
139     """
140         Takes some WallItem iterators and zips them into one big wall.
141         Input iterators must already be sorted by timestamp.
142     """
143     subwalls = []
144     for w in walls:
145         try:
146             subwalls.append([next(w), w])
147         except StopIteration:
148             pass
149
150     if max_len is None:
151         max_len = -1
152     while max_len and subwalls:
153         i, next_item = max(enumerate(subwalls), key=lambda x: x[1][0].timestamp)
154         yield next_item[0]
155         max_len -= 1
156         try:
157             next_item[0] = next(next_item[1])
158         except StopIteration:
159             del subwalls[i]
160
161
162 @register.inclusion_tag("documents/wall.html", takes_context=True)
163 def wall(context, user=None, max_len=100):
164     return {
165         "request": context['request'],
166         "STATIC_URL": context['STATIC_URL'],
167         "wall": big_wall([
168             changes_wall(user, max_len),
169             published_wall(user, max_len),
170             image_changes_wall(user, max_len),
171             image_published_wall(user, max_len),
172         ], max_len)}
173
174 @register.inclusion_tag("documents/wall.html", takes_context=True)
175 def day_wall(context, day):
176     return {
177         "request": context['request'],
178         "STATIC_URL": context['STATIC_URL'],
179         "wall": big_wall([
180             changes_wall(day=day),
181             published_wall(day=day),
182             image_changes_wall(day=day),
183             image_published_wall(day=day),
184         ])}