]> git.openstreetmap.org Git - osqa.git/blob - forum/templatetags/node_tags.py
We use ZeroClipboard to copy the permanent URL to the clipboard, this JS library...
[osqa.git] / forum / templatetags / node_tags.py
1 from datetime import datetime, timedelta\r
2 import re\r
3 \r
4 from forum.models import Question, Action\r
5 from django.utils.translation import ungettext, ugettext as _\r
6 from django.utils.html import strip_tags\r
7 from django.utils.encoding import smart_unicode\r
8 from django.utils.safestring import mark_safe\r
9 from django.core.urlresolvers import reverse\r
10 from django import template\r
11 from forum.actions import *\r
12 from forum import settings\r
13 \r
14 register = template.Library()\r
15 \r
16 @register.inclusion_tag('node/vote_buttons.html')\r
17 def vote_buttons(post, user):\r
18     context = dict(post=post, user_vote='none')\r
19 \r
20     if user.is_authenticated():\r
21         context['user_vote'] = {1: 'up', -1: 'down', None: 'none'}[VoteAction.get_for(user, post)]\r
22 \r
23     return context\r
24 \r
25 @register.inclusion_tag('node/accept_button.html')\r
26 def accept_button(answer, user):\r
27     if not settings.DISABLE_ACCEPTING_FEATURE:\r
28         return {\r
29             'can_accept': user.is_authenticated() and user.can_accept_answer(answer),\r
30             'answer': answer,\r
31             'user': user\r
32         }\r
33     else:\r
34         return ''\r
35 \r
36 @register.inclusion_tag('node/wiki_symbol.html')\r
37 def wiki_symbol(user, post):\r
38     context = {\r
39         'is_wiki': post.nis.wiki,\r
40         'post_type': post.friendly_name\r
41     }\r
42 \r
43     if post.nis.wiki:\r
44         if user.can_edit_post(post):\r
45             context['can_edit'] = True\r
46             context['edit_url'] = reverse('edit_' + post.node_type, kwargs={'id': post.id})\r
47         context['by'] = post.nstate.wiki.by.username\r
48         context['at'] = post.nstate.wiki.at\r
49 \r
50     return context\r
51 \r
52 @register.inclusion_tag('node/favorite_mark.html')\r
53 def favorite_mark(question, user):\r
54     try:\r
55         FavoriteAction.objects.get(canceled=False, node=question, user=user)\r
56         favorited = True\r
57     except:\r
58         favorited = False\r
59 \r
60     return {'favorited': favorited, 'favorite_count': question.favorite_count, 'question': question}\r
61 \r
62 @register.simple_tag\r
63 def post_classes(post):\r
64     classes = []\r
65 \r
66     if post.nis.deleted:\r
67         classes.append('deleted')\r
68 \r
69     if post.node_type == "answer":\r
70         if (not settings.DISABLE_ACCEPTING_FEATURE) and post.nis.accepted:\r
71             classes.append('accepted-answer')\r
72 \r
73         if post.author == post.question.author:\r
74             classes.append('answered-by-owner')\r
75 \r
76     return " ".join(classes)\r
77 \r
78 def post_control(text, url, command=False, withprompt=False, confirm=False, title="", copy=False):\r
79     classes = (command and "ajax-command" or " ") + (withprompt and " withprompt" or " ") + (confirm and " confirm" or " ") + \\r
80         (copy and " copy" or " ")\r
81     return {'text': text, 'url': url, 'classes': classes, 'title': title}\r
82 \r
83 @register.inclusion_tag('node/post_controls.html')\r
84 def post_controls(post, user):\r
85     controls = []\r
86     menu = []\r
87     post_type = post.node_type\r
88 \r
89     # We show the link tool if the post is an Answer. It is visible to Guests too.\r
90     if post_type == "answer":\r
91         # Answer permanent link tool\r
92         controls.append(post_control(_('permanent link'), reverse('answer_permanent_link', kwargs={'id' : post.id,}),\r
93                                      title=_("answer permanent link"), command=True, withprompt=True, copy=True))\r
94 \r
95         # Users should be able to award points for an answer. Users cannot award their own answers\r
96         if user != post.author and user.is_authenticated():\r
97             controls.append(post_control(_("award points"), reverse('award_points', kwargs={'user_id' : post.author.id,\r
98                                          'answer_id' : post.id}), title=_("award points to %s") % smart_unicode(post.author.username),\r
99                                          command=True, withprompt=True))\r
100 \r
101     # The other controls are visible only to authenticated users.\r
102     if user.is_authenticated():\r
103         try:\r
104             edit_url = reverse('edit_' + post_type, kwargs={'id': post.id})\r
105             if user.can_edit_post(post):\r
106                 controls.append(post_control(_('edit'), edit_url))\r
107             elif post_type == 'question' and user.can_retag_questions():\r
108                 controls.append(post_control(_('retag'), edit_url))\r
109         except:\r
110             pass\r
111 \r
112         if post_type == 'question':\r
113             if post.nis.closed and user.can_reopen_question(post):\r
114                 controls.append(post_control(_('reopen'), reverse('reopen', kwargs={'id': post.id}), command=True))\r
115             elif not post.nis.closed and user.can_close_question(post):\r
116                 controls.append(post_control(_('close'), reverse('close', kwargs={'id': post.id}), command=True, withprompt=True))\r
117 \r
118         if user.can_flag_offensive(post):\r
119             label = _('report')\r
120             \r
121             if user.can_view_offensive_flags(post):\r
122                 label =  "%s (%d)" % (label, post.flag_count)\r
123 \r
124             controls.append(post_control(label, reverse('flag_post', kwargs={'id': post.id}),\r
125                     command=True, withprompt=True, title=_("report as offensive (i.e containing spam, advertising, malicious text, etc.)")))\r
126 \r
127         if user.can_delete_post(post):\r
128             if post.nis.deleted:\r
129                 controls.append(post_control(_('undelete'), reverse('delete_post', kwargs={'id': post.id}),\r
130                         command=True, confirm=True))\r
131             else:\r
132                 controls.append(post_control(_('delete'), reverse('delete_post', kwargs={'id': post.id}),\r
133                         command=True, confirm=True))\r
134 \r
135         if user.can_delete_post(post):\r
136             menu.append(post_control(_('see revisions'),\r
137                         reverse('revisions',\r
138                         kwargs={'id': post.id}),\r
139                         command=False, confirm=False))\r
140 \r
141         if settings.WIKI_ON:\r
142             if (not post.nis.wiki) and user.can_wikify(post):\r
143                 menu.append(post_control(_('mark as community wiki'), reverse('wikify', kwargs={'id': post.id}),\r
144                             command=True, confirm=True))\r
145 \r
146             elif post.nis.wiki and user.can_cancel_wiki(post):\r
147                 menu.append(post_control(_('cancel community wiki'), reverse('wikify', kwargs={'id': post.id}),\r
148                             command=True, confirm=True))\r
149 \r
150         if post.node_type == "answer" and user.can_convert_to_comment(post):\r
151             menu.append(post_control(_('convert to comment'), reverse('convert_to_comment', kwargs={'id': post.id}),\r
152                         command=True, withprompt=True))\r
153         \r
154         if post.node_type == "answer" and user.can_convert_to_question(post):\r
155             menu.append(post_control(_('convert to question'), reverse('convert_to_question', kwargs={'id': post.id}),\r
156                         command=False, confirm=True))\r
157 \r
158         if user.is_superuser or user.is_staff:\r
159             plain_text = strip_tags(post.html)\r
160 \r
161             char_count = len(plain_text)\r
162             fullStr = plain_text + " "\r
163             left_trimmedStr = re.sub(re.compile(r"^[^\w]+", re.IGNORECASE), "", fullStr)\r
164             cleanedStr = re.sub(re.compile(r"[^\w]+", re.IGNORECASE), " ", left_trimmedStr)\r
165             splitString = cleanedStr.split(" ")\r
166             word_count = len(splitString) - 1\r
167 \r
168             metrics = mark_safe("<b>%s %s / %s %s</b>" % (char_count, ungettext('character', 'characters', char_count),\r
169                                         word_count, ungettext('word', 'words', word_count)))\r
170 \r
171             menu.append(post_control(metrics, "#", command=False, withprompt=False))\r
172 \r
173     return {'controls': controls, 'menu': menu, 'post': post, 'user': user}\r
174 \r
175 @register.inclusion_tag('node/comments.html')\r
176 def comments(post, user):\r
177     all_comments = post.comments.filter_state(deleted=False).order_by('added_at')\r
178 \r
179     if len(all_comments) <= 5:\r
180         top_scorers = all_comments\r
181     else:\r
182         top_scorers = sorted(all_comments, lambda c1, c2: cmp(c2.score, c1.score))[0:5]\r
183 \r
184     comments = []\r
185     showing = 0\r
186     for c in all_comments:\r
187         context = {\r
188             'can_delete': user.can_delete_comment(c),\r
189             'can_like': user.can_like_comment(c),\r
190             'can_edit': user.can_edit_comment(c),\r
191             'can_convert': user.can_convert_comment_to_answer(c)\r
192         }\r
193 \r
194         if c in top_scorers or c.is_reply_to(user):\r
195             context['top_scorer'] = True\r
196             showing += 1\r
197         \r
198         if context['can_like']:\r
199             context['likes'] = VoteAction.get_for(user, c) == 1\r
200 \r
201         context['user'] = c.user\r
202         context['comment'] = c.comment\r
203         context.update(dict(c.__dict__))\r
204         comments.append(context)\r
205 \r
206     return {\r
207         'comments': comments,\r
208         'post': post,\r
209         'can_comment': user.can_comment(post),\r
210         'max_length': settings.FORM_MAX_COMMENT_BODY,\r
211         'min_length': settings.FORM_MIN_COMMENT_BODY,\r
212         'show_gravatar': settings.FORM_GRAVATAR_IN_COMMENTS,\r
213         'showing': showing,\r
214         'total': len(all_comments),\r
215         'user': user,\r
216     }\r
217 \r
218 \r
219 @register.inclusion_tag("node/contributors_info.html")\r
220 def contributors_info(node, verb=None):\r
221     return {\r
222         'node_verb': verb and verb or ((node.node_type == "question") and _("asked") or (\r
223                     (node.node_type == "answer") and _("answered") or _("posted"))),\r
224         'node': node,\r
225     }\r
226 \r
227 @register.inclusion_tag("node/reviser_info.html")\r
228 def reviser_info(revision):\r
229     return {'revision': revision}\r