Show More
@@ -1,74 +1,80 b'' | |||
|
1 | 1 | {% load i18n %} |
|
2 | 2 | {% load board %} |
|
3 | 3 | |
|
4 | 4 | {% spaceless %} |
|
5 | 5 | {% if post.thread_new.archived %} |
|
6 | 6 | <div class="post archive_post" id="{{ post.id }}"> |
|
7 | 7 | {% elif post.thread_new.can_bump %} |
|
8 | 8 | <div class="post" id="{{ post.id }}"> |
|
9 | 9 | {% else %} |
|
10 | 10 | <div class="post dead_post" id="{{ post.id }}"> |
|
11 | 11 | {% endif %} |
|
12 | 12 | |
|
13 | 13 | {% if post.image %} |
|
14 | 14 | <div class="image"> |
|
15 | 15 | <a |
|
16 | 16 | class="thumb" |
|
17 | 17 | href="{{ post.image.url }}"><img |
|
18 | 18 | src="{{ post.image.url_200x150 }}" |
|
19 | 19 | alt="{{ post.id }}" |
|
20 | 20 | width="{{ post.image_pre_width }}" |
|
21 | 21 | height="{{ post.image_pre_height }}" |
|
22 | 22 | data-width="{{ post.image_width }}" |
|
23 | 23 | data-height="{{ post.image_height }}"/> |
|
24 | 24 | </a> |
|
25 | 25 | </div> |
|
26 | 26 | {% endif %} |
|
27 | 27 | <div class="message"> |
|
28 | 28 | <div class="post-info"> |
|
29 | 29 | <span class="title">{{ post.title }}</span> |
|
30 | 30 | <a class="post_id" href="{% post_url post.id %}"> |
|
31 | 31 | ({{ post.id }}) </a> |
|
32 | 32 | [<span class="pub_time">{{ post.pub_time }}</span>] |
|
33 | [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}') | |
|
34 | ; return false;">>></a>] | |
|
33 | {% if not truncated %} | |
|
34 | [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}') | |
|
35 | ; return false;">>></a>] | |
|
36 | {% endif %} | |
|
37 | {% if need_open_link %} | |
|
38 | [<a class="link" href=" | |
|
39 | {% url 'thread' post.id %}#form">{% trans "Reply" %}</a>] | |
|
40 | {% endif %} | |
|
35 | 41 | |
|
36 | 42 | {% if moderator %} |
|
37 | 43 | <span class="moderator_info"> |
|
38 |
|
|
|
44 | [<a href="{% url 'delete' post_id=post.id %}" | |
|
39 | 45 | >{% trans 'Delete' %}</a>] |
|
40 |
|
|
|
41 |
|
|
|
46 | ({{ post.poster_ip }}) | |
|
47 | [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}" | |
|
42 | 48 | >{% trans 'Ban IP' %}</a>] |
|
43 |
|
|
|
49 | </span> | |
|
44 | 50 | {% endif %} |
|
45 | 51 | </div> |
|
46 | 52 | {% autoescape off %} |
|
47 | 53 | {% if truncated %} |
|
48 | 54 | {{ post.text.rendered|truncatewords_html:50 }} |
|
49 | 55 | {% else %} |
|
50 | 56 | {{ post.text.rendered }} |
|
51 | 57 | {% endif %} |
|
52 | 58 | {% endautoescape %} |
|
53 | 59 | {% if post.is_referenced %} |
|
54 | 60 | <div class="refmap"> |
|
55 | {% trans "Replies" %}: | |
|
56 | {% for ref_post in post.get_sorted_referenced_posts %} | |
|
57 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a | |
|
58 | >{% if not forloop.last %},{% endif %} | |
|
59 | {% endfor %} | |
|
61 | {% trans "Replies" %}: | |
|
62 | {% for ref_post in post.get_sorted_referenced_posts %} | |
|
63 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a | |
|
64 | >{% if not forloop.last %},{% endif %} | |
|
65 | {% endfor %} | |
|
60 | 66 | </div> |
|
61 | 67 | {% endif %} |
|
62 | 68 | </div> |
|
63 | 69 | {% if post.is_opening and post.thread_new.tags.exists %} |
|
64 | 70 | <div class="metadata"> |
|
65 | 71 | <span class="tags"> |
|
66 | 72 | {% for tag in post.thread_new.get_tags %} |
|
67 | 73 | <a class="tag" href="{% url 'tag' tag.name %}"> |
|
68 | 74 | #{{ tag.name }}</a>{% if not forloop.last %},{% endif %} |
|
69 | 75 | {% endfor %} |
|
70 | 76 | </span> |
|
71 | 77 | </div> |
|
72 | 78 | {% endif %} |
|
73 | 79 | </div> |
|
74 | 80 | {% endspaceless %} |
@@ -1,254 +1,149 b'' | |||
|
1 | 1 | {% extends "boards/base.html" %} |
|
2 | 2 | |
|
3 | 3 | {% load i18n %} |
|
4 | 4 | {% load cache %} |
|
5 | 5 | {% load board %} |
|
6 | 6 | {% load static %} |
|
7 | 7 | |
|
8 | 8 | {% block head %} |
|
9 | 9 | {% if tag %} |
|
10 | 10 | <title>Neboard - {{ tag.name }}</title> |
|
11 | 11 | {% else %} |
|
12 | 12 | <title>Neboard</title> |
|
13 | 13 | {% endif %} |
|
14 | 14 | |
|
15 | 15 | {% if current_page.has_previous %} |
|
16 | 16 | <link rel="prev" href=" |
|
17 | 17 | {% if tag %} |
|
18 | 18 | {% url "tag" tag_name=tag page=current_page.previous_page_number %} |
|
19 | 19 | {% else %} |
|
20 | 20 | {% url "index" page=current_page.previous_page_number %} |
|
21 | 21 | {% endif %} |
|
22 | 22 | " /> |
|
23 | 23 | {% endif %} |
|
24 | 24 | {% if current_page.has_next %} |
|
25 | 25 | <link rel="next" href=" |
|
26 | 26 | {% if tag %} |
|
27 | 27 | {% url "tag" tag_name=tag page=current_page.next_page_number %} |
|
28 | 28 | {% else %} |
|
29 | 29 | {% url "index" page=current_page.next_page_number %} |
|
30 | 30 | {% endif %} |
|
31 | 31 | " /> |
|
32 | 32 | {% endif %} |
|
33 | 33 | |
|
34 | 34 | {% endblock %} |
|
35 | 35 | |
|
36 | 36 | {% block content %} |
|
37 | 37 | |
|
38 | 38 | {% get_current_language as LANGUAGE_CODE %} |
|
39 | 39 | |
|
40 | 40 | {% if tag %} |
|
41 | 41 | <div class="tag_info"> |
|
42 | 42 | <h2> |
|
43 | 43 | {% if tag in user.fav_tags.all %} |
|
44 | 44 | <a href="{% url 'tag_unsubscribe' tag.name %}?next={{ request.path }}" |
|
45 | 45 | class="fav">β </a> |
|
46 | 46 | {% else %} |
|
47 | 47 | <a href="{% url 'tag_subscribe' tag.name %}?next={{ request.path }}" |
|
48 | 48 | class="not_fav">β </a> |
|
49 | 49 | {% endif %} |
|
50 | 50 | #{{ tag.name }} |
|
51 | 51 | </h2> |
|
52 | 52 | </div> |
|
53 | 53 | {% endif %} |
|
54 | 54 | |
|
55 | 55 | {% if threads %} |
|
56 | 56 | {% if current_page.has_previous %} |
|
57 | 57 | <div class="page_link"> |
|
58 | 58 | <a href=" |
|
59 | 59 | {% if tag %} |
|
60 | 60 | {% url "tag" tag_name=tag page=current_page.previous_page_number %} |
|
61 | 61 | {% else %} |
|
62 | 62 | {% url "index" page=current_page.previous_page_number %} |
|
63 | 63 | {% endif %} |
|
64 | 64 | ">{% trans "Previous page" %}</a> |
|
65 | 65 | </div> |
|
66 | 66 | {% endif %} |
|
67 | 67 | |
|
68 | 68 | {% for thread in threads %} |
|
69 | 69 | {% cache 600 thread_short thread.thread.id thread.thread.last_edit_time moderator LANGUAGE_CODE %} |
|
70 | 70 | <div class="thread"> |
|
71 |
|
|
|
72 | <div class="post" id="{{ thread.op.id }}"> | |
|
73 | {% else %} | |
|
74 | <div class="post dead_post" id="{{ thread.op.id }}"> | |
|
75 | {% endif %} | |
|
76 | {% if thread.op.image %} | |
|
77 | <div class="image"> | |
|
78 | <a class="thumb" | |
|
79 | href="{{ thread.op.image.url }}"><img | |
|
80 | src="{{ thread.op.image.url_200x150 }}" | |
|
81 | alt="{{ thread.op.id }}" | |
|
82 | width="{{ thread.op.image_pre_width }}" | |
|
83 | height="{{ thread.op.image_pre_height }}" | |
|
84 | data-width="{{ thread.op.image_width }}" | |
|
85 | data-height="{{ thread.op.image_height }}"/> | |
|
86 | </a> | |
|
87 | </div> | |
|
88 | {% endif %} | |
|
89 | <div class="message"> | |
|
90 | <div class="post-info"> | |
|
91 | <span class="title">{{ thread.op.title }}</span> | |
|
92 | <a class="post_id" href="{% url 'thread' thread.op.id %}" | |
|
93 | > ({{ thread.op.id }})</a> | |
|
94 | [{{ thread.op.pub_time }}] | |
|
95 | [<a class="link" href=" | |
|
96 | {% url 'thread' thread.op.id %}#form" | |
|
97 | >{% trans "Reply" %}</a>] | |
|
98 | ||
|
99 | {% if moderator %} | |
|
100 | <span class="moderator_info"> | |
|
101 | [<a href=" | |
|
102 | {% url 'delete' post_id=thread.op.id %}?next={{ request.path }}" | |
|
103 | >{% trans 'Delete' %}</a>] | |
|
104 | ({{ thread.op.poster_ip }}) | |
|
105 | [<a href=" | |
|
106 | {% url 'ban' post_id=thread.op.id %}?next={{ request.path }}" | |
|
107 | >{% trans 'Ban IP' %}</a>] | |
|
108 | </span> | |
|
109 | {% endif %} | |
|
110 | </div> | |
|
111 | {% autoescape off %} | |
|
112 | {{ thread.op.text.rendered|truncatewords_html:50 }} | |
|
113 | {% endautoescape %} | |
|
114 | {% if thread.op.is_referenced %} | |
|
115 | <div class="refmap"> | |
|
116 | {% trans "Replies" %}: | |
|
117 | {% for ref_post in thread.op.get_sorted_referenced_posts %} | |
|
118 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a | |
|
119 | >{% if not forloop.last %},{% endif %} | |
|
120 | {% endfor %} | |
|
121 | </div> | |
|
122 | {% endif %} | |
|
123 | </div> | |
|
124 | <div class="metadata"> | |
|
125 | {{ thread.thread.get_images_count }} {% trans 'images' %}. | |
|
126 | {% if thread.thread.tags %} | |
|
127 | <span class="tags"> | |
|
128 | {% for tag in thread.thread.get_tags %} | |
|
129 | <a class="tag" href=" | |
|
130 | {% url 'tag' tag_name=tag.name %}"> | |
|
131 | #{{ tag.name }}</a | |
|
132 | >{% if not forloop.last %},{% endif %} | |
|
133 | {% endfor %} | |
|
134 | </span> | |
|
135 | {% endif %} | |
|
136 | </div> | |
|
137 | </div> | |
|
71 | {% post_view_truncated thread.op True %} | |
|
138 | 72 | {% if thread.last_replies.exists %} |
|
139 | 73 | {% if thread.skipped_replies %} |
|
140 | 74 | <div class="skipped_replies"> |
|
141 | 75 | <a href="{% url 'thread' thread.op.id %}"> |
|
142 | 76 | {% blocktrans with count=thread.skipped_replies %}Skipped {{ count }} replies. Open thread to see all replies.{% endblocktrans %} |
|
143 | 77 | </a> |
|
144 | 78 | </div> |
|
145 | 79 | {% endif %} |
|
146 | 80 | <div class="last-replies"> |
|
147 | 81 | {% for post in thread.last_replies %} |
|
148 |
{% |
|
|
149 | <div class="post" id="{{ post.id }}"> | |
|
150 | {% else %} | |
|
151 | <div class="post dead_post" id="{{ post.id }}"> | |
|
152 | {% endif %} | |
|
153 | {% if post.image %} | |
|
154 | <div class="image"> | |
|
155 | <a class="thumb" | |
|
156 | href="{{ post.image.url }}"><img | |
|
157 | src=" {{ post.image.url_200x150 }}" | |
|
158 | alt="{{ post.id }}" | |
|
159 | width="{{ post.image_pre_width }}" | |
|
160 | height="{{ post.image_pre_height }}" | |
|
161 | data-width="{{ post.image_width }}" | |
|
162 | data-height="{{ post.image_height }}"/> | |
|
163 | </a> | |
|
164 | </div> | |
|
165 | {% endif %} | |
|
166 | <div class="message"> | |
|
167 | <div class="post-info"> | |
|
168 | <span class="title">{{ post.title }}</span> | |
|
169 | <a class="post_id" href=" | |
|
170 | {% url 'thread' thread.op.id %}#{{ post.id }}"> | |
|
171 | ({{ post.id }})</a> | |
|
172 | [{{ post.pub_time }}] | |
|
173 | </div> | |
|
174 | {% autoescape off %} | |
|
175 | {{ post.text.rendered|truncatewords_html:50 }} | |
|
176 | {% endautoescape %} | |
|
177 | </div> | |
|
178 | {% if post.is_referenced %} | |
|
179 | <div class="refmap"> | |
|
180 | {% trans "Replies" %}: | |
|
181 | {% for ref_post in post.get_sorted_referenced_posts %} | |
|
182 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a | |
|
183 | >{% if not forloop.last %},{% endif %} | |
|
184 | {% endfor %} | |
|
185 | </div> | |
|
186 | {% endif %} | |
|
187 | </div> | |
|
82 | {% post_view_truncated post %} | |
|
188 | 83 | {% endfor %} |
|
189 | 84 | </div> |
|
190 | 85 | {% endif %} |
|
191 | 86 | </div> |
|
192 | 87 | {% endcache %} |
|
193 | 88 | {% endfor %} |
|
194 | 89 | |
|
195 | 90 | {% if current_page.has_next %} |
|
196 | 91 | <div class="page_link"> |
|
197 | 92 | <a href=" |
|
198 | 93 | {% if tag %} |
|
199 | 94 | {% url "tag" tag_name=tag page=current_page.next_page_number %} |
|
200 | 95 | {% else %} |
|
201 | 96 | {% url "index" page=current_page.next_page_number %} |
|
202 | 97 | {% endif %} |
|
203 | 98 | ">{% trans "Next page" %}</a> |
|
204 | 99 | </div> |
|
205 | 100 | {% endif %} |
|
206 | 101 | {% else %} |
|
207 | 102 | <div class="post"> |
|
208 | 103 | {% trans 'No threads exist. Create the first one!' %}</div> |
|
209 | 104 | {% endif %} |
|
210 | 105 | |
|
211 | 106 | <div class="post-form-w"> |
|
212 | 107 | <script src="{% static 'js/panel.js' %}"></script> |
|
213 | 108 | <div class="post-form"> |
|
214 | 109 | <div class="form-title">{% trans "Create new thread" %}</div> |
|
215 | 110 | <form enctype="multipart/form-data" method="post">{% csrf_token %} |
|
216 | 111 | {{ form.as_div }} |
|
217 | 112 | <div class="form-submit"> |
|
218 | 113 | <input type="submit" value="{% trans "Post" %}"/> |
|
219 | 114 | </div> |
|
220 | 115 | </form> |
|
221 | 116 | <div> |
|
222 | 117 | {% trans 'Tags must be delimited by spaces. Text or image is required.' %} |
|
223 | 118 | </div> |
|
224 | 119 | <div><a href="{% url "staticpage" name="help" %}"> |
|
225 | 120 | {% trans 'Text syntax' %}</a></div> |
|
226 | 121 | </div> |
|
227 | 122 | </div> |
|
228 | 123 | |
|
229 | 124 | {% endblock %} |
|
230 | 125 | |
|
231 | 126 | {% block metapanel %} |
|
232 | 127 | |
|
233 | 128 | <span class="metapanel"> |
|
234 | 129 | <b><a href="{% url "authors" %}">Neboard</a> 1.6 Amon</b> |
|
235 | 130 | {% trans "Pages:" %}[ |
|
236 | 131 | {% for page in paginator.page_range %} |
|
237 | 132 | <a |
|
238 | 133 | {% ifequal page current_page.number %} |
|
239 | 134 | class="current_page" |
|
240 | 135 | {% endifequal %} |
|
241 | 136 | href=" |
|
242 | 137 | {% if tag %} |
|
243 | 138 | {% url "tag" tag_name=tag page=page %} |
|
244 | 139 | {% else %} |
|
245 | 140 | {% url "index" page=page %} |
|
246 | 141 | {% endif %} |
|
247 | 142 | ">{{ page }}</a> |
|
248 | 143 | {% if not forloop.last %},{% endif %} |
|
249 | 144 | {% endfor %} |
|
250 | 145 | ] |
|
251 | 146 | [<a href="rss/">RSS</a>] |
|
252 | 147 | </span> |
|
253 | 148 | |
|
254 | 149 | {% endblock %} |
@@ -1,145 +1,79 b'' | |||
|
1 | 1 | {% extends "boards/base.html" %} |
|
2 | 2 | |
|
3 | 3 | {% load i18n %} |
|
4 | 4 | {% load cache %} |
|
5 | 5 | {% load static from staticfiles %} |
|
6 | 6 | {% load board %} |
|
7 | 7 | |
|
8 | 8 | {% block head %} |
|
9 | 9 | <title>{{ thread.get_opening_post.get_title|striptags|truncatewords:10 }} - Neboard</title> |
|
10 | 10 | {% endblock %} |
|
11 | 11 | |
|
12 | 12 | {% block content %} |
|
13 | 13 | {% spaceless %} |
|
14 | 14 | {% get_current_language as LANGUAGE_CODE %} |
|
15 | 15 | |
|
16 | 16 | {% cache 600 thread_view thread.id thread.last_edit_time moderator LANGUAGE_CODE %} |
|
17 | 17 | |
|
18 | 18 | <div class="image-mode-tab"> |
|
19 | 19 | <a class="current_mode" href="{% url 'thread' thread.get_opening_post.id %}">{% trans 'Normal mode' %}</a>, |
|
20 | 20 | <a href="{% url 'thread_mode' thread.get_opening_post.id 'gallery' %}">{% trans 'Gallery mode' %}</a> |
|
21 | 21 | </div> |
|
22 | 22 | |
|
23 | 23 | {% if bumpable %} |
|
24 | 24 | <div class="bar-bg"> |
|
25 | 25 | <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress"> |
|
26 | 26 | </div> |
|
27 | 27 | <div class="bar-text"> |
|
28 | 28 | <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %} |
|
29 | 29 | </div> |
|
30 | 30 | </div> |
|
31 | 31 | {% endif %} |
|
32 | 32 | <div class="thread"> |
|
33 | 33 | {% for post in posts %} |
|
34 |
{% |
|
|
35 | <div class="post" id="{{ post.id }}"> | |
|
36 | {% elif thread.archived %} | |
|
37 | <div class="post archive_post" id="{{ post.id }}"> | |
|
38 | {% else %} | |
|
39 | <div class="post dead_post" id="{{ post.id }}"> | |
|
40 | {% endif %} | |
|
41 | {% if post.image %} | |
|
42 | <div class="image"> | |
|
43 | <a | |
|
44 | class="thumb" | |
|
45 | href="{{ post.image.url }}"><img | |
|
46 | src="{{ post.image.url_200x150 }}" | |
|
47 | alt="{{ post.id }}" | |
|
48 | width="{{ post.image_pre_width }}" | |
|
49 | height="{{ post.image_pre_height }}" | |
|
50 | data-width="{{ post.image_width }}" | |
|
51 | data-height="{{ post.image_height }}"/> | |
|
52 | </a> | |
|
53 | </div> | |
|
54 | {% endif %} | |
|
55 | <div class="message"> | |
|
56 | <div class="post-info"> | |
|
57 | <span class="title">{{ post.title }}</span> | |
|
58 | <a class="post_id" href="#{{ post.id }}"> | |
|
59 | ({{ post.id }}) </a> | |
|
60 | [<span class="pub_time">{{ post.pub_time }}</span>] | |
|
61 | {% if not thread.archived %} | |
|
62 | [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}') | |
|
63 | ; return false;">>></a>] | |
|
64 | {% endif %} | |
|
65 | ||
|
66 | {% if moderator %} | |
|
67 | <span class="moderator_info"> | |
|
68 | [<a href="{% url 'delete' post_id=post.id %}" | |
|
69 | >{% trans 'Delete' %}</a>] | |
|
70 | ({{ post.poster_ip }}) | |
|
71 | [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}" | |
|
72 | >{% trans 'Ban IP' %}</a>] | |
|
73 | </span> | |
|
74 | {% endif %} | |
|
75 | </div> | |
|
76 | {% autoescape off %} | |
|
77 | {{ post.text.rendered }} | |
|
78 | {% endautoescape %} | |
|
79 | {% if post.is_referenced %} | |
|
80 | <div class="refmap"> | |
|
81 | {% trans "Replies" %}: | |
|
82 | {% for ref_post in post.get_sorted_referenced_posts %} | |
|
83 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a | |
|
84 | >{% if not forloop.last %},{% endif %} | |
|
85 | {% endfor %} | |
|
86 | </div> | |
|
87 | {% endif %} | |
|
88 | </div> | |
|
89 | {% if forloop.first %} | |
|
90 | <div class="metadata"> | |
|
91 | <span class="tags"> | |
|
92 | {% for tag in thread.get_tags %} | |
|
93 | <a class="tag" href="{% url 'tag' tag.name %}"> | |
|
94 | #{{ tag.name }}</a | |
|
95 | >{% if not forloop.last %},{% endif %} | |
|
96 | {% endfor %} | |
|
97 | </span> | |
|
98 | </div> | |
|
99 | {% endif %} | |
|
100 | </div> | |
|
34 | {% post_view post %} | |
|
101 | 35 | {% endfor %} |
|
102 | 36 | </div> |
|
103 | 37 | {% endcache %} |
|
104 | 38 | |
|
105 | 39 | {% if not thread.archived %} |
|
106 | 40 | |
|
107 | 41 | <div class="post-form-w"> |
|
108 | 42 | <script src="{% static 'js/panel.js' %}"></script> |
|
109 | 43 | <div class="form-title">{% trans "Reply to thread" %} #{{ thread.get_opening_post.id }}</div> |
|
110 | 44 | <div class="post-form"> |
|
111 | 45 | <form id="form" enctype="multipart/form-data" method="post" |
|
112 | 46 | >{% csrf_token %} |
|
113 | 47 | {{ form.as_div }} |
|
114 | 48 | <div class="form-submit"> |
|
115 | 49 | <input type="submit" value="{% trans "Post" %}"/> |
|
116 | 50 | </div> |
|
117 | 51 | </form> |
|
118 | 52 | <div><a href="{% url "staticpage" name="help" %}"> |
|
119 | 53 | {% trans 'Text syntax' %}</a></div> |
|
120 | 54 | </div> |
|
121 | 55 | </div> |
|
122 | 56 | |
|
123 | 57 | <script src="{% static 'js/jquery.form.min.js' %}"></script> |
|
124 | 58 | <script src="{% static 'js/thread_update.js' %}"></script> |
|
125 | 59 | {% endif %} |
|
126 | 60 | |
|
127 | 61 | <script src="{% static 'js/thread.js' %}"></script> |
|
128 | 62 | |
|
129 | 63 | {% endspaceless %} |
|
130 | 64 | {% endblock %} |
|
131 | 65 | |
|
132 | 66 | {% block metapanel %} |
|
133 | 67 | |
|
134 | 68 | {% get_current_language as LANGUAGE_CODE %} |
|
135 | 69 | |
|
136 | 70 | <span class="metapanel" data-last-update="{{ last_update }}"> |
|
137 | 71 | {% cache 600 thread_meta thread.last_edit_time moderator LANGUAGE_CODE %} |
|
138 | 72 | <span id="reply-count">{{ thread.get_reply_count }}</span> {% trans 'replies' %}, |
|
139 | 73 | <span id="image-count">{{ thread.get_images_count }}</span> {% trans 'images' %}. |
|
140 | 74 | {% trans 'Last update: ' %}<span id="last-update">{{ thread.last_edit_time }}</span> |
|
141 | 75 | [<a href="rss/">RSS</a>] |
|
142 | 76 | {% endcache %} |
|
143 | 77 | </span> |
|
144 | 78 | |
|
145 | 79 | {% endblock %} |
@@ -1,49 +1,71 b'' | |||
|
1 | 1 | from django.core.urlresolvers import reverse |
|
2 | 2 | from django.shortcuts import get_object_or_404 |
|
3 | 3 | from boards.models import Post |
|
4 | from boards.views import thread | |
|
4 | from boards.views import thread, api | |
|
5 | 5 | from django import template |
|
6 | 6 | |
|
7 | 7 | register = template.Library() |
|
8 | 8 | |
|
9 | 9 | actions = [ |
|
10 | 10 | { |
|
11 | 11 | 'name': 'google', |
|
12 | 12 | 'link': 'http://google.com/searchbyimage?image_url=%s', |
|
13 | 13 | }, |
|
14 | 14 | { |
|
15 | 15 | 'name': 'iqdb', |
|
16 | 16 | 'link': 'http://iqdb.org/?url=%s', |
|
17 | 17 | }, |
|
18 | 18 | ] |
|
19 | 19 | |
|
20 | 20 | |
|
21 | 21 | @register.simple_tag(name='post_url') |
|
22 | 22 | def post_url(*args, **kwargs): |
|
23 | 23 | post_id = args[0] |
|
24 | 24 | |
|
25 | 25 | post = get_object_or_404(Post, id=post_id) |
|
26 | 26 | |
|
27 | 27 | if not post.is_opening(): |
|
28 | 28 | link = reverse(thread, kwargs={ |
|
29 | 29 | 'post_id': post.thread_new.get_opening_post().id}) + '#' + str( |
|
30 | 30 | post_id) |
|
31 | 31 | else: |
|
32 | 32 | link = reverse(thread, kwargs={'post_id': post_id}) |
|
33 | 33 | |
|
34 | 34 | return link |
|
35 | 35 | |
|
36 | 36 | |
|
37 | 37 | @register.simple_tag(name='image_actions') |
|
38 | 38 | def image_actions(*args, **kwargs): |
|
39 | 39 | image_link = args[0] |
|
40 | 40 | if len(args) > 1: |
|
41 | 41 | image_link = 'http://' + args[1] + image_link # TODO https? |
|
42 | 42 | |
|
43 | 43 | result = '' |
|
44 | 44 | |
|
45 | 45 | for action in actions: |
|
46 | 46 | result += '[<a href="' + action['link'] % image_link + '">' + \ |
|
47 | 47 | action['name'] + '</a>]' |
|
48 | 48 | |
|
49 | 49 | return result |
|
50 | ||
|
51 | ||
|
52 | @register.inclusion_tag('boards/post.html', name='post_view') | |
|
53 | def post_view(*args, **kwargs): | |
|
54 | post = args[0] | |
|
55 | ||
|
56 | return { 'post': post } | |
|
57 | ||
|
58 | ||
|
59 | @register.inclusion_tag('boards/post.html', name='post_view_truncated') | |
|
60 | def post_view_truncated(*args, **kwargs): | |
|
61 | post = args[0] | |
|
62 | if len(args) > 1: | |
|
63 | need_open_link = args[1] | |
|
64 | else: | |
|
65 | need_open_link = False | |
|
66 | ||
|
67 | return { | |
|
68 | 'post': post, | |
|
69 | 'truncated': True, | |
|
70 | 'need_open_link': need_open_link | |
|
71 | } No newline at end of file |
@@ -1,206 +1,205 b'' | |||
|
1 | 1 | from datetime import datetime |
|
2 | 2 | import json |
|
3 | 3 | from django.db import transaction |
|
4 | 4 | from django.http import HttpResponse |
|
5 | 5 | from django.shortcuts import get_object_or_404, render |
|
6 | 6 | from django.template import RequestContext |
|
7 | 7 | from django.utils import timezone |
|
8 | 8 | from boards.forms import PostForm, PlainErrorList |
|
9 | 9 | from boards.models import Post, Thread, Tag |
|
10 | 10 | from boards.views import _datetime_to_epoch, _new_post, \ |
|
11 | 11 | _ban_current_user |
|
12 | 12 | |
|
13 | 13 | __author__ = 'neko259' |
|
14 | 14 | |
|
15 | 15 | PARAMETER_TRUNCATED = 'truncated' |
|
16 | 16 | PARAMETER_TAG = 'tag' |
|
17 | 17 | PARAMETER_OFFSET = 'offset' |
|
18 | 18 | PARAMETER_DIFF_TYPE = 'type' |
|
19 | 19 | |
|
20 | 20 | DIFF_TYPE_HTML = 'html' |
|
21 | 21 | DIFF_TYPE_JSON = 'json' |
|
22 | 22 | |
|
23 | 23 | STATUS_OK = 'ok' |
|
24 | 24 | STATUS_ERROR = 'error' |
|
25 | 25 | |
|
26 | 26 | |
|
27 | 27 | @transaction.atomic |
|
28 | 28 | def api_get_threaddiff(request, thread_id, last_update_time): |
|
29 | 29 | """Get posts that were changed or added since time""" |
|
30 | 30 | |
|
31 | 31 | thread = get_object_or_404(Post, id=thread_id).thread_new |
|
32 | 32 | |
|
33 | 33 | filter_time = datetime.fromtimestamp(float(last_update_time) / 1000000, |
|
34 | 34 | timezone.get_current_timezone()) |
|
35 | 35 | |
|
36 | 36 | json_data = { |
|
37 | 37 | 'added': [], |
|
38 | 38 | 'updated': [], |
|
39 | 39 | 'last_update': None, |
|
40 | 40 | } |
|
41 | 41 | added_posts = Post.objects.filter(thread_new=thread, |
|
42 | 42 | pub_time__gt=filter_time) \ |
|
43 | 43 | .order_by('pub_time') |
|
44 | 44 | updated_posts = Post.objects.filter(thread_new=thread, |
|
45 | 45 | pub_time__lte=filter_time, |
|
46 | 46 | last_edit_time__gt=filter_time) |
|
47 | 47 | |
|
48 | 48 | diff_type = DIFF_TYPE_HTML |
|
49 | 49 | if PARAMETER_DIFF_TYPE in request.GET: |
|
50 | 50 | diff_type = request.GET[PARAMETER_DIFF_TYPE] |
|
51 | 51 | |
|
52 | 52 | for post in added_posts: |
|
53 | 53 | json_data['added'].append(_get_post_data(post.id, diff_type, request)) |
|
54 | 54 | for post in updated_posts: |
|
55 | 55 | json_data['updated'].append(_get_post_data(post.id, diff_type, request)) |
|
56 | 56 | json_data['last_update'] = _datetime_to_epoch(thread.last_edit_time) |
|
57 | 57 | |
|
58 | 58 | return HttpResponse(content=json.dumps(json_data)) |
|
59 | 59 | |
|
60 | 60 | |
|
61 | 61 | def api_add_post(request, opening_post_id): |
|
62 | 62 | """ |
|
63 | 63 | Add a post and return the JSON response for it |
|
64 | 64 | """ |
|
65 | 65 | |
|
66 | 66 | opening_post = get_object_or_404(Post, id=opening_post_id) |
|
67 | 67 | |
|
68 | 68 | status = STATUS_OK |
|
69 | 69 | errors = [] |
|
70 | 70 | |
|
71 | 71 | if request.method == 'POST': |
|
72 | 72 | form = PostForm(request.POST, request.FILES, |
|
73 | 73 | error_class=PlainErrorList) |
|
74 | 74 | form.session = request.session |
|
75 | 75 | |
|
76 | 76 | #if form.need_to_ban: |
|
77 | 77 | # # Ban user because he is suspected to be a bot |
|
78 | 78 | # _ban_current_user(request) |
|
79 | 79 | # status = STATUS_ERROR |
|
80 | 80 | if form.is_valid(): |
|
81 | 81 | _new_post(request, form, opening_post, html_response=False) |
|
82 | 82 | else: |
|
83 | 83 | status = STATUS_ERROR |
|
84 | 84 | errors = form.as_json_errors() |
|
85 | 85 | |
|
86 | 86 | response = { |
|
87 | 87 | 'status': status, |
|
88 | 88 | 'errors': errors, |
|
89 | 89 | } |
|
90 | 90 | |
|
91 | 91 | return HttpResponse(content=json.dumps(response)) |
|
92 | 92 | |
|
93 | 93 | |
|
94 | 94 | def get_post(request, post_id): |
|
95 | 95 | """ |
|
96 | 96 | Get the html of a post. Used for popups. Post can be truncated if used |
|
97 | 97 | in threads list with 'truncated' get parameter. |
|
98 | 98 | """ |
|
99 | 99 | |
|
100 | 100 | post = get_object_or_404(Post, id=post_id) |
|
101 | thread = post.thread_new | |
|
102 | 101 | |
|
103 | 102 | context = RequestContext(request) |
|
104 | 103 | context['post'] = post |
|
105 | 104 | if PARAMETER_TRUNCATED in request.GET: |
|
106 | 105 | context[PARAMETER_TRUNCATED] = True |
|
107 | 106 | |
|
108 | 107 | return render(request, 'boards/post.html', context) |
|
109 | 108 | |
|
110 | 109 | |
|
111 | 110 | # TODO Test this |
|
112 | 111 | def api_get_threads(request, count): |
|
113 | 112 | """ |
|
114 | 113 | Get the JSON thread opening posts list. |
|
115 | 114 | Parameters that can be used for filtering: |
|
116 | 115 | tag, offset (from which thread to get results) |
|
117 | 116 | """ |
|
118 | 117 | |
|
119 | 118 | if PARAMETER_TAG in request.GET: |
|
120 | 119 | tag_name = request.GET[PARAMETER_TAG] |
|
121 | 120 | if tag_name is not None: |
|
122 | 121 | tag = get_object_or_404(Tag, name=tag_name) |
|
123 | 122 | threads = tag.threads.filter(archived=False) |
|
124 | 123 | else: |
|
125 | 124 | threads = Thread.objects.filter(archived=False) |
|
126 | 125 | |
|
127 | 126 | if PARAMETER_OFFSET in request.GET: |
|
128 | 127 | offset = request.GET[PARAMETER_OFFSET] |
|
129 | 128 | offset = int(offset) if offset is not None else 0 |
|
130 | 129 | else: |
|
131 | 130 | offset = 0 |
|
132 | 131 | |
|
133 | 132 | threads = threads.order_by('-bump_time') |
|
134 | 133 | threads = threads[offset:offset + int(count)] |
|
135 | 134 | |
|
136 | 135 | opening_posts = [] |
|
137 | 136 | for thread in threads: |
|
138 | 137 | opening_post = thread.get_opening_post() |
|
139 | 138 | |
|
140 | 139 | # TODO Add tags, replies and images count |
|
141 | 140 | opening_posts.append(_get_post_data(opening_post.id, |
|
142 | 141 | include_last_update=True)) |
|
143 | 142 | |
|
144 | 143 | return HttpResponse(content=json.dumps(opening_posts)) |
|
145 | 144 | |
|
146 | 145 | |
|
147 | 146 | # TODO Test this |
|
148 | 147 | def api_get_tags(request): |
|
149 | 148 | """ |
|
150 | 149 | Get all tags or user tags. |
|
151 | 150 | """ |
|
152 | 151 | |
|
153 | 152 | # TODO Get favorite tags for the given user ID |
|
154 | 153 | |
|
155 | 154 | tags = Tag.objects.get_not_empty_tags() |
|
156 | 155 | tag_names = [] |
|
157 | 156 | for tag in tags: |
|
158 | 157 | tag_names.append(tag.name) |
|
159 | 158 | |
|
160 | 159 | return HttpResponse(content=json.dumps(tag_names)) |
|
161 | 160 | |
|
162 | 161 | |
|
163 | 162 | # TODO The result can be cached by the thread last update time |
|
164 | 163 | # TODO Test this |
|
165 | 164 | def api_get_thread_posts(request, opening_post_id): |
|
166 | 165 | """ |
|
167 | 166 | Get the JSON array of thread posts |
|
168 | 167 | """ |
|
169 | 168 | |
|
170 | 169 | opening_post = get_object_or_404(Post, id=opening_post_id) |
|
171 | 170 | thread = opening_post.thread_new |
|
172 | 171 | posts = thread.get_replies() |
|
173 | 172 | |
|
174 | 173 | json_data = { |
|
175 | 174 | 'posts': [], |
|
176 | 175 | 'last_update': None, |
|
177 | 176 | } |
|
178 | 177 | json_post_list = [] |
|
179 | 178 | |
|
180 | 179 | for post in posts: |
|
181 | 180 | json_post_list.append(_get_post_data(post.id)) |
|
182 | 181 | json_data['last_update'] = _datetime_to_epoch(thread.last_edit_time) |
|
183 | 182 | json_data['posts'] = json_post_list |
|
184 | 183 | |
|
185 | 184 | return HttpResponse(content=json.dumps(json_data)) |
|
186 | 185 | |
|
187 | 186 | |
|
188 | 187 | # TODO Add pub time and replies |
|
189 | 188 | def _get_post_data(post_id, format_type=DIFF_TYPE_JSON, request=None, |
|
190 | 189 | include_last_update=False): |
|
191 | 190 | if format_type == DIFF_TYPE_HTML: |
|
192 | 191 | return get_post(request, post_id).content.strip() |
|
193 | 192 | elif format_type == DIFF_TYPE_JSON: |
|
194 | 193 | post = get_object_or_404(Post, id=post_id) |
|
195 | 194 | post_json = { |
|
196 | 195 | 'id': post.id, |
|
197 | 196 | 'title': post.title, |
|
198 | 197 | 'text': post.text.rendered, |
|
199 | 198 | } |
|
200 | 199 | if post.image: |
|
201 | 200 | post_json['image'] = post.image.url |
|
202 | 201 | post_json['image_preview'] = post.image.url_200x150 |
|
203 | 202 | if include_last_update: |
|
204 | 203 | post_json['bump_time'] = _datetime_to_epoch( |
|
205 | 204 | post.thread_new.bump_time) |
|
206 | 205 | return post_json |
General Comments 0
You need to be logged in to leave comments.
Login now