##// END OF EJS Templates
Merged with 1.5 dev branch
neko259 -
r463:8531d7b0 merge 1.5 default
parent child Browse files
Show More
@@ -0,0 +1,92 b''
1 # -*- coding: utf-8 -*-
2 from south.utils import datetime_utils as datetime
3 from south.db import db
4 from south.v2 import SchemaMigration
5 from django.db import models
6
7
8 class Migration(SchemaMigration):
9
10 def forwards(self, orm):
11 # Adding field 'Post.image_pre_width'
12 db.add_column(u'boards_post', 'image_pre_width',
13 self.gf('django.db.models.fields.IntegerField')(default=0),
14 keep_default=False)
15
16 # Adding field 'Post.image_pre_height'
17 db.add_column(u'boards_post', 'image_pre_height',
18 self.gf('django.db.models.fields.IntegerField')(default=0),
19 keep_default=False)
20
21
22 def backwards(self, orm):
23 # Deleting field 'Post.image_pre_width'
24 db.delete_column(u'boards_post', 'image_pre_width')
25
26 # Deleting field 'Post.image_pre_height'
27 db.delete_column(u'boards_post', 'image_pre_height')
28
29
30 models = {
31 'boards.ban': {
32 'Meta': {'object_name': 'Ban'},
33 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
34 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
35 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
36 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'})
37 },
38 'boards.post': {
39 'Meta': {'object_name': 'Post'},
40 '_text_rendered': ('django.db.models.fields.TextField', [], {}),
41 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
42 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}),
43 'image_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
44 'image_pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
45 'image_pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
46 'image_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
47 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
48 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
49 'poster_user_agent': ('django.db.models.fields.TextField', [], {}),
50 'pub_time': ('django.db.models.fields.DateTimeField', [], {}),
51 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'rfp+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}),
52 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}),
53 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'markdown'", 'max_length': '30'}),
54 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Post']", 'null': 'True'}),
55 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Thread']", 'null': 'True'}),
56 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
57 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.User']", 'null': 'True'})
58 },
59 'boards.setting': {
60 'Meta': {'object_name': 'Setting'},
61 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
62 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
63 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.User']"}),
64 'value': ('django.db.models.fields.CharField', [], {'max_length': '50'})
65 },
66 'boards.tag': {
67 'Meta': {'object_name': 'Tag'},
68 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
69 'linked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}),
70 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
71 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tag+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Thread']"})
72 },
73 'boards.thread': {
74 'Meta': {'object_name': 'Thread'},
75 'bump_time': ('django.db.models.fields.DateTimeField', [], {}),
76 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
77 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
78 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tre+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}),
79 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'})
80 },
81 'boards.user': {
82 'Meta': {'object_name': 'User'},
83 'fav_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}),
84 'fav_threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}),
85 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
86 'rank': ('django.db.models.fields.IntegerField', [], {}),
87 'registration_time': ('django.db.models.fields.DateTimeField', [], {}),
88 'user_id': ('django.db.models.fields.CharField', [], {'max_length': '50'})
89 }
90 }
91
92 complete_apps = ['boards'] No newline at end of file
@@ -0,0 +1,66 b''
1 {% extends "boards/base.html" %}
2
3 {% load i18n %}
4 {% load cache %}
5 {% load static from staticfiles %}
6 {% load board %}
7
8 {% block head %}
9 <title>Neboard - {{ thread.get_opening_post.get_title }}</title>
10 {% endblock %}
11
12 {% block content %}
13 {% spaceless %}
14 {% get_current_language as LANGUAGE_CODE %}
15
16 <script src="{% static 'js/thread.js' %}"></script>
17
18 {% cache 600 thread_gallery_view thread.id thread.last_edit_time LANGUAGE_CODE %}
19 <div class="image-mode-tab">
20 <a href="{% url 'thread' thread.get_opening_post.id %}">{% trans 'Normal mode' %}</a>,
21 <a class="current_mode" href="{% url 'thread_mode' thread.get_opening_post.id 'gallery' %}">{% trans 'Gallery mode' %}</a>
22 </div>
23
24 <div id="posts-table">
25 {% for post in thread.get_replies %}
26 {% if post.image %}
27 <div class="gallery_image">
28 <div>
29 <a
30 class="thumb"
31 href="{{ post.image.url }}"><img
32 src="{{ post.image.url_200x150 }}"
33 alt="{{ post.id }}"
34 width="{{ post.image_pre_width }}"
35 height="{{ post.image_pre_height }}"
36 data-width="{{ post.image_width }}"
37 data-height="{{ post.image_height }}"/>
38 </a>
39 </div>
40 <div class="gallery_image_metadata">
41 {{ post.image_width }}x{{ post.image_height }}
42 {% image_actions post.image.url request.get_host %}
43 </div>
44 </div>
45 {% endif %}
46 {% endfor %}
47 </div>
48 {% endcache %}
49
50 {% endspaceless %}
51 {% endblock %}
52
53 {% block metapanel %}
54
55 {% get_current_language as LANGUAGE_CODE %}
56
57 <span class="metapanel" data-last-update="{{ last_update }}">
58 {% cache 600 thread_meta thread.last_edit_time moderator LANGUAGE_CODE %}
59 <span id="reply-count">{{ thread.get_reply_count }}</span> {% trans 'replies' %},
60 <span id="image-count">{{ thread.get_images_count }}</span> {% trans 'images' %}.
61 {% trans 'Last update: ' %}{{ thread.last_edit_time }}
62 [<a href="rss/">RSS</a>]
63 {% endcache %}
64 </span>
65
66 {% endblock %}
@@ -0,0 +1,7 b''
1 # 1.5 Aker #
2 * Saving image previews size. No space will be shown below images in some
3 styles.
4 * Showing notification in page title when new posts are loaded into the open
5 thread.
6 * Thread moderation fixes
7 * Added new gallery with search links and image metadata No newline at end of file
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: 2013-11-27 12:34+0200\n"
10 "POT-Creation-Date: 2013-12-24 20:39+0200\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"
@@ -34,77 +34,72 b' msgstr "\xd1\x80\xd0\xb0\xd0\xb7\xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd1\x87\xd0\xb8\xd0\xba javascript"'
34 msgid "designer"
34 msgid "designer"
35 msgstr "дизайнер"
35 msgstr "дизайнер"
36
36
37 #: forms.py:48 templates/boards/posting_general.html:209
37 #: forms.py:72
38 #: templates/boards/thread.html:101
39 msgid "Title"
38 msgid "Title"
40 msgstr "Заголовок"
39 msgstr "Заголовок"
41
40
42 #: forms.py:50 templates/boards/posting_general.html:224
41 #: forms.py:74
43 #: templates/boards/thread.html:116
44 msgid "Text"
42 msgid "Text"
45 msgstr "Текст"
43 msgstr "Текст"
46
44
47 #: forms.py:51 templates/boards/posting_general.html:229
45 #: forms.py:75
48 #: templates/boards/thread.html:121
49 msgid "Image"
46 msgid "Image"
50 msgstr "Изображение"
47 msgstr "Изображение"
51
48
52 #: forms.py:54 templates/boards/posting_general.html:239
49 #: forms.py:78
53 #: templates/boards/thread.html:126
54 msgid "e-mail"
50 msgid "e-mail"
55 msgstr ""
51 msgstr ""
56
52
57 #: forms.py:65
53 #: forms.py:89
58 #, python-format
54 #, python-format
59 msgid "Title must have less than %s characters"
55 msgid "Title must have less than %s characters"
60 msgstr "Заголовок должен иметь меньше %s символов"
56 msgstr "Заголовок должен иметь меньше %s символов"
61
57
62 #: forms.py:74
58 #: forms.py:98
63 #, python-format
59 #, python-format
64 msgid "Text must have less than %s characters"
60 msgid "Text must have less than %s characters"
65 msgstr "Текст должен быть короче %s символов"
61 msgstr "Текст должен быть короче %s символов"
66
62
67 #: forms.py:85
63 #: forms.py:109
68 #, python-format
64 #, python-format
69 msgid "Image must be less than %s bytes"
65 msgid "Image must be less than %s bytes"
70 msgstr "Изображение должно быть менее %s байт"
66 msgstr "Изображение должно быть менее %s байт"
71
67
72 #: forms.py:112
68 #: forms.py:136
73 msgid "Either text or image must be entered."
69 msgid "Either text or image must be entered."
74 msgstr "Текст или картинка должны быть введены."
70 msgstr "Текст или картинка должны быть введены."
75
71
76 #: forms.py:125
72 #: forms.py:149
77 #, python-format
73 #, python-format
78 msgid "Wait %s seconds after last posting"
74 msgid "Wait %s seconds after last posting"
79 msgstr "Подождите %s секунд после последнего постинга"
75 msgstr "Подождите %s секунд после последнего постинга"
80
76
81 #: forms.py:139 templates/boards/post.html:60
77 #: forms.py:163 templates/boards/post.html:61 templates/boards/tags.html:6
82 #: templates/boards/posting_general.html:234 templates/boards/tags.html:6
83 #: templates/boards/rss/post.html:10
78 #: templates/boards/rss/post.html:10
84 msgid "Tags"
79 msgid "Tags"
85 msgstr "Теги"
80 msgstr "Теги"
86
81
87 #: forms.py:147
82 #: forms.py:171
88 msgid "Inappropriate characters in tags."
83 msgid "Inappropriate characters in tags."
89 msgstr "Недопустимые символы в тегах."
84 msgstr "Недопустимые символы в тегах."
90
85
91 #: forms.py:175 forms.py:196
86 #: forms.py:199 forms.py:220
92 msgid "Captcha validation failed"
87 msgid "Captcha validation failed"
93 msgstr "Проверка капчи провалена"
88 msgstr "Проверка капчи провалена"
94
89
95 #: forms.py:202
90 #: forms.py:226
96 msgid "Theme"
91 msgid "Theme"
97 msgstr "Тема"
92 msgstr "Тема"
98
93
99 #: forms.py:207
94 #: forms.py:231
100 msgid "Enable moderation panel"
95 msgid "Enable moderation panel"
101 msgstr "Включить панель модерации"
96 msgstr "Включить панель модерации"
102
97
103 #: forms.py:222
98 #: forms.py:246
104 msgid "No such user found"
99 msgid "No such user found"
105 msgstr "Данный пользователь не найден"
100 msgstr "Данный пользователь не найден"
106
101
107 #: forms.py:236
102 #: forms.py:260
108 #, python-format
103 #, python-format
109 msgid "Wait %s minutes after last login"
104 msgid "Wait %s minutes after last login"
110 msgstr "Подождите %s минут после последнего входа"
105 msgstr "Подождите %s минут после последнего входа"
@@ -137,15 +132,15 b' msgstr "\xd0\xa0\xd0\xb5\xd0\xbf\xd0\xbe\xd0\xb7\xd0\xb8\xd1\x82\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb9"'
137 msgid "Feed"
132 msgid "Feed"
138 msgstr "Лента"
133 msgstr "Лента"
139
134
140 #: templates/boards/base.html:36
135 #: templates/boards/base.html:31
141 msgid "All threads"
136 msgid "All threads"
142 msgstr "Все темы"
137 msgstr "Все темы"
143
138
144 #: templates/boards/base.html:41
139 #: templates/boards/base.html:36
145 msgid "Tag management"
140 msgid "Tag management"
146 msgstr "Управление тегами"
141 msgstr "Управление тегами"
147
142
148 #: templates/boards/base.html:43
143 #: templates/boards/base.html:38
149 msgid "Settings"
144 msgid "Settings"
150 msgstr "Настройки"
145 msgstr "Настройки"
151
146
@@ -171,92 +166,65 b' msgstr "ID \xd0\xbf\xd0\xbe\xd0\xbb\xd1\x8c\xd0\xb7\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd0\xb5\xd0\xbb\xd1\x8f"'
171 msgid "Insert your user id above"
166 msgid "Insert your user id above"
172 msgstr "Вставьте свой ID пользователя выше"
167 msgstr "Вставьте свой ID пользователя выше"
173
168
174 #: templates/boards/post.html:34 templates/boards/posting_general.html:100
169 #: templates/boards/post.html:35 templates/boards/posting_general.html:103
175 #: templates/boards/thread.html:59
170 #: templates/boards/thread.html:68
176 msgid "Delete"
171 msgid "Delete"
177 msgstr "Удалить"
172 msgstr "Удалить"
178
173
179 #: templates/boards/post.html:37 templates/boards/posting_general.html:104
174 #: templates/boards/post.html:38 templates/boards/posting_general.html:107
180 #: templates/boards/thread.html:62
175 #: templates/boards/thread.html:71
181 msgid "Ban IP"
176 msgid "Ban IP"
182 msgstr "Заблокировать IP"
177 msgstr "Заблокировать IP"
183
178
184 #: templates/boards/post.html:50 templates/boards/posting_general.html:113
179 #: templates/boards/post.html:51 templates/boards/posting_general.html:116
185 #: templates/boards/posting_general.html:172 templates/boards/thread.html:71
180 #: templates/boards/posting_general.html:180 templates/boards/thread.html:80
186 msgid "Replies"
181 msgid "Replies"
187 msgstr "Ответы"
182 msgstr "Ответы"
188
183
189 #: templates/boards/posting_general.html:63
184 #: templates/boards/posting_general.html:64
190 msgid "Previous page"
185 msgid "Previous page"
191 msgstr "Предыдущая страница"
186 msgstr "Предыдущая страница"
192
187
193 #: templates/boards/posting_general.html:94
188 #: templates/boards/posting_general.html:97
194 msgid "Reply"
189 msgid "Reply"
195 msgstr "Ответ"
190 msgstr "Ответ"
196
191
197 #: templates/boards/posting_general.html:122 templates/boards/thread.html:154
192 #: templates/boards/posting_general.html:125 templates/boards/thread.html:130
198 msgid "replies"
193 #: templates/boards/thread_gallery.html:52
199 msgstr "ответов"
200
201 #: templates/boards/posting_general.html:123 templates/boards/thread.html:155
202 msgid "images"
194 msgid "images"
203 msgstr "изображений"
195 msgstr "изображений"
204
196
205 #: templates/boards/posting_general.html:138
197 #: templates/boards/posting_general.html:142
206 #, python-format
198 #, python-format
207 msgid "Skipped %(count)s replies. Open thread to see all replies."
199 msgid "Skipped %(count)s replies. Open thread to see all replies."
208 msgstr "Пропущено %(count)s ответов. Откройте тред, чтобы увидеть все ответы."
200 msgstr "Пропущено %(count)s ответов. Откройте тред, чтобы увидеть все ответы."
209
201
210 #: templates/boards/posting_general.html:195
202 #: templates/boards/posting_general.html:203
211 msgid "Next page"
203 msgid "Next page"
212 msgstr "Следующая страница"
204 msgstr "Следующая страница"
213
205
214 #: templates/boards/posting_general.html:200
206 #: templates/boards/posting_general.html:208
215 msgid "No threads exist. Create the first one!"
207 msgid "No threads exist. Create the first one!"
216 msgstr "Нет тем. Создайте первую!"
208 msgstr "Нет тем. Создайте первую!"
217
209
218 #: templates/boards/posting_general.html:206
210 #: templates/boards/posting_general.html:214
219 msgid "Create new thread"
211 msgid "Create new thread"
220 msgstr "Создать новую тему"
212 msgstr "Создать новую тему"
221
213
222 #: templates/boards/posting_general.html:214 templates/boards/thread.html:106
214 #: templates/boards/posting_general.html:218 templates/boards/thread.html:112
223 msgid "Formatting"
224 msgstr "Форматирование"
225
226 #: templates/boards/posting_general.html:216 templates/boards/thread.html:108
227 msgid "quote"
228 msgstr "цитата"
229
230 #: templates/boards/posting_general.html:217 templates/boards/thread.html:109
231 msgid "italic"
232 msgstr "курсив"
233
234 #: templates/boards/posting_general.html:218 templates/boards/thread.html:110
235 msgid "bold"
236 msgstr "полужирный"
237
238 #: templates/boards/posting_general.html:219 templates/boards/thread.html:111
239 msgid "spoiler"
240 msgstr "спойлер"
241
242 #: templates/boards/posting_general.html:220 templates/boards/thread.html:112
243 msgid "comment"
244 msgstr "комментарий"
245
246 #: templates/boards/posting_general.html:252 templates/boards/thread.html:140
247 msgid "Post"
215 msgid "Post"
248 msgstr "Отправить"
216 msgstr "Отправить"
249
217
250 #: templates/boards/posting_general.html:254
218 #: templates/boards/posting_general.html:222
251 msgid "Tags must be delimited by spaces. Text or image is required."
219 msgid "Tags must be delimited by spaces. Text or image is required."
252 msgstr ""
220 msgstr ""
253 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
221 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
254
222
255 #: templates/boards/posting_general.html:257 templates/boards/thread.html:142
223 #: templates/boards/posting_general.html:225 templates/boards/thread.html:116
256 msgid "Text syntax"
224 msgid "Text syntax"
257 msgstr "Синтаксис текста"
225 msgstr "Синтаксис текста"
258
226
259 #: templates/boards/posting_general.html:267
227 #: templates/boards/posting_general.html:235
260 msgid "Pages:"
228 msgid "Pages:"
261 msgstr "Страницы: "
229 msgstr "Страницы: "
262
230
@@ -292,15 +260,27 b' msgstr "\xd1\x82\xd0\xb5\xd0\xbc"'
292 msgid "No tags found."
260 msgid "No tags found."
293 msgstr "Теги не найдены."
261 msgstr "Теги не найдены."
294
262
295 #: templates/boards/thread.html:24
263 #: templates/boards/thread.html:22 templates/boards/thread_gallery.html:20
264 msgid "Normal mode"
265 msgstr "Нормальный режим"
266
267 #: templates/boards/thread.html:23 templates/boards/thread_gallery.html:21
268 msgid "Gallery mode"
269 msgstr "Режим галереи"
270
271 #: templates/boards/thread.html:31
296 msgid "posts to bumplimit"
272 msgid "posts to bumplimit"
297 msgstr "сообщений до бамплимита"
273 msgstr "сообщений до бамплимита"
298
274
299 #: templates/boards/thread.html:98
275 #: templates/boards/thread.html:106
300 msgid "Reply to thread"
276 msgid "Reply to thread"
301 msgstr "Ответить в тему"
277 msgstr "Ответить в тему"
302
278
303 #: templates/boards/thread.html:156
279 #: templates/boards/thread.html:129 templates/boards/thread_gallery.html:51
280 msgid "replies"
281 msgstr "ответов"
282
283 #: templates/boards/thread.html:131 templates/boards/thread_gallery.html:53
304 msgid "Last update: "
284 msgid "Last update: "
305 msgstr "Последнее обновление: "
285 msgstr "Последнее обновление: "
306
286
@@ -353,6 +333,24 b' msgstr "\xd0\xa1\xd1\x81\xd1\x8b\xd0\xbb\xd0\xba\xd0\xb0 \xd0\xbd\xd0\xb0 \xd1\x81\xd0\xbe\xd0\xbe\xd0\xb1\xd1\x89\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5"'
353 msgid "Strikethrough text"
333 msgid "Strikethrough text"
354 msgstr "Зачеркнутый текст"
334 msgstr "Зачеркнутый текст"
355
335
336 #~ msgid "Formatting"
337 #~ msgstr "Форматирование"
338
339 #~ msgid "quote"
340 #~ msgstr "цитата"
341
342 #~ msgid "italic"
343 #~ msgstr "курсив"
344
345 #~ msgid "bold"
346 #~ msgstr "полужирный"
347
348 #~ msgid "spoiler"
349 #~ msgstr "спойлер"
350
351 #~ msgid "comment"
352 #~ msgstr "комментарий"
353
356 #~ msgid "Tag: "
354 #~ msgid "Tag: "
357 #~ msgstr "Тег: "
355 #~ msgstr "Тег: "
358
356
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -8,7 +8,7 b' msgid ""'
8 msgstr ""
8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n"
9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n"
10 "Report-Msgid-Bugs-To: \n"
11 "POT-Creation-Date: 2013-11-13 17:25+0200\n"
11 "POT-Creation-Date: 2013-12-21 21:45+0200\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,11 +19,11 b' msgstr ""'
19 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
20 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
21
21
22 #: static/js/refpopup.js:60
22 #: static/js/refpopup.js:57
23 msgid "Loading..."
23 msgid "Loading..."
24 msgstr "Загрузка..."
24 msgstr "Загрузка..."
25
25
26 #: static/js/refpopup.js:86
26 #: static/js/refpopup.js:76
27 msgid "Post not found"
27 msgid "Post not found"
28 msgstr "Сообщение не найдено"
28 msgstr "Сообщение не найдено"
29
29
@@ -35,5 +35,9 b' msgstr "\xd0\x9d\xd0\xbe\xd1\x80\xd0\xbc\xd0\xb0\xd0\xbb\xd1\x8c\xd0\xbd\xd1\x8b\xd0\xb9"'
35 msgid "Gallery"
35 msgid "Gallery"
36 msgstr "Галерея"
36 msgstr "Галерея"
37
37
38 #: static/js/thread_update.js:177
39 msgid "[new posts]"
40 msgstr "[новые посты]"
41
38 #~ msgid "Replies"
42 #~ msgid "Replies"
39 #~ msgstr "Ответы"
43 #~ msgstr "Ответы"
@@ -34,7 +34,8 b' class MinifyHTMLMiddleware(object):'
34 except AttributeError:
34 except AttributeError:
35 compress_html = False
35 compress_html = False
36
36
37 if TYPE_HTML in response[RESPONSE_CONTENT_TYPE] and compress_html:
37 if RESPONSE_CONTENT_TYPE in response\
38 and TYPE_HTML in response[RESPONSE_CONTENT_TYPE] and compress_html:
38 response.content = strip_spaces_between_tags(
39 response.content = strip_spaces_between_tags(
39 response.content.strip())
40 response.content.strip())
40 return response No newline at end of file
41 return response
@@ -86,12 +86,18 b' class PostManager(models.Manager):'
86
86
87 def delete_post(self, post):
87 def delete_post(self, post):
88 """
88 """
89 Delete post and update its thread
89 Delete post and update or delete its thread
90 """
90 """
91
92 thread = post.thread_new
91
93
92 thread = post.thread_new
94 if thread.get_opening_post() == self:
93 thread.last_edit_time = timezone.now()
95 thread.replies.delete()
94 thread.save()
96
97 thread.delete()
98 else:
99 thread.last_edit_time = timezone.now()
100 thread.save()
95
101
96 post.delete()
102 post.delete()
97
103
@@ -235,10 +241,15 b' class Post(models.Model):'
235 image_width = models.IntegerField(default=0)
241 image_width = models.IntegerField(default=0)
236 image_height = models.IntegerField(default=0)
242 image_height = models.IntegerField(default=0)
237
243
244 image_pre_width = models.IntegerField(default=0)
245 image_pre_height = models.IntegerField(default=0)
246
238 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
247 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
239 blank=True, sizes=(IMAGE_THUMB_SIZE,),
248 blank=True, sizes=(IMAGE_THUMB_SIZE,),
240 width_field='image_width',
249 width_field='image_width',
241 height_field='image_height')
250 height_field='image_height',
251 preview_width_field='image_pre_width',
252 preview_height_field='image_pre_height')
242
253
243 poster_ip = models.GenericIPAddressField()
254 poster_ip = models.GenericIPAddressField()
244 poster_user_agent = models.TextField()
255 poster_user_agent = models.TextField()
@@ -27,3 +27,7 b''
27 z-index: 300;
27 z-index: 300;
28 position:absolute;
28 position:absolute;
29 }
29 }
30
31 .gallery_image {
32 display: inline-block;
33 } No newline at end of file
@@ -173,8 +173,6 b' blockquote {'
173 min-width: 1px;
173 min-width: 1px;
174 text-align: center;
174 text-align: center;
175 display: table-row;
175 display: table-row;
176
177 height: 150px;
178 }
176 }
179
177
180 .post > .metadata {
178 .post > .metadata {
@@ -356,3 +354,15 b' li {'
356 .skipped_replies {
354 .skipped_replies {
357 margin: 5px;
355 margin: 5px;
358 }
356 }
357
358 .current_page, .current_mode {
359 border: solid 1px #afdcec;
360 padding: 2px;
361 }
362
363 .gallery_image {
364 border: solid 1px;
365 padding: 0.5ex;
366 margin: 0.5ex;
367 text-align: center;
368 } No newline at end of file
@@ -171,8 +171,6 b' blockquote {'
171 min-width: 1px;
171 min-width: 1px;
172 text-align: center;
172 text-align: center;
173 display: table-row;
173 display: table-row;
174
175 height: 150px;
176 }
174 }
177
175
178 .post > .metadata {
176 .post > .metadata {
@@ -342,3 +340,8 b' input[type="submit"]:hover {'
342 .skipped_replies {
340 .skipped_replies {
343 margin: 5px;
341 margin: 5px;
344 }
342 }
343
344 .current_page, .current_mode {
345 border: solid 1px #000;
346 padding: 2px;
347 } No newline at end of file
@@ -330,4 +330,28 b' li {'
330
330
331 .mark_btn:last-child {
331 .mark_btn:last-child {
332 border-right: 1px solid #182F6F;
332 border-right: 1px solid #182F6F;
333 }
334
335 .current_page {
336 border-bottom: 1px solid #FFF;
337 padding: 0px 0.5ex;
338 }
339
340 .image-mode-tab a {
341 text-decoration: none;
342 }
343 .image-mode-tab .current_mode::before {
344 content: "✓ ";
345 padding: 0 0 0 .5ex;
346 color: #182F6F;
347 background: #FFF;
348 }
349 .image-mode-tab .current_mode {
350 padding: 0 .5ex 0 0;
351 color: #182F6F;
352 background: #FFF;
353 }
354
355 .gallery_image_metadata {
356 margin-bottom: 1em;
333 } No newline at end of file
357 }
@@ -23,33 +23,6 b''
23 for the JavaScript code in this page.
23 for the JavaScript code in this page.
24 */
24 */
25
25
26 function addGalleryPanel() {
27 var gallery = $('a[class="thumb"]').clone(true),
28 normal = $('.post').clone(true);
29
30 $('.navigation_panel').filter(':first').after(
31 '<div class="image-mode-tab" role="radiogroup" aria-label="Image mode2">' +
32 '<label><input type="radio" class="image-mode-normal" name="image-mode" value="0" checked="checked"/>'+ gettext('Normal') +'</label>' +
33 '<label><input type="radio" class="image-mode-table" name="image-mode" value="1"/>'+ gettext('Gallery') +'</label>' +
34 '</div>'
35 );
36
37 $('input[name="image-mode"]').change(function() {
38 //gallery mode
39 if($(this).val() === '1') {
40 $('.thread').replaceWith(
41 $('<div id="posts-table"></div>').append(gallery)
42 );
43 }
44 //normal mode
45 else {
46 $('#posts-table').replaceWith(
47 $('<div class="thread"></div>').append(normal)
48 );
49 }
50 });
51 }
52
53 function moveCaretToEnd(el) {
26 function moveCaretToEnd(el) {
54 if (typeof el.selectionStart == "number") {
27 if (typeof el.selectionStart == "number") {
55 el.selectionStart = el.selectionEnd = el.value.length;
28 el.selectionStart = el.selectionEnd = el.value.length;
@@ -72,10 +45,3 b' function addQuickReply(postId) {'
72
45
73 $("html, body").animate({ scrollTop: $(textAreaId).offset().top }, "slow");
46 $("html, body").animate({ scrollTop: $(textAreaId).offset().top }, "slow");
74 }
47 }
75
76
77
78 $(document).ready(function(){
79 addGalleryPanel();
80 initAutoupdate();
81 });
@@ -97,6 +97,10 b' function updateThread() {'
97
97
98 updateBumplimitProgress(data.added.length);
98 updateBumplimitProgress(data.added.length);
99 updatePostBumpableStatus();
99 updatePostBumpableStatus();
100
101 if (data.added.length + data.updated.length > 0) {
102 showNewPostsTitle();
103 }
100 })
104 })
101 .error(function(data) {
105 .error(function(data) {
102 // TODO Show error message that server is unavailable?
106 // TODO Show error message that server is unavailable?
@@ -162,3 +166,27 b' function updatePostBumpableStatus() {'
162 $('.thread').find('.post').addClass('dead_post');
166 $('.thread').find('.post').addClass('dead_post');
163 }
167 }
164 }
168 }
169
170 var documentOriginalTitle = '';
171 /**
172 * Show 'new posts' text in the title if the document is not visible to a user
173 */
174 function showNewPostsTitle() {
175 if (document.hidden) {
176 documentOriginalTitle = document.title;
177 document.title = gettext('[new posts]') + ' ' + document.title;
178
179 document.addEventListener('visibilitychange', function() {
180 if (documentOriginalTitle !== '') {
181 document.title = documentOriginalTitle;
182 documentOriginalTitle = '';
183 }
184
185 document.removeEventListener('visibilitychange', null);
186 });
187 }
188 }
189
190 $(document).ready(function(){
191 initAutoupdate();
192 });
@@ -79,6 +79,8 b''
79 href="{{ thread.op.image.url }}"><img
79 href="{{ thread.op.image.url }}"><img
80 src="{{ thread.op.image.url_200x150 }}"
80 src="{{ thread.op.image.url_200x150 }}"
81 alt="{{ thread.op.id }}"
81 alt="{{ thread.op.id }}"
82 width="{{ thread.op.image_pre_width }}"
83 height="{{ thread.op.image_pre_height }}"
82 data-width="{{ thread.op.image_width }}"
84 data-width="{{ thread.op.image_width }}"
83 data-height="{{ thread.op.image_height }}"/>
85 data-height="{{ thread.op.image_height }}"/>
84 </a>
86 </a>
@@ -99,7 +101,7 b''
99 [<a href="
101 [<a href="
100 {% url 'delete' post_id=thread.op.id %}?next={{ request.path }}"
102 {% url 'delete' post_id=thread.op.id %}?next={{ request.path }}"
101 >{% trans 'Delete' %}</a>]
103 >{% trans 'Delete' %}</a>]
102 ({{ thread.thread.poster_ip }})
104 ({{ thread.op.poster_ip }})
103 [<a href="
105 [<a href="
104 {% url 'ban' post_id=thread.op.id %}?next={{ request.path }}"
106 {% url 'ban' post_id=thread.op.id %}?next={{ request.path }}"
105 >{% trans 'Ban IP' %}</a>]
107 >{% trans 'Ban IP' %}</a>]
@@ -154,6 +156,8 b''
154 href="{{ post.image.url }}"><img
156 href="{{ post.image.url }}"><img
155 src=" {{ post.image.url_200x150 }}"
157 src=" {{ post.image.url_200x150 }}"
156 alt="{{ post.id }}"
158 alt="{{ post.id }}"
159 width="{{ post.image_pre_width }}"
160 height="{{ post.image_pre_height }}"
157 data-width="{{ post.image_width }}"
161 data-width="{{ post.image_width }}"
158 data-height="{{ post.image_height }}"/>
162 data-height="{{ post.image_height }}"/>
159 </a>
163 </a>
@@ -227,17 +231,23 b''
227 {% block metapanel %}
231 {% block metapanel %}
228
232
229 <span class="metapanel">
233 <span class="metapanel">
230 <b><a href="{% url "authors" %}">Neboard</a> 1.4.1</b>
234 <b><a href="{% url "authors" %}">Neboard</a> 1.5 Aker</b>
231 {% trans "Pages:" %}
235 {% trans "Pages:" %}[
232 {% for page in pages %}
236 {% for page in pages %}
233 [<a href="
237 <a
238 {% ifequal page current_page %}
239 class="current_page"
240 {% endifequal %}
241 href="
234 {% if tag %}
242 {% if tag %}
235 {% url "tag" tag_name=tag page=page %}
243 {% url "tag" tag_name=tag page=page %}
236 {% else %}
244 {% else %}
237 {% url "index" page=page %}
245 {% url "index" page=page %}
238 {% endif %}
246 {% endif %}
239 ">{{ page }}</a>]
247 ">{{ page }}</a>
248 {% if not forloop.last %},{% endif %}
240 {% endfor %}
249 {% endfor %}
250 ]
241 [<a href="rss/">RSS</a>]
251 [<a href="rss/">RSS</a>]
242 </span>
252 </span>
243
253
@@ -6,7 +6,7 b''
6 {% load board %}
6 {% load board %}
7
7
8 {% block head %}
8 {% block head %}
9 <title>Neboard - {{ thread.get_replies.0.get_title }}</title>
9 <title>Neboard - {{ thread.get_opening_post.get_title }}</title>
10 {% endblock %}
10 {% endblock %}
11
11
12 {% block content %}
12 {% block content %}
@@ -17,6 +17,12 b''
17 <script src="{% static 'js/thread.js' %}"></script>
17 <script src="{% static 'js/thread.js' %}"></script>
18
18
19 {% cache 600 thread_view thread.id thread.last_edit_time moderator LANGUAGE_CODE %}
19 {% cache 600 thread_view thread.id thread.last_edit_time moderator LANGUAGE_CODE %}
20
21 <div class="image-mode-tab">
22 <a class="current_mode" href="{% url 'thread' thread.get_opening_post.id %}">{% trans 'Normal mode' %}</a>,
23 <a href="{% url 'thread_mode' thread.get_opening_post.id 'gallery' %}">{% trans 'Gallery mode' %}</a>
24 </div>
25
20 {% if bumpable %}
26 {% if bumpable %}
21 <div class="bar-bg">
27 <div class="bar-bg">
22 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
28 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
@@ -40,6 +46,8 b''
40 href="{{ post.image.url }}"><img
46 href="{{ post.image.url }}"><img
41 src="{{ post.image.url_200x150 }}"
47 src="{{ post.image.url_200x150 }}"
42 alt="{{ post.id }}"
48 alt="{{ post.id }}"
49 width="{{ post.image_pre_width }}"
50 height="{{ post.image_pre_height }}"
43 data-width="{{ post.image_width }}"
51 data-width="{{ post.image_width }}"
44 data-height="{{ post.image_height }}"/>
52 data-height="{{ post.image_height }}"/>
45 </a>
53 </a>
@@ -6,6 +6,17 b' from django import template'
6
6
7 register = template.Library()
7 register = template.Library()
8
8
9 actions = [
10 {
11 'name': 'google',
12 'link': 'http://google.com/searchbyimage?image_url=%s',
13 },
14 {
15 'name': 'iqdb',
16 'link': 'http://iqdb.org/?url=%s',
17 },
18 ]
19
9
20
10 @register.simple_tag(name='post_url')
21 @register.simple_tag(name='post_url')
11 def post_url(*args, **kwargs):
22 def post_url(*args, **kwargs):
@@ -21,3 +32,18 b' def post_url(*args, **kwargs):'
21 link = reverse(thread, kwargs={'post_id': post_id})
32 link = reverse(thread, kwargs={'post_id': post_id})
22
33
23 return link
34 return link
35
36
37 @register.simple_tag(name='image_actions')
38 def image_actions(*args, **kwargs):
39 image_link = args[0]
40 if len(args) > 1:
41 image_link = 'http://' + args[1] + image_link # TODO https?
42
43 result = ''
44
45 for action in actions:
46 result += '[<a href="' + action['link'] % image_link + '">' + \
47 action['name'] + '</a>]'
48
49 return result
@@ -3,6 +3,7 b''
3 django-thumbs by Antonio Melé
3 django-thumbs by Antonio Melé
4 http://django.es
4 http://django.es
5 """
5 """
6 from django.core.files.images import ImageFile
6 from django.db.models import ImageField
7 from django.db.models import ImageField
7 from django.db.models.fields.files import ImageFieldFile
8 from django.db.models.fields.files import ImageFieldFile
8 from PIL import Image
9 from PIL import Image
@@ -13,13 +14,13 b' import cStringIO'
13 def generate_thumb(img, thumb_size, format):
14 def generate_thumb(img, thumb_size, format):
14 """
15 """
15 Generates a thumbnail image and returns a ContentFile object with the thumbnail
16 Generates a thumbnail image and returns a ContentFile object with the thumbnail
16
17
17 Parameters:
18 Parameters:
18 ===========
19 ===========
19 img File object
20 img File object
20
21
21 thumb_size desired thumbnail size, ie: (200,120)
22 thumb_size desired thumbnail size, ie: (200,120)
22
23
23 format format of the original image ('jpeg','gif','png',...)
24 format format of the original image ('jpeg','gif','png',...)
24 (this format will be used for the generated thumbnail, too)
25 (this format will be used for the generated thumbnail, too)
25 """
26 """
@@ -41,7 +42,7 b' def generate_thumb(img, thumb_size, form'
41 # crop it
42 # crop it
42 image2 = image.crop(
43 image2 = image.crop(
43 (xnewsize, ynewsize, xsize - xnewsize, ysize - ynewsize))
44 (xnewsize, ynewsize, xsize - xnewsize, ysize - ynewsize))
44 # load is necessary after crop
45 # load is necessary after crop
45 image2.load()
46 image2.load()
46 # thumbnail of the cropped image (with ANTIALIAS to make it look better)
47 # thumbnail of the cropped image (with ANTIALIAS to make it look better)
47 image2.thumbnail(thumb_size, Image.ANTIALIAS)
48 image2.thumbnail(thumb_size, Image.ANTIALIAS)
@@ -160,7 +161,9 b' class ImageWithThumbsField(ImageField):'
160 """
161 """
161
162
162 def __init__(self, verbose_name=None, name=None, width_field=None,
163 def __init__(self, verbose_name=None, name=None, width_field=None,
163 height_field=None, sizes=None, **kwargs):
164 height_field=None, sizes=None,
165 preview_width_field=None, preview_height_field=None,
166 **kwargs):
164 self.verbose_name = verbose_name
167 self.verbose_name = verbose_name
165 self.name = name
168 self.name = name
166 self.width_field = width_field
169 self.width_field = width_field
@@ -168,6 +171,46 b' class ImageWithThumbsField(ImageField):'
168 self.sizes = sizes
171 self.sizes = sizes
169 super(ImageField, self).__init__(**kwargs)
172 super(ImageField, self).__init__(**kwargs)
170
173
174 if sizes is not None and len(sizes) == 1:
175 self.preview_width_field = preview_width_field
176 self.preview_height_field = preview_height_field
177
178 def update_dimension_fields(self, instance, force=False, *args, **kwargs):
179 """
180 Update original image dimension fields and thumb dimension fields
181 (only if 1 thumb size is defined)
182 """
183
184 super(ImageWithThumbsField, self).update_dimension_fields(instance,
185 force, *args,
186 **kwargs)
187 thumb_width_field = self.preview_width_field
188 thumb_height_field = self.preview_height_field
189
190 if thumb_width_field is None or thumb_height_field is None \
191 or len(self.sizes) != 1:
192 return
193
194 original_width = getattr(instance, self.width_field)
195 original_height = getattr(instance, self.height_field)
196
197 if original_width > 0 and original_height > 0:
198 thumb_width, thumb_height = self.sizes[0]
199
200 w_scale = float(thumb_width) / original_width
201 h_scale = float(thumb_height) / original_height
202 scale_ratio = min(w_scale, h_scale)
203
204 if scale_ratio >= 1:
205 thumb_width_ratio = original_width
206 thumb_height_ratio = original_height
207 else:
208 thumb_width_ratio = int(original_width * scale_ratio)
209 thumb_height_ratio = int(original_height * scale_ratio)
210
211 setattr(instance, thumb_width_field, thumb_width_ratio)
212 setattr(instance, thumb_height_field, thumb_height_ratio)
213
171
214
172 from south.modelsinspector import add_introspection_rules
215 from south.modelsinspector import add_introspection_rules
173 add_introspection_rules([], ["^boards\.thumbs\.ImageWithThumbsField"])
216 add_introspection_rules([], ["^boards\.thumbs\.ImageWithThumbsField"])
@@ -31,6 +31,7 b" urlpatterns = patterns('',"
31
31
32 # /boards/thread/
32 # /boards/thread/
33 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
33 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
34 url(r'^thread/(?P<post_id>\w+)/(?P<mode>\w+)/$', views.thread, name='thread_mode'),
34 url(r'^settings/$', views.settings, name='settings'),
35 url(r'^settings/$', views.settings, name='settings'),
35 url(r'^tags/$', views.all_tags, name='tags'),
36 url(r'^tags/$', views.all_tags, name='tags'),
36 url(r'^captcha/', include('captcha.urls')),
37 url(r'^captcha/', include('captcha.urls')),
@@ -7,7 +7,7 b' import re'
7
7
8 from django.core import serializers
8 from django.core import serializers
9 from django.core.urlresolvers import reverse
9 from django.core.urlresolvers import reverse
10 from django.http import HttpResponseRedirect
10 from django.http import HttpResponseRedirect, Http404
11 from django.http.response import HttpResponse
11 from django.http.response import HttpResponse
12 from django.template import RequestContext
12 from django.template import RequestContext
13 from django.shortcuts import render, redirect, get_object_or_404
13 from django.shortcuts import render, redirect, get_object_or_404
@@ -30,6 +30,8 b' import neboard'
30
30
31
31
32 BAN_REASON_SPAM = 'Autoban: spam bot'
32 BAN_REASON_SPAM = 'Autoban: spam bot'
33 MODE_GALLERY = 'gallery'
34 MODE_NORMAL = 'normal'
33
35
34
36
35 def index(request, page=0):
37 def index(request, page=0):
@@ -62,6 +64,7 b' def index(request, page=0):'
62 # TODO Make this generic for tag and threads list pages
64 # TODO Make this generic for tag and threads list pages
63 context['threads'] = None if len(threads) == 0 else threads
65 context['threads'] = None if len(threads) == 0 else threads
64 context['form'] = form
66 context['form'] = form
67 context['current_page'] = int(page)
65
68
66 page_count = Post.objects.get_thread_page_count()
69 page_count = Post.objects.get_thread_page_count()
67 context['pages'] = range(page_count)
70 context['pages'] = range(page_count)
@@ -154,6 +157,7 b' def tag(request, tag_name, page=0):'
154 context = _init_default_context(request)
157 context = _init_default_context(request)
155 context['threads'] = None if len(threads) == 0 else threads
158 context['threads'] = None if len(threads) == 0 else threads
156 context['tag'] = tag
159 context['tag'] = tag
160 context['current_page'] = int(page)
157
161
158 page_count = Post.objects.get_thread_page_count(tag=tag)
162 page_count = Post.objects.get_thread_page_count(tag=tag)
159 context['pages'] = range(page_count)
163 context['pages'] = range(page_count)
@@ -169,7 +173,7 b' def tag(request, tag_name, page=0):'
169 context)
173 context)
170
174
171
175
172 def thread(request, post_id):
176 def thread(request, post_id, mode=MODE_NORMAL):
173 """Get all thread posts"""
177 """Get all thread posts"""
174
178
175 if utils.need_include_captcha(request):
179 if utils.need_include_captcha(request):
@@ -209,7 +213,14 b' def thread(request, post_id):'
209 context["last_update"] = _datetime_to_epoch(thread_to_show.last_edit_time)
213 context["last_update"] = _datetime_to_epoch(thread_to_show.last_edit_time)
210 context["thread"] = thread_to_show
214 context["thread"] = thread_to_show
211
215
212 return render(request, 'boards/thread.html', context)
216 if MODE_NORMAL == mode:
217 document = 'boards/thread.html'
218 elif MODE_GALLERY == mode:
219 document = 'boards/thread_gallery.html'
220 else:
221 raise Http404
222
223 return render(request, document, context)
213
224
214
225
215 def login(request):
226 def login(request):
@@ -27,7 +27,7 b' Site: http://neboard.me/'
27 # INSTALLATION #
27 # INSTALLATION #
28
28
29 1. Install all dependencies over pip or system-wide
29 1. Install all dependencies over pip or system-wide
30 2. Setup a database in neboard/settings.py
30 2. Setup a database in `neboard/settings.py`
31 3. Run `./manage.py syncdb` and ensure the database was created
31 3. Run `./manage.py syncdb` and ensure the database was created
32 4. Run `./manage.py migrate boards` to apply all south migrations
32 4. Run `./manage.py migrate boards` to apply all south migrations
33
33
@@ -41,6 +41,15 b' See django-admin command help for detail'
41
41
42 Also consider using wsgi or fcgi interfaces on production servers.
42 Also consider using wsgi or fcgi interfaces on production servers.
43
43
44 # UPGRADE #
45
46 1. Backup your project data.
47 2. Save the settings in `neboard/settings.py` and `boards/settings.py`
48 3. Copy the project contents over the old project directory
49 4. Run migrations by `./manage.py migrate boards`
50
51 You can also just clone the mercurial project and pull it to update
52
44 # CONCLUSION #
53 # CONCLUSION #
45
54
46 Enjoy our software and thank you!
55 Enjoy our software and thank you!
@@ -12,6 +12,7 b' denied". Use second only for autoban for'
12 [DONE] Split up post model into post and thread,
12 [DONE] Split up post model into post and thread,
13 and move everything that is used only in 1st post to thread model.
13 and move everything that is used only in 1st post to thread model.
14 [DONE] Show board speed in the lower panel (posts per day)
14 [DONE] Show board speed in the lower panel (posts per day)
15 [DONE] Save image thumbnails size to the separate field
15
16
16 [NOT STARTED] Tree view (JS)
17 [NOT STARTED] Tree view (JS)
17 [NOT STARTED] Adding tags to images filename
18 [NOT STARTED] Adding tags to images filename
@@ -22,7 +23,6 b' and move everything that is used only in'
22 [NOT STARTED] Javascript disabling engine
23 [NOT STARTED] Javascript disabling engine
23 [NOT STARTED] Group tags by first letter in all tags list
24 [NOT STARTED] Group tags by first letter in all tags list
24 [NOT STARTED] Character counter in the post field
25 [NOT STARTED] Character counter in the post field
25 [NOT STARTED] Save image thumbnails size to the separate field
26 [NOT STARTED] Whitelist functionality. Permin autoban of an address
26 [NOT STARTED] Whitelist functionality. Permin autoban of an address
27 [NOT STARTED] Statistics module. Count views (optional, may result in bad
27 [NOT STARTED] Statistics module. Count views (optional, may result in bad
28 performance), posts per day/week/month, users (or IPs)
28 performance), posts per day/week/month, users (or IPs)
General Comments 0
You need to be logged in to leave comments. Login now