##// END OF EJS Templates
Added ability to rollover thread
neko259 -
r2108:ed3f943b default
parent child Browse files
Show More
1 NO CONTENT: modified file, binary diff hidden
@@ -1,93 +1,97 b''
1 1 # SOME DESCRIPTIVE TITLE.
2 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 3 # This file is distributed under the same license as the PACKAGE package.
4 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 5 #
6 6 #, fuzzy
7 7 msgid ""
8 8 msgstr ""
9 9 "Project-Id-Version: PACKAGE VERSION\n"
10 10 "Report-Msgid-Bugs-To: \n"
11 11 "POT-Creation-Date: 2015-09-04 18:47+0300\n"
12 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 14 "Language-Team: LANGUAGE <LL@li.org>\n"
15 15 "Language: \n"
16 16 "MIME-Version: 1.0\n"
17 17 "Content-Type: text/plain; charset=UTF-8\n"
18 18 "Content-Transfer-Encoding: 8bit\n"
19 19 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
20 20 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
21 21
22 22 #: static/js/3party/jquery-ui.min.js:8
23 23 msgid "'"
24 24 msgstr ""
25 25
26 26 #: static/js/refpopup.js:72
27 27 msgid "Loading..."
28 28 msgstr "Загрузка..."
29 29
30 30 #: static/js/refpopup.js:91
31 31 msgid "Post not found"
32 32 msgstr "Сообщение не найдено"
33 33
34 34 #: static/js/thread_update.js:261
35 35 msgid "message"
36 36 msgid_plural "messages"
37 37 msgstr[0] "сообщение"
38 38 msgstr[1] "сообщения"
39 39 msgstr[2] "сообщений"
40 40
41 41 #: static/js/thread_update.js:262
42 42 msgid "image"
43 43 msgid_plural "images"
44 44 msgstr[0] "изображение"
45 45 msgstr[1] "изображения"
46 46 msgstr[2] "изображений"
47 47
48 48 #: static/js/thread_update.js:445
49 49 msgid "Sending message..."
50 50 msgstr "Отправка сообщения..."
51 51
52 52 #: static/js/thread_update.js:449
53 53 msgid "Server error!"
54 54 msgstr "Ошибка сервера!"
55 55
56 56 msgid "Computing PoW..."
57 57 msgstr "Расчёт PoW..."
58 58
59 59 msgid "Duplicates search"
60 60 msgstr "Поиск дубликатов"
61 61
62 62 msgid "Add local sticker"
63 63 msgstr "Добавить локальный стикер"
64 64
65 65 msgid "Input sticker name"
66 66 msgstr "Введите название стикера"
67 67
68 68 msgid "Images posted: "
69 69 msgstr "Вставленных изображений: "
70 70
71 71 msgid "Ban and delete"
72 72 msgstr "Забанить и удалить"
73 73
74 74 msgid "Are you sure?"
75 75 msgstr "Вы уверены?"
76 76
77 77 msgid "Ban"
78 78 msgstr "Забанить"
79 79
80 80 msgid "Delete post"
81 81 msgstr "Удалить пост"
82 82
83 83 msgid "Delete thread"
84 84 msgstr "Удалить тему"
85 85
86 86 msgid "Edit"
87 87 msgstr "Изменить"
88 88
89 89 msgid "Edit thread"
90 90 msgstr "Изменить тему"
91 91
92 92 msgid "Hide/show"
93 93 msgstr "Скрыть/показать"
94
95 msgid "Rollover thread"
96 msgstr "Перекатить тред"
97
1 NO CONTENT: modified file, binary diff hidden
@@ -1,93 +1,97 b''
1 1 # SOME DESCRIPTIVE TITLE.
2 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 3 # This file is distributed under the same license as the PACKAGE package.
4 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 5 #
6 6 #, fuzzy
7 7 msgid ""
8 8 msgstr ""
9 9 "Project-Id-Version: PACKAGE VERSION\n"
10 10 "Report-Msgid-Bugs-To: \n"
11 11 "POT-Creation-Date: 2015-09-04 18:47+0300\n"
12 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 14 "Language-Team: LANGUAGE <LL@li.org>\n"
15 15 "Language: \n"
16 16 "MIME-Version: 1.0\n"
17 17 "Content-Type: text/plain; charset=UTF-8\n"
18 18 "Content-Transfer-Encoding: 8bit\n"
19 19 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
20 20 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
21 21
22 22 #: static/js/3party/jquery-ui.min.js:8
23 23 msgid "'"
24 24 msgstr ""
25 25
26 26 #: static/js/refpopup.js:72
27 27 msgid "Loading..."
28 28 msgstr "Завантаження..."
29 29
30 30 #: static/js/refpopup.js:91
31 31 msgid "Post not found"
32 32 msgstr "Повідомлення не знайдене"
33 33
34 34 #: static/js/thread_update.js:261
35 35 msgid "message"
36 36 msgid_plural "messages"
37 37 msgstr[0] "повідомлення"
38 38 msgstr[1] "повідомлення"
39 39 msgstr[2] "повідомлень"
40 40
41 41 #: static/js/thread_update.js:262
42 42 msgid "image"
43 43 msgid_plural "images"
44 44 msgstr[0] "зображення"
45 45 msgstr[1] "зображення"
46 46 msgstr[2] "зображень"
47 47
48 48 #: static/js/thread_update.js:445
49 49 msgid "Sending message..."
50 50 msgstr "Повідомлення надсилається..."
51 51
52 52 #: static/js/thread_update.js:449
53 53 msgid "Server error!"
54 54 msgstr "Сервер нездужає! Заходьте пізніше!"
55 55
56 56 msgid "Computing PoW..."
57 57 msgstr "Розраховується PoW..."
58 58
59 59 msgid "Duplicates search"
60 60 msgstr "Пошук дублікатів"
61 61
62 62 msgid "Add local sticker"
63 63 msgstr "Додати локальний стікер"
64 64
65 65 msgid "Input sticker name"
66 66 msgstr "Введіть назву стікера"
67 67
68 68 msgid "Images posted: "
69 69 msgstr "Вставлених зображень: "
70 70
71 71 msgid "Ban and delete"
72 72 msgstr "Заблокувати й видалити"
73 73
74 74 msgid "Are you sure?"
75 75 msgstr "Чи ви певні?"
76 76
77 77 msgid "Ban"
78 78 msgstr "Заблокувати"
79 79
80 80 msgid "Delete post"
81 81 msgstr "Видалити повідомлення"
82 82
83 83 msgid "Delete thread"
84 84 msgstr "Вирвати нитку"
85 85
86 86 msgid "Edit"
87 87 msgstr "Змінити"
88 88
89 89 msgid "Edit thread"
90 90 msgstr "Змінити нитку"
91 91
92 92 msgid "Hide/show"
93 93 msgstr "Приховати/відобразити"
94
95 msgid "Rollover thread"
96 msgstr "Перекотити нитку"
97
@@ -1,362 +1,371 b''
1 1 /*
2 2 @licstart The following is the entire license notice for the
3 3 JavaScript code in this page.
4 4
5 5
6 6 Copyright (C) 2013 neko259
7 7
8 8 The JavaScript code in this page is free software: you can
9 9 redistribute it and/or modify it under the terms of the GNU
10 10 General Public License (GNU GPL) as published by the Free Software
11 11 Foundation, either version 3 of the License, or (at your option)
12 12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15 15
16 16 As additional permission under GNU GPL version 3 section 7, you
17 17 may distribute non-source (e.g., minimized or compacted) forms of
18 18 that code without the copy of the GNU GPL normally required by
19 19 section 4, provided you include this license notice and a URL
20 20 through which recipients can access the Corresponding Source.
21 21
22 22 @licend The above is the entire license notice
23 23 for the JavaScript code in this page.
24 24 */
25 25
26 26 var ITEM_VOLUME_LEVEL = 'volumeLevel';
27 27 var ITEM_HIDDEN_POSTS = 'hiddenPosts';
28 28
29 29 var IMAGE_TYPES = ['image/png', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/gif'];
30 30
31 31 /**
32 32 * An email is a hidden file to prevent spam bots from posting. It has to be
33 33 * hidden.
34 34 */
35 35 function hideEmailFromForm() {
36 36 $('.form-email').parent().parent().hide();
37 37 }
38 38
39 39 /**
40 40 * Highlight code blocks with code highlighter
41 41 */
42 42 function highlightCode(node) {
43 43 node.find('pre code').each(function(i, e) {
44 44 hljs.highlightBlock(e);
45 45 });
46 46 }
47 47
48 48 function updateFavPosts(data) {
49 49 var includePostBody = $('#fav-panel').is(":visible");
50 50
51 51 var allNewPostCount = 0;
52 52
53 53 if (includePostBody) {
54 54 var favoriteThreadPanel = $('#fav-panel');
55 55 favoriteThreadPanel.empty();
56 56 }
57 57
58 58 $.each($.parseJSON(data), function (_, dict) {
59 59 var newPostCount = dict.new_post_count;
60 60 allNewPostCount += newPostCount;
61 61
62 62 if (includePostBody) {
63 63 var favThreadNode = $('<div class="post"></div>');
64 64 favThreadNode.append($(dict.post_url));
65 65 favThreadNode.append(' ');
66 66 favThreadNode.append($('<span class="title">' + dict.title + '</span>'));
67 67
68 68 if (newPostCount > 0) {
69 69 favThreadNode.append(' (<a href="' + dict.newest_post_link + '">+' + newPostCount + "</a>)");
70 70 }
71 71
72 72 favoriteThreadPanel.append(favThreadNode);
73 73
74 74 addRefLinkPreview(favThreadNode[0]);
75 75 }
76 76 });
77 77
78 78 var newPostCountNode = $('#new-fav-post-count');
79 79 if (allNewPostCount > 0) {
80 80 newPostCountNode.text('(+' + allNewPostCount + ')');
81 81 newPostCountNode.show();
82 82 } else {
83 83 newPostCountNode.hide();
84 84 }
85 85 }
86 86
87 87 function initFavPanel() {
88 88 var favPanelButton = $('#fav-panel-btn');
89 89 if (favPanelButton.length > 0 && typeof SharedWorker != 'undefined') {
90 90 var worker = new SharedWorker($('body').attr('data-update-script'));
91 91 worker.port.onmessage = function(e) {
92 92 updateFavPosts(e.data);
93 93 };
94 94 worker.onerror = function(event){
95 95 throw new Error(event.message + " (" + event.filename + ":" + event.lineno + ")");
96 96 };
97 97 worker.port.start();
98 98
99 99 $(favPanelButton).click(function() {
100 100 var favPanel = $('#fav-panel');
101 101 favPanel.toggle();
102 102
103 103 worker.port.postMessage({ includePostBody: favPanel.is(':visible')});
104 104
105 105 return false;
106 106 });
107 107
108 108 $(document).on('keyup.removepic', function(e) {
109 109 if(e.which === 27) {
110 110 $('#fav-panel').hide();
111 111 }
112 112 });
113 113 }
114 114 }
115 115
116 116 function setVolumeLevel(level) {
117 117 localStorage.setItem(ITEM_VOLUME_LEVEL, level);
118 118 }
119 119
120 120 function getVolumeLevel() {
121 121 var level = localStorage.getItem(ITEM_VOLUME_LEVEL);
122 122 if (level == null) {
123 123 level = 1.0;
124 124 }
125 125 return level
126 126 }
127 127
128 128 function processVolumeUser(node) {
129 129 if (!window.localStorage) return;
130 130 node.prop("volume", getVolumeLevel());
131 131 node.on('volumechange', function(event) {
132 132 setVolumeLevel(event.target.volume);
133 133 $("video,audio").prop("volume", getVolumeLevel());
134 134 });
135 135 }
136 136
137 137 function getHiddenPosts() {
138 138 var arr = Array();
139 139 var hiddenPosts = localStorage.getItem(ITEM_HIDDEN_POSTS);
140 140 if (hiddenPosts) {
141 141 arr = JSON.parse(hiddenPosts);
142 142 }
143 143 return arr;
144 144 }
145 145
146 146 function processPostHiding(posts) {
147 147 var hiddenPosts = getHiddenPosts();
148 148
149 149 $.each(posts, function(index) {
150 150 var post = $(this);
151 151 if (hiddenPosts.indexOf(post.attr("id")) > -1) {
152 152 post.toggleClass("hidden_post");
153 153 }
154 154 });
155 155 }
156 156
157 157 /**
158 158 * Add all scripts than need to work on post, when the post is added to the
159 159 * document.
160 160 */
161 161 function addScriptsToPost(post) {
162 162 addRefLinkPreview(post[0]);
163 163 highlightCode(post);
164 164 processVolumeUser(post.find("video,audio"));
165 165 processPostHiding([post]);
166 166 }
167 167
168 168 /**
169 169 * Fix compatibility issues with some rare browsers
170 170 */
171 171 function compatibilityCrutches() {
172 172 if (window.operamini) {
173 173 $('#form textarea').each(function() { this.placeholder = ''; });
174 174 }
175 175 }
176 176
177 177 function togglePostHidden(postId) {
178 178 var hiddenPosts = getHiddenPosts();
179 179
180 180 var elIndex = hiddenPosts.indexOf(postId);
181 181 if (elIndex > -1) {
182 182 hiddenPosts.splice(elIndex, 1);
183 183 } else {
184 184 hiddenPosts.push(postId);
185 185 }
186 186 localStorage.setItem(ITEM_HIDDEN_POSTS, JSON.stringify(hiddenPosts));
187 187
188 188 $('#' + postId).toggleClass("hidden_post");
189 189 }
190 190
191 191 function addContextMenu() {
192 192 $.contextMenu({
193 193 selector: '.file-menu',
194 194 trigger: 'left',
195 195
196 196 build: function($trigger, e) {
197 197 var fileSearchUrl = $trigger.data('search-url');
198 198 var isImage = IMAGE_TYPES.indexOf($trigger.data('type')) > -1;
199 199 var hasUrl = fileSearchUrl.length > 0;
200 200 var id = $trigger.data('id');
201 201 return {
202 202 items: {
203 203 duplicates: {
204 204 name: gettext('Duplicates search'),
205 205 callback: function(key, opts) {
206 206 window.location = '/feed/?image=' + $trigger.data('filename');
207 207 }
208 208 },
209 209 google: {
210 210 name: 'Google',
211 211 visible: isImage && hasUrl,
212 212 callback: function(key, opts) {
213 213 window.location = 'https://www.google.com/searchbyimage?image_url=' + fileSearchUrl;
214 214 }
215 215 },
216 216 iqdb: {
217 217 name: 'IQDB',
218 218 visible: isImage && hasUrl,
219 219 callback: function(key, opts) {
220 220 window.location = 'http://iqdb.org/?url=' + fileSearchUrl;
221 221 }
222 222 },
223 223 tineye: {
224 224 name: 'TinEye',
225 225 visible: isImage && hasUrl,
226 226 callback: function(key, opts) {
227 227 window.location = 'http://tineye.com/search?url=' + fileSearchUrl;
228 228 }
229 229 },
230 230 addAlias: {
231 231 name: gettext('Add local sticker'),
232 232 callback: function(key, opts) {
233 233 var alias = prompt(gettext('Input sticker name'));
234 234 if (alias) {
235 235 window.location = '/stickers/?action=add&name=' + alias + '&id=' + id;
236 236 }
237 237 }
238 238 }
239 239 }
240 240 };
241 241 }
242 242 });
243 243
244 244 $.contextMenu({
245 245 selector: '.post .post-menu',
246 246 trigger: 'left',
247 247 build: function($trigger, e) {
248 248 var canEditPost = PERMS['change_post'];
249 249 var canDeletePost = PERMS['delete_post'];
250 250 var canEditThread = PERMS['change_thread'];
251 251 var canDeleteThread = PERMS['delete_thread'];
252 252
253 253 var post = $trigger.parents('.post');
254 254
255 255 var isOpening = post.data('opening') === 'True';
256 256 var threadId = post.data('thread-id');
257 257 var hasGlobalId = post.data('has-global-id') === 'True';
258 258
259 259 var posterIp = $trigger.siblings('.pub_time').attr('title');
260 260 var hasIp = posterIp != null;
261 261
262 262 var postId = post.attr('id');
263 263
264 264 return {
265 265 items: {
266 266 hide: {
267 267 name: gettext('Hide/show'),
268 268 callback: function(key, opt) {
269 269 togglePostHidden(postId);
270 270 }
271 271 },
272 272 edit: {
273 273 name: gettext('Edit'),
274 274 callback: function(key, opt) {
275 275 window.location = '/admin/boards/post/' + postId + '/change/';
276 276 },
277 277 visible: canEditPost
278 278 },
279 279 deletePost: {
280 280 name: gettext('Delete post'),
281 281 callback: function(key, opt) {
282 282 window.location = '/admin/boards/post/' + postId + '/delete/';
283 283 },
284 284 visible: !isOpening && canDeletePost
285 285 },
286 286 editThread: {
287 287 name: gettext('Edit thread'),
288 288 callback: function(key, opt) {
289 289 window.location = '/admin/boards/thread/' + threadId + '/change/';
290 290 },
291 291 visible: isOpening && canEditThread
292 292 },
293 293 deleteThread: {
294 294 name: gettext('Delete thread'),
295 295 callback: function(key, opt) {
296 296 window.location = '/admin/boards/thread/' + threadId + '/delete/';
297 297 },
298 298 visible: isOpening && canDeleteThread
299 299 },
300 300 findByIp: {
301 301 name: 'IP = ' + posterIp,
302 302 callback: function(key, opt) {
303 303 window.location = '/feed/?ip=' + posterIp;
304 304 },
305 305 visible: canEditPost && hasIp
306 306 },
307 307 raw: {
308 308 name: 'RAW',
309 309 callback: function(key, opt) {
310 310 window.location = '/post_xml/' + postId;
311 311 },
312 312 visible: canEditPost && hasGlobalId
313 313 },
314 314 ban: {
315 315 name: gettext('Ban'),
316 316 callback: function(key, opt) {
317 317 if (confirm(gettext('Are you sure?'))) {
318 318 window.location = '/utils?method=ban&post_id=' + postId;
319 319 }
320 320 },
321 321 visible: canEditPost && hasIp
322 322 },
323 323 banAndDelete: {
324 324 name: gettext('Ban and delete'),
325 325 callback: function(key, opt) {
326 326 if (confirm(gettext('Are you sure?'))) {
327 327 window.location = '/utils?method=ban_and_delete&post_id=' + postId;
328 328 }
329 329 },
330 330 visible: hasIp && canDeletePost
331 },
332 rollover: {
333 name: gettext('Rollover thread'),
334 callback: function(key, opt) {
335 if (confirm(gettext('Are you sure?'))) {
336 window.location = '/all/?t_from_id=' + postId + '#form';
337 }
338 },
339 visible: isOpening
331 340 }
332 341 }
333 342 };
334 343 }
335 344 });
336 345 }
337 346
338 347 $( document ).ready(function() {
339 348 hideEmailFromForm();
340 349
341 350 $("a[href='#top']").click(function() {
342 351 $("html, body").animate({ scrollTop: 0 }, "slow");
343 352 return false;
344 353 });
345 354
346 355 addImgPreview();
347 356
348 357 addRefLinkPreview();
349 358
350 359 highlightCode($(document));
351 360
352 361 initFavPanel();
353 362
354 363 var volumeUsers = $("video,audio");
355 364 processVolumeUser(volumeUsers);
356 365
357 366 addContextMenu();
358 367
359 368 compatibilityCrutches();
360 369
361 370 processPostHiding($('.post'));
362 371 });
@@ -1,136 +1,151 b''
1 1 from django.core.paginator import EmptyPage
2 2 from django.http import Http404
3 3 from django.shortcuts import render, redirect
4 4 from django.urls import reverse
5 5 from django.utils.decorators import method_decorator
6 6 from django.views.decorators.csrf import csrf_protect
7 7
8 8 from boards import settings
9 9 from boards.abstracts.constants import PARAM_PAGE
10 10 from boards.abstracts.paginator import get_paginator
11 11 from boards.abstracts.settingsmanager import get_settings_manager, \
12 12 SETTING_ONLY_FAVORITES, SETTING_SUBSCRIBE_BY_DEFAULT
13 13 from boards.forms import ThreadForm, PlainErrorList
14 14 from boards.models import Post, Thread
15 15 from boards.settings import SECTION_VIEW
16 16 from boards.views.base import BaseBoardView, CONTEXT_FORM
17 17 from boards.views.mixins import PaginatedMixin, \
18 18 DispatcherMixin, PARAMETER_METHOD
19 19
20 20 ORDER_BUMP = 'bump'
21 21
22 22 PARAM_ORDER = 'order'
23 23
24 24 FORM_TAGS = 'tags'
25 25 FORM_TEXT = 'text'
26 26 FORM_TITLE = 'title'
27 27 FORM_IMAGE = 'image'
28 28 FORM_THREADS = 'threads'
29 29
30 30 TAG_DELIMITER = ' '
31 31
32 32 PARAMETER_CURRENT_PAGE = 'current_page'
33 33 PARAMETER_PAGINATOR = 'paginator'
34 34 PARAMETER_THREADS = 'threads'
35 35 PARAMETER_ADDITIONAL = 'additional_params'
36 36 PARAMETER_RSS_URL = 'rss_url'
37 37
38 38 TEMPLATE = 'boards/all_threads.html'
39 39 DEFAULT_PAGE = 1
40 40
41 41
42 42 class AllThreadsView(BaseBoardView, PaginatedMixin, DispatcherMixin):
43 43
44 44 tag_name = ''
45 45
46 46 def __init__(self):
47 47 self.settings_manager = None
48 48 super(AllThreadsView, self).__init__()
49 49
50 50 @method_decorator(csrf_protect)
51 51 def get(self, request, form: ThreadForm=None):
52 52 page = request.GET.get(PARAM_PAGE, DEFAULT_PAGE)
53 53
54 54 params = self.get_context_data(request=request)
55 55
56 56 subscribe_by_default = get_settings_manager(request).get_setting(
57 57 SETTING_SUBSCRIBE_BY_DEFAULT, False)
58 58
59 59 if not form:
60 t_from_id = request.GET.get('t_from_id')
61 if t_from_id:
62 source_op = Post.objects.get(id=int(t_from_id))
63 tags_str = ' '.join([tag.get_name() for tag in source_op.get_thread().get_tags()])
64 post_link = '[post]{}[/post]'.format(source_op.id) #FIXME To constants
65 new_title = source_op.get_title() + ' NEW' # TODO More intelligent name change
66
67 form = ThreadForm(error_class=PlainErrorList,
68 initial={
69 FORM_TAGS: tags_str,
70 'subscribe': subscribe_by_default,
71 FORM_TEXT: post_link,
72 FORM_TITLE: new_title,
73 })
74 else:
60 75 form = ThreadForm(error_class=PlainErrorList,
61 76 initial={FORM_TAGS: self.tag_name,
62 77 'subscribe': subscribe_by_default})
63 78
64 79 self.settings_manager = get_settings_manager(request)
65 80
66 81 threads = self.get_threads()
67 82
68 83 order = request.GET.get(PARAM_ORDER, ORDER_BUMP)
69 84 if order == ORDER_BUMP:
70 85 threads = threads.order_by('-bump_time')
71 86 else:
72 87 threads = threads.filter(replies__opening=True)\
73 88 .order_by('-replies__pub_time')
74 89 threads = threads.distinct()
75 90
76 91 paginator = get_paginator(threads, settings.get_int(
77 92 SECTION_VIEW, 'ThreadsPerPage'),
78 93 link=self.get_reverse_url(),
79 94 params=request.GET.dict())
80 95 paginator.current_page = int(page)
81 96
82 97 try:
83 98 threads = paginator.page(page).object_list
84 99 except EmptyPage:
85 100 raise Http404()
86 101
87 102 params[PARAMETER_THREADS] = threads
88 103 params[CONTEXT_FORM] = form
89 104 params[PARAMETER_RSS_URL] = self.get_rss_url()
90 105
91 106 params.update(self.get_page_context(paginator, page))
92 107
93 108 return render(request, TEMPLATE, params)
94 109
95 110 @method_decorator(csrf_protect)
96 111 def post(self, request):
97 112 if PARAMETER_METHOD in request.POST:
98 113 self.dispatch_method(request)
99 114
100 115 return redirect(self.get_reverse_url())
101 116
102 117 form = ThreadForm(request.POST, request.FILES,
103 118 error_class=PlainErrorList, session=request.session)
104 119
105 120 if form.is_valid():
106 121 return Post.objects.create_from_form(request, form, None)
107 122 if form.need_to_ban:
108 123 # Ban user because he is suspected to be a bot
109 124 self._ban_current_user(request)
110 125
111 126 return self.get(request, form)
112 127
113 128 def get_reverse_url(self):
114 129 return reverse('index')
115 130
116 131 def get_threads(self):
117 132 """
118 133 Gets list of threads that will be shown on a page.
119 134 """
120 135
121 136 threads = Thread.objects\
122 137 .exclude(tags__in=self.settings_manager.get_hidden_tags())
123 138 if self.settings_manager.get_setting(SETTING_ONLY_FAVORITES):
124 139 fav_tags = self.settings_manager.get_fav_tags()
125 140 if len(fav_tags) > 0:
126 141 threads = threads.filter(tags__in=fav_tags)
127 142
128 143 return threads
129 144
130 145 def get_rss_url(self):
131 146 return self.get_reverse_url() + 'rss/'
132 147
133 148 def toggle_fav(self, request):
134 149 settings_manager = get_settings_manager(request)
135 150 settings_manager.set_setting(SETTING_ONLY_FAVORITES,
136 151 not settings_manager.get_setting(SETTING_ONLY_FAVORITES, False))
General Comments 0
You need to be logged in to leave comments. Login now