Show More
@@ -0,0 +1,19 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | from __future__ import unicode_literals | |
|
3 | ||
|
4 | from django.db import models, migrations | |
|
5 | ||
|
6 | ||
|
7 | class Migration(migrations.Migration): | |
|
8 | ||
|
9 | dependencies = [ | |
|
10 | ('boards', '0018_banner'), | |
|
11 | ] | |
|
12 | ||
|
13 | operations = [ | |
|
14 | migrations.AlterField( | |
|
15 | model_name='post', | |
|
16 | name='referenced_posts', | |
|
17 | field=models.ManyToManyField(db_index=True, to='boards.Post', null=True, related_name='refposts', blank=True), | |
|
18 | ), | |
|
19 | ] |
@@ -0,0 +1,19 b'' | |||
|
1 | {% extends "boards/thread.html" %} | |
|
2 | ||
|
3 | {% load i18n %} | |
|
4 | {% load static from staticfiles %} | |
|
5 | {% load board %} | |
|
6 | {% load tz %} | |
|
7 | ||
|
8 | {% block thread_content %} | |
|
9 | {% get_current_language as LANGUAGE_CODE %} | |
|
10 | {% get_current_timezone as TIME_ZONE %} | |
|
11 | ||
|
12 | <div class="thread"> | |
|
13 | {% for post in thread.get_top_level_replies %} | |
|
14 | {% post_view post moderator=moderator reply_link=True mode_tree=True %} | |
|
15 | {% endfor %} | |
|
16 | </div> | |
|
17 | ||
|
18 | <script src="{% static 'js/thread.js' %}"></script> | |
|
19 | {% endblock %} |
@@ -0,0 +1,27 b'' | |||
|
1 | from boards import settings | |
|
2 | from boards.views.thread import ThreadView | |
|
3 | ||
|
4 | TEMPLATE_TREE = 'boards/thread_tree.html' | |
|
5 | ||
|
6 | CONTEXT_OP = 'opening_post' | |
|
7 | CONTEXT_BUMPABLE = 'bumpable' | |
|
8 | ||
|
9 | ||
|
10 | class TreeThreadView(ThreadView): | |
|
11 | ||
|
12 | def get_template(self): | |
|
13 | return TEMPLATE_TREE | |
|
14 | ||
|
15 | def get_data(self, thread): | |
|
16 | params = dict() | |
|
17 | ||
|
18 | bumpable = thread.can_bump() | |
|
19 | params[CONTEXT_BUMPABLE] = bumpable | |
|
20 | max_posts = thread.max_posts | |
|
21 | ||
|
22 | params[CONTEXT_OP] = thread.get_opening_post() | |
|
23 | ||
|
24 | return params | |
|
25 | ||
|
26 | def get_mode(self): | |
|
27 | return 'tree' |
|
1 | NO CONTENT: modified file, binary diff hidden |
@@ -7,7 +7,7 b' msgid ""' | |||
|
7 | 7 | msgstr "" |
|
8 | 8 | "Project-Id-Version: PACKAGE VERSION\n" |
|
9 | 9 | "Report-Msgid-Bugs-To: \n" |
|
10 |
"POT-Creation-Date: 2015-05-1 |
|
|
10 | "POT-Creation-Date: 2015-05-19 15:44+0300\n" | |
|
11 | 11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
|
12 | 12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
|
13 | 13 | "Language-Team: LANGUAGE <LL@li.org>\n" |
@@ -189,7 +189,7 b' msgid "Create new thread"' | |||
|
189 | 189 | msgstr "Создать новую тему" |
|
190 | 190 | |
|
191 | 191 | #: templates/boards/all_threads.html:118 templates/boards/preview.html:16 |
|
192 |
#: templates/boards/thread_normal.html: |
|
|
192 | #: templates/boards/thread_normal.html:38 | |
|
193 | 193 | msgid "Post" |
|
194 | 194 | msgstr "Отправить" |
|
195 | 195 | |
@@ -199,7 +199,7 b' msgstr ""' | |||
|
199 | 199 | "Метки должны быть разделены пробелами. Текст или изображение обязательны." |
|
200 | 200 | |
|
201 | 201 | #: templates/boards/all_threads.html:126 |
|
202 |
#: templates/boards/thread_normal.html:4 |
|
|
202 | #: templates/boards/thread_normal.html:43 | |
|
203 | 203 | msgid "Text syntax" |
|
204 | 204 | msgstr "Синтаксис текста" |
|
205 | 205 | |
@@ -244,7 +244,6 b' msgid "tags"' | |||
|
244 | 244 | msgstr "метки" |
|
245 | 245 | |
|
246 | 246 | #: templates/boards/base.html:40 |
|
247 | #| msgid "Search" | |
|
248 | 247 | msgid "search" |
|
249 | 248 | msgstr "поиск" |
|
250 | 249 | |
@@ -298,15 +297,15 b' msgstr "\xd0\x98\xd0\xb7\xd0\xbc\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x82\xd1\x8c"' | |||
|
298 | 297 | msgid "Edit thread" |
|
299 | 298 | msgstr "Изменить тему" |
|
300 | 299 | |
|
301 |
#: templates/boards/post.html: |
|
|
300 | #: templates/boards/post.html:84 | |
|
302 | 301 | msgid "Replies" |
|
303 | 302 | msgstr "Ответы" |
|
304 | 303 | |
|
305 |
#: templates/boards/post.html: |
|
|
304 | #: templates/boards/post.html:97 templates/boards/thread.html:37 | |
|
306 | 305 | msgid "messages" |
|
307 | 306 | msgstr "сообщений" |
|
308 | 307 | |
|
309 |
#: templates/boards/post.html:9 |
|
|
308 | #: templates/boards/post.html:98 templates/boards/thread.html:38 | |
|
310 | 309 | msgid "images" |
|
311 | 310 | msgstr "изображений" |
|
312 | 311 | |
@@ -388,37 +387,40 b' msgstr "\xd0\x9c\xd0\xb5\xd1\x82\xd0\xba\xd0\xb8 \xd0\xbd\xd0\xb5 \xd0\xbd\xd0\xb0\xd0\xb9\xd0\xb4\xd0\xb5\xd0\xbd\xd1\x8b."' | |||
|
388 | 387 | msgid "All tags" |
|
389 | 388 | msgstr "Все метки" |
|
390 | 389 | |
|
391 |
#: templates/boards/thread.html: |
|
|
392 | msgid "Last update: " | |
|
393 | msgstr "Последнее обновление: " | |
|
394 | ||
|
395 | #: templates/boards/thread_gallery.html:19 | |
|
396 | #: templates/boards/thread_normal.html:13 | |
|
390 | #: templates/boards/thread.html:15 | |
|
397 | 391 | msgid "Normal mode" |
|
398 | 392 | msgstr "Нормальный режим" |
|
399 | 393 | |
|
400 |
#: templates/boards/thread |
|
|
401 | #: templates/boards/thread_normal.html:14 | |
|
394 | #: templates/boards/thread.html:16 | |
|
402 | 395 | msgid "Gallery mode" |
|
403 | 396 | msgstr "Режим галереи" |
|
404 | 397 | |
|
405 |
#: templates/boards/thread |
|
|
398 | #: templates/boards/thread.html:17 | |
|
399 | #| msgid "Normal mode" | |
|
400 | msgid "Tree mode" | |
|
401 | msgstr "Древовидный режим" | |
|
402 | ||
|
403 | #: templates/boards/thread.html:39 | |
|
404 | msgid "Last update: " | |
|
405 | msgstr "Последнее обновление: " | |
|
406 | ||
|
407 | #: templates/boards/thread_gallery.html:36 | |
|
406 | 408 | msgid "No images." |
|
407 | 409 | msgstr "Нет изображений." |
|
408 | 410 | |
|
409 |
#: templates/boards/thread_normal.html: |
|
|
411 | #: templates/boards/thread_normal.html:17 | |
|
410 | 412 | msgid "posts to bumplimit" |
|
411 | 413 | msgstr "сообщений до бамплимита" |
|
412 | 414 | |
|
413 |
#: templates/boards/thread_normal.html:3 |
|
|
415 | #: templates/boards/thread_normal.html:31 | |
|
414 | 416 | msgid "Reply to thread" |
|
415 | 417 | msgstr "Ответить в тему" |
|
416 | 418 | |
|
417 |
#: templates/boards/thread_normal.html:4 |
|
|
419 | #: templates/boards/thread_normal.html:44 | |
|
418 | 420 | msgid "Close form" |
|
419 | 421 | msgstr "Закрыть форму" |
|
420 | 422 | |
|
421 |
#: templates/boards/thread_normal.html: |
|
|
423 | #: templates/boards/thread_normal.html:58 templates/boards/thread_tree.html:22 | |
|
422 | 424 | msgid "Update" |
|
423 | 425 | msgstr "Обновить" |
|
424 | 426 |
@@ -51,6 +51,15 b" PARAMETER_NEED_OPEN_LINK = 'need_open_li" | |||
|
51 | 51 | PARAMETER_REPLY_LINK = 'reply_link' |
|
52 | 52 | PARAMETER_NEED_OP_DATA = 'need_op_data' |
|
53 | 53 | |
|
54 | POST_VIEW_PARAMS = ( | |
|
55 | 'need_op_data', | |
|
56 | 'reply_link', | |
|
57 | 'moderator', | |
|
58 | 'need_open_link', | |
|
59 | 'truncated', | |
|
60 | 'mode_tree', | |
|
61 | ) | |
|
62 | ||
|
54 | 63 | REFMAP_STR = '<a href="{}">>>{}</a>' |
|
55 | 64 | |
|
56 | 65 | |
@@ -171,7 +180,7 b' class Post(models.Model, Viewable):' | |||
|
171 | 180 | |
|
172 | 181 | referenced_posts = models.ManyToManyField('Post', symmetrical=False, |
|
173 | 182 | null=True, |
|
174 |
blank=True, related_name='r |
|
|
183 | blank=True, related_name='refposts', | |
|
175 | 184 | db_index=True) |
|
176 | 185 | refmap = models.TextField(null=True, blank=True) |
|
177 | 186 | threads = models.ManyToManyField('Thread', db_index=True) |
@@ -183,6 +192,9 b' class Post(models.Model, Viewable):' | |||
|
183 | 192 | def __str__(self): |
|
184 | 193 | return 'P#{}/{}'.format(self.id, self.title) |
|
185 | 194 | |
|
195 | def get_referenced_posts(self): | |
|
196 | return self.referenced_posts.order_by('pub_time') | |
|
197 | ||
|
186 | 198 | def get_title(self) -> str: |
|
187 | 199 | """ |
|
188 | 200 | Gets original post title or part of its text. |
@@ -228,8 +240,7 b' class Post(models.Model, Viewable):' | |||
|
228 | 240 | |
|
229 | 241 | return self.threads |
|
230 | 242 | |
|
231 | def get_view(self, moderator=False, need_open_link=False, | |
|
232 | truncated=False, reply_link=False, *args, **kwargs) -> str: | |
|
243 | def get_view(self, *args, **kwargs) -> str: | |
|
233 | 244 | """ |
|
234 | 245 | Renders post's HTML view. Some of the post params can be passed over |
|
235 | 246 | kwargs for the means of caching (if we view the thread, some params |
@@ -250,19 +261,21 b' class Post(models.Model, Viewable):' | |||
|
250 | 261 | elif not thread.can_bump(): |
|
251 | 262 | css_class += ' dead_post' |
|
252 | 263 | |
|
253 | return render_to_string('boards/post.html', { | |
|
264 | params = dict() | |
|
265 | for param in POST_VIEW_PARAMS: | |
|
266 | if param in kwargs: | |
|
267 | params[param] = kwargs[param] | |
|
268 | ||
|
269 | params.update({ | |
|
254 | 270 | PARAMETER_POST: self, |
|
255 | PARAMETER_MODERATOR: moderator, | |
|
256 | 271 | PARAMETER_IS_OPENING: is_opening, |
|
257 | 272 | PARAMETER_THREAD: thread, |
|
258 | 273 | PARAMETER_CSS_CLASS: css_class, |
|
259 | PARAMETER_NEED_OPEN_LINK: need_open_link, | |
|
260 | PARAMETER_TRUNCATED: truncated, | |
|
261 | 274 | PARAMETER_OP_ID: opening_post_id, |
|
262 | PARAMETER_REPLY_LINK: reply_link, | |
|
263 | PARAMETER_NEED_OP_DATA: kwargs.get(PARAMETER_NEED_OP_DATA) | |
|
264 | 275 | }) |
|
265 | 276 | |
|
277 | return render_to_string('boards/post.html', params) | |
|
278 | ||
|
266 | 279 | def get_search_view(self, *args, **kwargs): |
|
267 | 280 | return self.get_view(need_op_data=True, *args, **kwargs) |
|
268 | 281 |
@@ -156,6 +156,9 b' class Thread(models.Model):' | |||
|
156 | 156 | query = query.defer('poster_ip') |
|
157 | 157 | return query.all() |
|
158 | 158 | |
|
159 | def get_top_level_replies(self): | |
|
160 | return self.get_replies().exclude(refposts__threads__in=[self]) | |
|
161 | ||
|
159 | 162 | def get_replies_with_images(self, view_fields_only=False) -> list: |
|
160 | 163 | """ |
|
161 | 164 | Gets replies that have at least one image attached |
@@ -524,3 +524,10 b' ul {' | |||
|
524 | 524 | .post-button-form > button:hover { |
|
525 | 525 | text-decoration: underline; |
|
526 | 526 | } |
|
527 | ||
|
528 | .tree_reply > .post { | |
|
529 | margin-left: 1ex; | |
|
530 | margin-top: 1ex; | |
|
531 | border-left: solid 1px #777; | |
|
532 | border-right: solid 1px #777; | |
|
533 | } |
@@ -69,11 +69,19 b'' | |||
|
69 | 69 | {% endif %} |
|
70 | 70 | {% endautoescape %} |
|
71 | 71 | {% if post.is_referenced %} |
|
72 | <div class="refmap"> | |
|
73 | {% autoescape off %} | |
|
74 | {% trans "Replies" %}: {{ post.refmap }} | |
|
75 | {% endautoescape %} | |
|
76 | </div> | |
|
72 | {% if mode_tree %} | |
|
73 | <div class="tree_reply"> | |
|
74 | {% for refpost in post.get_referenced_posts %} | |
|
75 | {% post_view refpost mode_tree=True %} | |
|
76 | {% endfor %} | |
|
77 | </div> | |
|
78 | {% else %} | |
|
79 | <div class="refmap"> | |
|
80 | {% autoescape off %} | |
|
81 | {% trans "Replies" %}: {{ post.refmap }} | |
|
82 | {% endautoescape %} | |
|
83 | </div> | |
|
84 | {% endif %} | |
|
77 | 85 | {% endif %} |
|
78 | 86 | </div> |
|
79 | 87 | {% comment %} |
@@ -10,6 +10,17 b'' | |||
|
10 | 10 | - {{ site_name }}</title> |
|
11 | 11 | {% endblock %} |
|
12 | 12 | |
|
13 | {% block content %} | |
|
14 | <div class="image-mode-tab"> | |
|
15 | <a {% ifequal mode 'normal' %}class="current_mode"{% endifequal %} href="{% url 'thread' opening_post.id %}">{% trans 'Normal mode' %}</a>, | |
|
16 | <a {% ifequal mode 'gallery' %}class="current_mode"{% endifequal %} href="{% url 'thread_gallery' opening_post.id %}">{% trans 'Gallery mode' %}</a>, | |
|
17 | <a {% ifequal mode 'tree' %}class="current_mode"{% endifequal %} href="{% url 'thread_tree' opening_post.id %}">{% trans 'Tree mode' %}</a> | |
|
18 | </div> | |
|
19 | ||
|
20 | {% block thread_content %} | |
|
21 | {% endblock %} | |
|
22 | {% endblock %} | |
|
23 | ||
|
13 | 24 | {% block metapanel %} |
|
14 | 25 | |
|
15 | 26 | <span class="metapanel" |
@@ -11,15 +11,10 b'' | |||
|
11 | 11 | - {{ site_name }}</title> |
|
12 | 12 | {% endblock %} |
|
13 | 13 | |
|
14 | {% block content %} | |
|
14 | {% block thread_content %} | |
|
15 | 15 | {% get_current_language as LANGUAGE_CODE %} |
|
16 | 16 | {% get_current_timezone as TIME_ZONE %} |
|
17 | 17 | |
|
18 | <div class="image-mode-tab"> | |
|
19 | <a href="{% url 'thread' thread.get_opening_post.id %}">{% trans 'Normal mode' %}</a>, | |
|
20 | <a class="current_mode" href="{% url 'thread_gallery' thread.get_opening_post.id %}">{% trans 'Gallery mode' %}</a> | |
|
21 | </div> | |
|
22 | ||
|
23 | 18 | <div id="posts-table"> |
|
24 | 19 | {% if posts %} |
|
25 | 20 | {% for post in posts %} |
@@ -5,15 +5,10 b'' | |||
|
5 | 5 | {% load board %} |
|
6 | 6 | {% load tz %} |
|
7 | 7 | |
|
8 | {% block content %} | |
|
8 | {% block thread_content %} | |
|
9 | 9 | {% get_current_language as LANGUAGE_CODE %} |
|
10 | 10 | {% get_current_timezone as TIME_ZONE %} |
|
11 | 11 | |
|
12 | <div class="image-mode-tab"> | |
|
13 | <a class="current_mode" href="{% url 'thread' opening_post.id %}">{% trans 'Normal mode' %}</a>, | |
|
14 | <a href="{% url 'thread_gallery' opening_post.id %}">{% trans 'Gallery mode' %}</a> | |
|
15 | </div> | |
|
16 | ||
|
17 | 12 | {% if bumpable and thread.has_post_limit %} |
|
18 | 13 | <div class="bar-bg"> |
|
19 | 14 | <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress"> |
@@ -31,10 +31,12 b" urlpatterns = patterns(''," | |||
|
31 | 31 | tag_threads.TagView.as_view(), name='tag'), |
|
32 | 32 | |
|
33 | 33 | # /boards/thread/ |
|
34 |
url(r'^thread/(?P<post_id>\d+)/$', views.thread. |
|
|
34 | url(r'^thread/(?P<post_id>\d+)/$', views.thread.NormalThreadView.as_view(), | |
|
35 | 35 | name='thread'), |
|
36 |
url(r'^thread/(?P<post_id>\d+)/mode/gallery/$', views.thread. |
|
|
36 | url(r'^thread/(?P<post_id>\d+)/mode/gallery/$', views.thread.GalleryThreadView.as_view(), | |
|
37 | 37 | name='thread_gallery'), |
|
38 | url(r'^thread/(?P<post_id>\d+)/mode/tree/$', views.thread.TreeThreadView.as_view(), | |
|
39 | name='thread_tree'), | |
|
38 | 40 | # /feed/ |
|
39 | 41 | url(r'^feed/$', views.feed.FeedView.as_view(), name='feed'), |
|
40 | 42 | url(r'^feed/page/(?P<page>\w+)/$', views.feed.FeedView.as_view(), |
@@ -1,3 +1,4 b'' | |||
|
1 | 1 | from boards.views.thread.thread import ThreadView |
|
2 | 2 | from boards.views.thread.normal import NormalThreadView |
|
3 | 3 | from boards.views.thread.gallery import GalleryThreadView |
|
4 | from boards.views.thread.tree import TreeThreadView |
@@ -3,6 +3,7 b' from boards.views.thread import ThreadVi' | |||
|
3 | 3 | TEMPLATE_GALLERY = 'boards/thread_gallery.html' |
|
4 | 4 | |
|
5 | 5 | CONTEXT_POSTS = 'posts' |
|
6 | CONTEXT_OP = 'opening_post' | |
|
6 | 7 | |
|
7 | 8 | |
|
8 | 9 | class GalleryThreadView(ThreadView): |
@@ -15,5 +16,9 b' class GalleryThreadView(ThreadView):' | |||
|
15 | 16 | |
|
16 | 17 | params[CONTEXT_POSTS] = thread.get_replies_with_images( |
|
17 | 18 | view_fields_only=True) |
|
19 | params[CONTEXT_OP] = thread.get_opening_post() | |
|
18 | 20 | |
|
19 | 21 | return params |
|
22 | ||
|
23 | def get_mode(self): | |
|
24 | return 'gallery' |
@@ -14,6 +14,9 b' class NormalThreadView(ThreadView):' | |||
|
14 | 14 | def get_template(self): |
|
15 | 15 | return TEMPLATE_NORMAL |
|
16 | 16 | |
|
17 | def get_mode(self): | |
|
18 | return 'normal' | |
|
19 | ||
|
17 | 20 | def get_data(self, thread): |
|
18 | 21 | params = dict() |
|
19 | 22 |
@@ -21,6 +21,7 b" CONTEXT_WS_PROJECT = 'ws_project'" | |||
|
21 | 21 | CONTEXT_WS_HOST = 'ws_host' |
|
22 | 22 | CONTEXT_WS_PORT = 'ws_port' |
|
23 | 23 | CONTEXT_WS_TIME = 'ws_token_time' |
|
24 | CONTEXT_MODE = 'mode' | |
|
24 | 25 | |
|
25 | 26 | FORM_TITLE = 'title' |
|
26 | 27 | FORM_TEXT = 'text' |
@@ -51,6 +52,7 b' class ThreadView(BaseBoardView, PostMixi' | |||
|
51 | 52 | params[CONTEXT_FORM] = form |
|
52 | 53 | params[CONTEXT_LASTUPDATE] = str(thread_to_show.last_edit_time) |
|
53 | 54 | params[CONTEXT_THREAD] = thread_to_show |
|
55 | params[CONTEXT_MODE] = self.get_mode() | |
|
54 | 56 | |
|
55 | 57 | if settings.get_bool('External', 'WebsocketsEnabled'): |
|
56 | 58 | token_time = format(timezone.now(), u'U') |
@@ -129,3 +131,6 b' class ThreadView(BaseBoardView, PostMixi' | |||
|
129 | 131 | """ |
|
130 | 132 | |
|
131 | 133 | pass |
|
134 | ||
|
135 | def get_mode(self): | |
|
136 | pass |
General Comments 0
You need to be logged in to leave comments.
Login now