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.
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 _
10 from documents.models import Chunk, BookPublishRecord, Image, ImagePublishRecord
12 register = template.Library()
15 class WallItem(object):
24 def __init__(self, tag):
29 return self.user.email
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')
38 qs = qs.filter(Q(author=user) | Q(tree__user=user))
39 if max_len is not None:
42 next_day = day + timedelta(1)
43 qs = qs.filter(created_at__gte=day, created_at__lt=next_day)
45 tag = 'stage' if item.tags.count() else 'change'
48 if user and item.author != user:
49 w.header = _('Related 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
58 w.user_name = item.author_name
59 w.email = item.author_email
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')
67 qs = qs.filter(Q(author=user) | Q(tree__user=user))
68 if max_len is not None:
71 next_day = day + timedelta(1)
72 qs = qs.filter(created_at__gte=day, created_at__lt=next_day)
74 tag = 'stage' if item.tags.count() else 'change'
77 if user and item.author != user:
78 w.header = _('Related edit')
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
87 w.user_name = item.author_name
88 w.email = item.author_email
93 # TODO: marked for publishing
96 def published_wall(user=None, max_len=None, day=None):
97 qs = BookPublishRecord.objects.select_related('book')
99 # TODO: published my book
100 qs = qs.filter(Q(user=user))
101 if max_len is not None:
104 next_day = day + timedelta(1)
105 qs = qs.filter(timestamp__gte=day, timestamp__lt=next_day)
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()
113 w.email = item.user.email
117 def image_published_wall(user=None, max_len=None, day=None):
118 qs = ImagePublishRecord.objects.select_related('image')
120 # TODO: published my book
121 qs = qs.filter(Q(user=user))
122 if max_len is not None:
125 next_day = day + timedelta(1)
126 qs = qs.filter(timestamp__gte=day, timestamp__lt=next_day)
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()
134 w.email = item.user.email
138 def big_wall(walls, max_len=None):
140 Takes some WallItem iterators and zips them into one big wall.
141 Input iterators must already be sorted by timestamp.
146 subwalls.append([next(w), w])
147 except StopIteration:
152 while max_len and subwalls:
153 i, next_item = max(enumerate(subwalls), key=lambda x: x[1][0].timestamp)
157 next_item[0] = next(next_item[1])
158 except StopIteration:
162 @register.inclusion_tag("documents/wall.html", takes_context=True)
163 def wall(context, user=None, max_len=100):
165 "request": context['request'],
166 "STATIC_URL": context['STATIC_URL'],
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),
174 @register.inclusion_tag("documents/wall.html", takes_context=True)
175 def day_wall(context, day):
177 "request": context['request'],
178 "STATIC_URL": context['STATIC_URL'],
180 changes_wall(day=day),
181 published_wall(day=day),
182 image_changes_wall(day=day),
183 image_published_wall(day=day),