Merge master into img-playground. Image support with new management features. Missing...
[redakcja.git] / apps / catalogue / templatetags / wall.py
1 from __future__ import absolute_import
2
3 from datetime import timedelta
4 from django.db.models import Q
5 from django.core.urlresolvers import reverse
6 from django.contrib.comments.models import Comment
7 from django import template
8 from django.utils.translation import ugettext as _
9
10 from catalogue.models import Chunk, BookPublishRecord
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__title')
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 # TODO: marked for publishing
64
65
66 def published_wall(user=None, max_len=None, day=None):
67     qs = BookPublishRecord.objects.select_related('book__title')
68     if user:
69         # TODO: published my book
70         qs = qs.filter(Q(user=user))
71     if max_len is not None:
72         qs = qs[:max_len]
73     if day is not None:
74         next_day = day + timedelta(1)
75         qs = qs.filter(timestamp__gte=day, timestamp__lt=next_day)
76     for item in qs:
77         w = WallItem('publish')
78         w.header = _('Publication')
79         w.title = item.book.title
80         w.timestamp = item.timestamp
81         w.url = item.book.get_absolute_url()
82         w.user = item.user
83         w.email = item.user.email
84         yield w
85
86
87 def comments_wall(user=None, max_len=None, day=None):
88     qs = Comment.objects.filter(is_public=True).select_related().order_by('-submit_date')
89     if user:
90         # TODO: comments concerning my books
91         qs = qs.filter(Q(user=user))
92     if max_len is not None:
93         qs = qs[:max_len]
94     if day is not None:
95         next_day = day + timedelta(1)
96         qs = qs.filter(submit_date__gte=day, submit_date__lt=next_day)
97     for item in qs:
98         w  = WallItem('comment')
99         w.header = _('Comment')
100         w.title = item.content_object
101         w.summary = item.comment
102         w.url = item.content_object.get_absolute_url()
103         w.timestamp = item.submit_date
104         w.user = item.user
105         ui = item.userinfo
106         w.email = item.email
107         w.user_name = item.name
108         yield w
109
110
111 def big_wall(walls, max_len=None):
112     """
113         Takes some WallItem iterators and zips them into one big wall.
114         Input iterators must already be sorted by timestamp.
115     """
116     subwalls = []
117     for w in walls:
118         try:
119             subwalls.append([next(w), w])
120         except StopIteration:
121             pass
122
123     if max_len is None:
124         max_len = -1
125     while max_len and subwalls:
126         i, next_item = max(enumerate(subwalls), key=lambda x: x[1][0].timestamp)
127         yield next_item[0]
128         max_len -= 1
129         try:
130             next_item[0] = next(next_item[1])
131         except StopIteration:
132             del subwalls[i]
133
134
135 @register.inclusion_tag("catalogue/wall.html", takes_context=True)
136 def wall(context, user=None, max_len=100):
137     return {
138         "request": context['request'],
139         "STATIC_URL": context['STATIC_URL'],
140         "wall": big_wall([
141             changes_wall(user, max_len),
142             published_wall(user, max_len),
143             comments_wall(user, max_len),
144         ], max_len)}
145
146 @register.inclusion_tag("catalogue/wall.html", takes_context=True)
147 def day_wall(context, day):
148     return {
149         "request": context['request'],
150         "STATIC_URL": context['STATIC_URL'],
151         "wall": big_wall([
152             changes_wall(day=day),
153             published_wall(day=day),
154             comments_wall(day=day),
155         ])}