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