##// END OF EJS Templates
Added a hidden antispam field to the forms.
neko259 -
r207:b89107f5 default
parent child Browse files
Show More
@@ -1,209 +1,215 b''
1 import re
1 import re
2 from captcha.fields import CaptchaField
2 from captcha.fields import CaptchaField
3 from django import forms
3 from django import forms
4 from django.forms.util import ErrorList
4 from django.forms.util import ErrorList
5 from django.utils.translation import ugettext_lazy as _
5 from django.utils.translation import ugettext_lazy as _
6 import time
6 import time
7 from boards.models import TITLE_MAX_LENGTH, User
7 from boards.models import TITLE_MAX_LENGTH, User
8 from neboard import settings
8 from neboard import settings
9 from boards import utils
9 from boards import utils
10
10
11 LAST_POST_TIME = "last_post_time"
11 LAST_POST_TIME = "last_post_time"
12
12
13
13
14 class PlainErrorList(ErrorList):
14 class PlainErrorList(ErrorList):
15 def __unicode__(self):
15 def __unicode__(self):
16 return self.as_text()
16 return self.as_text()
17
17
18 def as_text(self):
18 def as_text(self):
19 return ''.join([u'(!) %s ' % e for e in self])
19 return ''.join([u'(!) %s ' % e for e in self])
20
20
21
21
22 class NeboardForm(forms.Form):
22 class NeboardForm(forms.Form):
23
23
24 def as_p(self):
24 def as_p(self):
25 "Returns this form rendered as HTML <p>s."
25 "Returns this form rendered as HTML <p>s."
26 return self._html_output(
26 return self._html_output(
27 normal_row='<div class="form-row">'
27 normal_row='<div class="form-row">'
28 '<div class="form-label">'
28 '<div class="form-label">'
29 '%(label)s'
29 '%(label)s'
30 '</div>'
30 '</div>'
31 '<div class="form-input">'
31 '<div class="form-input">'
32 '%(field)s'
32 '%(field)s'
33 '</div>'
33 '</div>'
34 '%(help_text)s'
34 '%(help_text)s'
35 '</div>',
35 '</div>',
36 error_row='<div class="form-errors">%s</div>',
36 error_row='<div class="form-errors">%s</div>',
37 row_ender='</p>',
37 row_ender='</p>',
38 help_text_html=' <span class="helptext">%s</span>',
38 help_text_html=' <span class="helptext">%s</span>',
39 errors_on_separate_row=True)
39 errors_on_separate_row=True)
40
40
41
41
42 class PostForm(NeboardForm):
42 class PostForm(NeboardForm):
43
43
44 MAX_TEXT_LENGTH = 30000
44 MAX_TEXT_LENGTH = 30000
45 MAX_IMAGE_SIZE = 8 * 1024 * 1024
45 MAX_IMAGE_SIZE = 8 * 1024 * 1024
46
46
47 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False)
47 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False)
48 text = forms.CharField(widget=forms.Textarea, required=False)
48 text = forms.CharField(widget=forms.Textarea, required=False)
49 image = forms.ImageField(required=False)
49 image = forms.ImageField(required=False)
50
50
51 # This field is for spam prevention only
52 email = forms.CharField(max_length=100, required=False)
53
51 session = None
54 session = None
52
55
53 def clean_title(self):
56 def clean_title(self):
54 title = self.cleaned_data['title']
57 title = self.cleaned_data['title']
55 if title:
58 if title:
56 if len(title) > TITLE_MAX_LENGTH:
59 if len(title) > TITLE_MAX_LENGTH:
57 raise forms.ValidationError('Title must have less than' +
60 raise forms.ValidationError('Title must have less than' +
58 str(TITLE_MAX_LENGTH) +
61 str(TITLE_MAX_LENGTH) +
59 ' characters.')
62 ' characters.')
60 return title
63 return title
61
64
62 def clean_text(self):
65 def clean_text(self):
63 text = self.cleaned_data['text']
66 text = self.cleaned_data['text']
64 if text:
67 if text:
65 if len(text) > self.MAX_TEXT_LENGTH:
68 if len(text) > self.MAX_TEXT_LENGTH:
66 raise forms.ValidationError('Text must have less than ' +
69 raise forms.ValidationError('Text must have less than ' +
67 str(self.MAX_TEXT_LENGTH) +
70 str(self.MAX_TEXT_LENGTH) +
68 ' characters.')
71 ' characters.')
69 return text
72 return text
70
73
71 def clean_image(self):
74 def clean_image(self):
72 image = self.cleaned_data['image']
75 image = self.cleaned_data['image']
73 if image:
76 if image:
74 if image._size > self.MAX_IMAGE_SIZE:
77 if image._size > self.MAX_IMAGE_SIZE:
75 raise forms.ValidationError('Image must be less than ' +
78 raise forms.ValidationError('Image must be less than ' +
76 str(self.MAX_IMAGE_SIZE) +
79 str(self.MAX_IMAGE_SIZE) +
77 ' bytes.')
80 ' bytes.')
78 return image
81 return image
79
82
80 def clean(self):
83 def clean(self):
81 cleaned_data = super(PostForm, self).clean()
84 cleaned_data = super(PostForm, self).clean()
82
85
86 if cleaned_data['email']:
87 raise forms.ValidationError('A human cannot enter a hidden field')
88
83 if not self.errors:
89 if not self.errors:
84 self._clean_text_image()
90 self._clean_text_image()
85
91
86 if not self.errors and self.session:
92 if not self.errors and self.session:
87 self._validate_posting_speed()
93 self._validate_posting_speed()
88
94
89 return cleaned_data
95 return cleaned_data
90
96
91 def _clean_text_image(self):
97 def _clean_text_image(self):
92 text = self.cleaned_data.get('text')
98 text = self.cleaned_data.get('text')
93 image = self.cleaned_data.get('image')
99 image = self.cleaned_data.get('image')
94
100
95 if (not text) and (not image):
101 if (not text) and (not image):
96 error_message = _('Either text or image must be entered.')
102 error_message = _('Either text or image must be entered.')
97 self._errors['text'] = self.error_class([error_message])
103 self._errors['text'] = self.error_class([error_message])
98
104
99 def _validate_posting_speed(self):
105 def _validate_posting_speed(self):
100 can_post = True
106 can_post = True
101
107
102 if LAST_POST_TIME in self.session:
108 if LAST_POST_TIME in self.session:
103 now = time.time()
109 now = time.time()
104 last_post_time = self.session[LAST_POST_TIME]
110 last_post_time = self.session[LAST_POST_TIME]
105
111
106 current_delay = int(now - last_post_time)
112 current_delay = int(now - last_post_time)
107
113
108 if current_delay < settings.POSTING_DELAY:
114 if current_delay < settings.POSTING_DELAY:
109 error_message = 'Wait ' + str(settings.POSTING_DELAY -
115 error_message = 'Wait ' + str(settings.POSTING_DELAY -
110 current_delay)\
116 current_delay)\
111 + ' seconds after last posting'
117 + ' seconds after last posting'
112 self._errors['text'] = self.error_class([error_message])
118 self._errors['text'] = self.error_class([error_message])
113
119
114 can_post = False
120 can_post = False
115
121
116 if can_post:
122 if can_post:
117 self.session[LAST_POST_TIME] = time.time()
123 self.session[LAST_POST_TIME] = time.time()
118
124
119
125
120 class ThreadForm(PostForm):
126 class ThreadForm(PostForm):
121 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
127 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
122 tags = forms.CharField(max_length=100)
128 tags = forms.CharField(max_length=100)
123
129
124 def clean_tags(self):
130 def clean_tags(self):
125 tags = self.cleaned_data['tags']
131 tags = self.cleaned_data['tags']
126
132
127 if tags:
133 if tags:
128 if not self.regex_tags.match(tags):
134 if not self.regex_tags.match(tags):
129 raise forms.ValidationError(
135 raise forms.ValidationError(
130 _('Inappropriate characters in tags.'))
136 _('Inappropriate characters in tags.'))
131
137
132 return tags
138 return tags
133
139
134 def clean(self):
140 def clean(self):
135 cleaned_data = super(ThreadForm, self).clean()
141 cleaned_data = super(ThreadForm, self).clean()
136
142
137 return cleaned_data
143 return cleaned_data
138
144
139
145
140 class PostCaptchaForm(PostForm):
146 class PostCaptchaForm(PostForm):
141 captcha = CaptchaField()
147 captcha = CaptchaField()
142
148
143 def __init__(self, *args, **kwargs):
149 def __init__(self, *args, **kwargs):
144 self.request = kwargs['request']
150 self.request = kwargs['request']
145 del kwargs['request']
151 del kwargs['request']
146
152
147 super(PostCaptchaForm, self).__init__(*args, **kwargs)
153 super(PostCaptchaForm, self).__init__(*args, **kwargs)
148
154
149 def clean(self):
155 def clean(self):
150 cleaned_data = super(PostCaptchaForm, self).clean()
156 cleaned_data = super(PostCaptchaForm, self).clean()
151
157
152 success = self.is_valid()
158 success = self.is_valid()
153 utils.update_captcha_access(self.request, success)
159 utils.update_captcha_access(self.request, success)
154
160
155 if success:
161 if success:
156 return cleaned_data
162 return cleaned_data
157 else:
163 else:
158 raise forms.ValidationError(_("Captcha validation failed"))
164 raise forms.ValidationError(_("Captcha validation failed"))
159
165
160
166
161 class ThreadCaptchaForm(ThreadForm):
167 class ThreadCaptchaForm(ThreadForm):
162 captcha = CaptchaField()
168 captcha = CaptchaField()
163
169
164 def __init__(self, *args, **kwargs):
170 def __init__(self, *args, **kwargs):
165 self.request = kwargs['request']
171 self.request = kwargs['request']
166 del kwargs['request']
172 del kwargs['request']
167
173
168 super(ThreadCaptchaForm, self).__init__(*args, **kwargs)
174 super(ThreadCaptchaForm, self).__init__(*args, **kwargs)
169
175
170 def clean(self):
176 def clean(self):
171 cleaned_data = super(ThreadCaptchaForm, self).clean()
177 cleaned_data = super(ThreadCaptchaForm, self).clean()
172
178
173 success = self.is_valid()
179 success = self.is_valid()
174 utils.update_captcha_access(self.request, success)
180 utils.update_captcha_access(self.request, success)
175
181
176 if success:
182 if success:
177 return cleaned_data
183 return cleaned_data
178 else:
184 else:
179 raise forms.ValidationError(_("Captcha validation failed"))
185 raise forms.ValidationError(_("Captcha validation failed"))
180
186
181
187
182 class SettingsForm(NeboardForm):
188 class SettingsForm(NeboardForm):
183
189
184 theme = forms.ChoiceField(choices=settings.THEMES,
190 theme = forms.ChoiceField(choices=settings.THEMES,
185 label=_('Theme'))
191 label=_('Theme'))
186
192
187
193
188 class ModeratorSettingsForm(SettingsForm):
194 class ModeratorSettingsForm(SettingsForm):
189
195
190 moderate = forms.BooleanField(required=False, label=_('Enable moderation '
196 moderate = forms.BooleanField(required=False, label=_('Enable moderation '
191 'panel'))
197 'panel'))
192
198
193
199
194 class LoginForm(NeboardForm):
200 class LoginForm(NeboardForm):
195 user_id = forms.CharField()
201 user_id = forms.CharField()
196
202
197 def clean_user_id(self):
203 def clean_user_id(self):
198 user_id = self.cleaned_data['user_id']
204 user_id = self.cleaned_data['user_id']
199 if user_id:
205 if user_id:
200 users = User.objects.filter(user_id=user_id)
206 users = User.objects.filter(user_id=user_id)
201 if len(users) == 0:
207 if len(users) == 0:
202 raise forms.ValidationError(_('No such user found'))
208 raise forms.ValidationError(_('No such user found'))
203
209
204 return user_id
210 return user_id
205
211
206 def clean(self):
212 def clean(self):
207 cleaned_data = super(LoginForm, self).clean()
213 cleaned_data = super(LoginForm, self).clean()
208
214
209 return cleaned_data No newline at end of file
215 return cleaned_data
@@ -1,307 +1,311 b''
1 html {
1 html {
2 background: #555;
2 background: #555;
3 color: #ffffff;
3 color: #ffffff;
4 }
4 }
5
5
6 #admin_panel {
6 #admin_panel {
7 background: #FF0000;
7 background: #FF0000;
8 color: #00FF00
8 color: #00FF00
9 }
9 }
10
10
11 .input_field {
11 .input_field {
12
12
13 }
13 }
14
14
15 .input_field_name {
15 .input_field_name {
16
16
17 }
17 }
18
18
19 .input_field_error {
19 .input_field_error {
20 color: #FF0000;
20 color: #FF0000;
21 }
21 }
22
22
23
23
24 .title {
24 .title {
25 font-weight: bold;
25 font-weight: bold;
26 color: #ffcc00;
26 color: #ffcc00;
27 }
27 }
28
28
29 .link, a {
29 .link, a {
30 color: #afdcec;
30 color: #afdcec;
31 }
31 }
32
32
33 .block {
33 .block {
34 display: inline-block;
34 display: inline-block;
35 vertical-align: top;
35 vertical-align: top;
36 }
36 }
37
37
38 .tag {
38 .tag {
39 color: #b4cfec;
39 color: #b4cfec;
40 }
40 }
41
41
42 .post_id {
42 .post_id {
43 color: #fff380;
43 color: #fff380;
44 }
44 }
45
45
46 .post, .dead_post, #posts-table {
46 .post, .dead_post, #posts-table {
47 background: #333;
47 background: #333;
48 margin: 5px;
48 margin: 5px;
49 padding: 10px;
49 padding: 10px;
50 border: solid 1px #888;
50 border: solid 1px #888;
51 clear: left;
51 clear: left;
52 word-wrap: break-word;
52 word-wrap: break-word;
53 }
53 }
54
54
55 .metadata {
55 .metadata {
56 padding: 5px;
56 padding: 5px;
57 margin-top: 10px;
57 margin-top: 10px;
58 border: solid 1px #666;
58 border: solid 1px #666;
59 font-size: 0.9em;
59 font-size: 0.9em;
60 color: #ddd;
60 color: #ddd;
61 display: table;
61 display: table;
62 }
62 }
63
63
64 .navigation_panel, .tag_info {
64 .navigation_panel, .tag_info {
65 background: #444;
65 background: #444;
66 margin: 5px;
66 margin: 5px;
67 padding: 10px;
67 padding: 10px;
68 border: solid 1px #888;
68 border: solid 1px #888;
69 color: #eee;
69 color: #eee;
70 }
70 }
71
71
72 .navigation_panel .link {
72 .navigation_panel .link {
73 border-right: 1px solid #fff;
73 border-right: 1px solid #fff;
74 font-weight: bold;
74 font-weight: bold;
75 margin-right: 1ex;
75 margin-right: 1ex;
76 padding-right: 1ex;
76 padding-right: 1ex;
77 }
77 }
78 .navigation_panel .link:last-child {
78 .navigation_panel .link:last-child {
79 border-left: 1px solid #fff;
79 border-left: 1px solid #fff;
80 border-right: none;
80 border-right: none;
81 float: right;
81 float: right;
82 margin-left: 1ex;
82 margin-left: 1ex;
83 margin-right: 0;
83 margin-right: 0;
84 padding-left: 1ex;
84 padding-left: 1ex;
85 padding-right: 0;
85 padding-right: 0;
86 }
86 }
87
87
88 .navigation_panel::after, .post::after {
88 .navigation_panel::after, .post::after {
89 clear: both;
89 clear: both;
90 content: ".";
90 content: ".";
91 display: block;
91 display: block;
92 height: 0;
92 height: 0;
93 line-height: 0;
93 line-height: 0;
94 visibility: hidden;
94 visibility: hidden;
95 }
95 }
96
96
97 p {
97 p {
98 margin-top: .5em;
98 margin-top: .5em;
99 margin-bottom: .5em;
99 margin-bottom: .5em;
100 }
100 }
101
101
102 .post-form-w {
102 .post-form-w {
103 display: table;
103 display: table;
104 background: #333344;
104 background: #333344;
105 border: solid 1px #888;
105 border: solid 1px #888;
106 color: #fff;
106 color: #fff;
107 padding: 10px;
107 padding: 10px;
108 margin: 5px
108 margin: 5px
109 }
109 }
110
110
111 .form-row {
111 .form-row {
112 display: table-row;
112 display: table-row;
113 }
113 }
114
114
115 .form-label, .form-input, .form-errors {
115 .form-label, .form-input, .form-errors {
116 display: table-cell;
116 display: table-cell;
117 }
117 }
118
118
119 .form-label {
119 .form-label {
120 padding: .25em 1ex .25em 0;
120 padding: .25em 1ex .25em 0;
121 vertical-align: top;
121 vertical-align: top;
122 }
122 }
123
123
124 .form-input {
124 .form-input {
125 padding: .25em 0;
125 padding: .25em 0;
126 }
126 }
127
127
128 .form-errors {
128 .form-errors {
129 padding-left: 1ex;
129 padding-left: 1ex;
130 font-weight: bold;
130 font-weight: bold;
131 vertical-align: middle;
131 vertical-align: middle;
132 }
132 }
133
133
134 .post-form input, .post-form textarea {
134 .post-form input, .post-form textarea {
135 background: #333;
135 background: #333;
136 color: #fff;
136 color: #fff;
137 border: solid 1px;
137 border: solid 1px;
138 padding: 0;
138 padding: 0;
139 width: 100%;
139 width: 100%;
140 }
140 }
141
141
142 .form-submit {
142 .form-submit {
143 border-bottom: 2px solid #ddd;
143 border-bottom: 2px solid #ddd;
144 margin-bottom: .5em;
144 margin-bottom: .5em;
145 padding-bottom: .5em;
145 padding-bottom: .5em;
146 }
146 }
147
147
148 .form-title {
148 .form-title {
149 font-weight: bold;
149 font-weight: bold;
150 }
150 }
151
151
152 input[type="submit"] {
152 input[type="submit"] {
153 background: #222;
153 background: #222;
154 border: solid 1px #fff;
154 border: solid 1px #fff;
155 color: #fff;
155 color: #fff;
156 }
156 }
157
157
158 blockquote {
158 blockquote {
159 border-left: solid 2px;
159 border-left: solid 2px;
160 padding-left: 5px;
160 padding-left: 5px;
161 color: #B1FB17;
161 color: #B1FB17;
162 margin: 0;
162 margin: 0;
163 }
163 }
164
164
165 .post > .image {
165 .post > .image {
166 float: left;
166 float: left;
167 margin: 0 1ex .5ex 0;
167 margin: 0 1ex .5ex 0;
168 min-width: 1px;
168 min-width: 1px;
169 text-align: center;
169 text-align: center;
170 display: table-row;
170 display: table-row;
171
171
172 height: 150px;
172 height: 150px;
173 }
173 }
174
174
175 .post > .metadata {
175 .post > .metadata {
176 clear: left;
176 clear: left;
177 }
177 }
178
178
179 .get {
179 .get {
180 font-weight: bold;
180 font-weight: bold;
181 color: #d55;
181 color: #d55;
182 }
182 }
183
183
184 * {
184 * {
185 text-decoration: none;
185 text-decoration: none;
186 }
186 }
187
187
188 .dead_post {
188 .dead_post {
189 background-color: #442222;
189 background-color: #442222;
190 }
190 }
191
191
192 .quote {
192 .quote {
193 color: #92cf38;
193 color: #92cf38;
194 font-style: italic;
194 font-style: italic;
195 }
195 }
196
196
197 .spoiler {
197 .spoiler {
198 background: white;
198 background: white;
199 color: white;
199 color: white;
200 }
200 }
201
201
202 .spoiler:hover {
202 .spoiler:hover {
203 color: black;
203 color: black;
204 }
204 }
205
205
206 .comment {
206 .comment {
207 color: #eb2;
207 color: #eb2;
208 font-style: italic;
208 font-style: italic;
209 }
209 }
210
210
211 a:hover {
211 a:hover {
212 text-decoration: underline;
212 text-decoration: underline;
213 }
213 }
214
214
215 .last-replies {
215 .last-replies {
216 margin-left: 3ex;
216 margin-left: 3ex;
217 }
217 }
218
218
219 .thread {
219 .thread {
220 margin-bottom: 3ex;
220 margin-bottom: 3ex;
221 }
221 }
222
222
223 .post:target {
223 .post:target {
224 border: solid 2px white;
224 border: solid 2px white;
225 }
225 }
226
226
227 pre{
227 pre{
228 white-space:pre-wrap
228 white-space:pre-wrap
229 }
229 }
230
230
231 li {
231 li {
232 list-style-position: inside;
232 list-style-position: inside;
233 }
233 }
234
234
235 .fancybox-skin {
235 .fancybox-skin {
236 position: relative;
236 position: relative;
237 background-color: #fff;
237 background-color: #fff;
238 color: #ddd;
238 color: #ddd;
239 text-shadow: none;
239 text-shadow: none;
240 }
240 }
241
241
242 .fancybox-image {
242 .fancybox-image {
243 border: 1px solid black;
243 border: 1px solid black;
244 }
244 }
245
245
246 .image-mode-tab {
246 .image-mode-tab {
247 background: #444;
247 background: #444;
248 color: #eee;
248 color: #eee;
249 display: table;
249 display: table;
250 margin: 5px;
250 margin: 5px;
251 padding: 5px;
251 padding: 5px;
252 border: 1px solid #888;
252 border: 1px solid #888;
253 }
253 }
254
254
255 .image-mode-tab > label {
255 .image-mode-tab > label {
256 margin: 0 1ex;
256 margin: 0 1ex;
257 }
257 }
258
258
259 .image-mode-tab > label > input {
259 .image-mode-tab > label > input {
260 margin-right: .5ex;
260 margin-right: .5ex;
261 }
261 }
262
262
263 #posts-table {
263 #posts-table {
264 margin: 5px;
264 margin: 5px;
265 }
265 }
266
266
267 .tag_info {
267 .tag_info {
268 display: table;
268 display: table;
269 }
269 }
270
270
271 .tag_info > h2 {
271 .tag_info > h2 {
272 margin: 0;
272 margin: 0;
273 }
273 }
274
274
275 .post-info {
275 .post-info {
276 color: #ddd;
276 color: #ddd;
277 }
277 }
278
278
279 .moderator_info {
279 .moderator_info {
280 color: #e99d41;
280 color: #e99d41;
281 float: right;
281 float: right;
282 border: dashed 1px;
282 border: dashed 1px;
283 padding: 3px;
283 padding: 3px;
284 }
284 }
285
285
286 .refmap {
286 .refmap {
287 font-size: 0.9em;
287 font-size: 0.9em;
288 color: #ccc;
288 color: #ccc;
289 margin-top: 1em;
289 margin-top: 1em;
290 }
290 }
291
291
292 input[type="submit"]:hover {
292 input[type="submit"]:hover {
293 background: #555;
293 background: #555;
294 }
294 }
295
295
296
296
297 .fav {
297 .fav {
298 color: yellow;
298 color: yellow;
299 }
299 }
300
300
301 .not_fav {
301 .not_fav {
302 color: #ccc;
302 color: #ccc;
303 }
303 }
304
304
305 .role {
305 .role {
306 text-decoration: underline;
306 text-decoration: underline;
307 } No newline at end of file
307 }
308
309 .form-email {
310 display: none;
311 }
@@ -1,304 +1,308 b''
1 html {
1 html {
2 background: rgb(238, 238, 238);
2 background: rgb(238, 238, 238);
3 color: rgb(51, 51, 51);
3 color: rgb(51, 51, 51);
4 }
4 }
5
5
6 #admin_panel {
6 #admin_panel {
7 background: #FF0000;
7 background: #FF0000;
8 color: #00FF00
8 color: #00FF00
9 }
9 }
10
10
11 .input_field {
11 .input_field {
12
12
13 }
13 }
14
14
15 .input_field_name {
15 .input_field_name {
16
16
17 }
17 }
18
18
19 .input_field_error {
19 .input_field_error {
20 color: #FF0000;
20 color: #FF0000;
21 }
21 }
22
22
23
23
24 .title {
24 .title {
25 font-weight: bold;
25 font-weight: bold;
26 color: #333;
26 color: #333;
27 font-size: 2ex;
27 font-size: 2ex;
28 }
28 }
29
29
30 .link, a {
30 .link, a {
31 color: rgb(255, 102, 0);
31 color: rgb(255, 102, 0);
32 }
32 }
33
33
34 .block {
34 .block {
35 display: inline-block;
35 display: inline-block;
36 vertical-align: top;
36 vertical-align: top;
37 }
37 }
38
38
39 .tag {
39 .tag {
40 color: #222;
40 color: #222;
41 }
41 }
42
42
43 .post_id:hover {
43 .post_id:hover {
44 color: #11f;
44 color: #11f;
45 }
45 }
46
46
47 .post_id {
47 .post_id {
48 color: #444;
48 color: #444;
49 }
49 }
50
50
51 .post, .dead_post, #posts-table {
51 .post, .dead_post, #posts-table {
52 margin: 5px;
52 margin: 5px;
53 padding: 10px;
53 padding: 10px;
54 background: rgb(221, 221, 221);
54 background: rgb(221, 221, 221);
55 border: 1px solid rgb(204, 204, 204);
55 border: 1px solid rgb(204, 204, 204);
56 border-radius: 5px 5px 5px 5px;
56 border-radius: 5px 5px 5px 5px;
57 clear: left;
57 clear: left;
58 word-wrap: break-word;
58 word-wrap: break-word;
59 display: table;
59 display: table;
60 }
60 }
61
61
62 .metadata {
62 .metadata {
63 padding: 5px;
63 padding: 5px;
64 margin-top: 10px;
64 margin-top: 10px;
65 border: solid 1px #666;
65 border: solid 1px #666;
66 font-size: 0.9em;
66 font-size: 0.9em;
67 display: table;
67 display: table;
68 }
68 }
69
69
70 .navigation_panel, .tag_info {
70 .navigation_panel, .tag_info {
71 margin: 5px;
71 margin: 5px;
72 padding: 10px;
72 padding: 10px;
73 border: 1px solid rgb(204, 204, 204);
73 border: 1px solid rgb(204, 204, 204);
74 border-radius: 5px 5px 5px 5px;
74 border-radius: 5px 5px 5px 5px;
75 }
75 }
76
76
77 .navigation_panel .link {
77 .navigation_panel .link {
78 border-right: 1px solid #000;
78 border-right: 1px solid #000;
79 font-weight: bold;
79 font-weight: bold;
80 margin-right: 1ex;
80 margin-right: 1ex;
81 padding-right: 1ex;
81 padding-right: 1ex;
82 }
82 }
83 .navigation_panel .link:last-child {
83 .navigation_panel .link:last-child {
84 border-left: 1px solid #000;
84 border-left: 1px solid #000;
85 border-right: none;
85 border-right: none;
86 float: right;
86 float: right;
87 margin-left: 1ex;
87 margin-left: 1ex;
88 margin-right: 0;
88 margin-right: 0;
89 padding-left: 1ex;
89 padding-left: 1ex;
90 padding-right: 0;
90 padding-right: 0;
91 }
91 }
92
92
93 .navigation_panel::after, .post::after {
93 .navigation_panel::after, .post::after {
94 clear: both;
94 clear: both;
95 content: ".";
95 content: ".";
96 display: block;
96 display: block;
97 height: 0;
97 height: 0;
98 line-height: 0;
98 line-height: 0;
99 visibility: hidden;
99 visibility: hidden;
100 }
100 }
101
101
102 p {
102 p {
103 margin-top: .5em;
103 margin-top: .5em;
104 margin-bottom: .5em;
104 margin-bottom: .5em;
105 }
105 }
106
106
107 .post-form-w {
107 .post-form-w {
108 display: table;
108 display: table;
109 padding: 10px;
109 padding: 10px;
110 margin: 5px
110 margin: 5px
111 }
111 }
112
112
113 .form-row {
113 .form-row {
114 display: table-row;
114 display: table-row;
115 }
115 }
116
116
117 .form-label, .form-input, .form-errors {
117 .form-label, .form-input, .form-errors {
118 display: table-cell;
118 display: table-cell;
119 }
119 }
120
120
121 .form-label {
121 .form-label {
122 padding: .25em 1ex .25em 0;
122 padding: .25em 1ex .25em 0;
123 vertical-align: top;
123 vertical-align: top;
124 }
124 }
125
125
126 .form-input {
126 .form-input {
127 padding: .25em 0;
127 padding: .25em 0;
128 }
128 }
129
129
130 .form-errors {
130 .form-errors {
131 padding-left: 1ex;
131 padding-left: 1ex;
132 font-weight: bold;
132 font-weight: bold;
133 vertical-align: middle;
133 vertical-align: middle;
134 }
134 }
135
135
136 .post-form input, .post-form textarea {
136 .post-form input, .post-form textarea {
137 background: #fff;
137 background: #fff;
138 color: #000;
138 color: #000;
139 border: solid 1px;
139 border: solid 1px;
140 padding: 0;
140 padding: 0;
141 width: 100%;
141 width: 100%;
142 }
142 }
143
143
144 .form-submit {
144 .form-submit {
145 border-bottom: 2px solid #ddd;
145 border-bottom: 2px solid #ddd;
146 margin-bottom: .5em;
146 margin-bottom: .5em;
147 padding-bottom: .5em;
147 padding-bottom: .5em;
148 }
148 }
149
149
150 .form-title {
150 .form-title {
151 font-weight: bold;
151 font-weight: bold;
152 }
152 }
153
153
154 input[type="submit"] {
154 input[type="submit"] {
155 background: #fff;
155 background: #fff;
156 border: solid 1px #000;
156 border: solid 1px #000;
157 color: #000;
157 color: #000;
158 }
158 }
159
159
160 blockquote {
160 blockquote {
161 border-left: solid 2px;
161 border-left: solid 2px;
162 padding-left: 5px;
162 padding-left: 5px;
163 color: #B1FB17;
163 color: #B1FB17;
164 margin: 0;
164 margin: 0;
165 }
165 }
166
166
167 .post > .image {
167 .post > .image {
168 float: left;
168 float: left;
169 margin: 0 1ex .5ex 0;
169 margin: 0 1ex .5ex 0;
170 min-width: 1px;
170 min-width: 1px;
171 text-align: center;
171 text-align: center;
172 display: table-row;
172 display: table-row;
173
173
174 height: 150px;
174 height: 150px;
175 }
175 }
176
176
177 .post > .metadata {
177 .post > .metadata {
178 clear: left;
178 clear: left;
179 }
179 }
180
180
181 .get {
181 .get {
182 font-weight: bold;
182 font-weight: bold;
183 color: #d55;
183 color: #d55;
184 }
184 }
185
185
186 * {
186 * {
187 text-decoration: none;
187 text-decoration: none;
188 }
188 }
189
189
190 .dead_post {
190 .dead_post {
191 background-color: #ecc;
191 background-color: #ecc;
192 }
192 }
193
193
194 .quote {
194 .quote {
195 color: #080;
195 color: #080;
196 font-style: italic;
196 font-style: italic;
197 }
197 }
198
198
199 .spoiler {
199 .spoiler {
200 background: white;
200 background: white;
201 color: white;
201 color: white;
202 }
202 }
203
203
204 .spoiler:hover {
204 .spoiler:hover {
205 color: black;
205 color: black;
206 }
206 }
207
207
208 .comment {
208 .comment {
209 color: #8B6914;
209 color: #8B6914;
210 font-style: italic;
210 font-style: italic;
211 }
211 }
212
212
213 a:hover {
213 a:hover {
214 text-decoration: underline;
214 text-decoration: underline;
215 }
215 }
216
216
217 .last-replies {
217 .last-replies {
218 margin-left: 3ex;
218 margin-left: 3ex;
219 }
219 }
220
220
221 .thread {
221 .thread {
222 margin-bottom: 3ex;
222 margin-bottom: 3ex;
223 }
223 }
224
224
225 .post:target {
225 .post:target {
226 border: solid 2px black;
226 border: solid 2px black;
227 }
227 }
228
228
229 pre{
229 pre{
230 white-space:pre-wrap
230 white-space:pre-wrap
231 }
231 }
232
232
233 li {
233 li {
234 list-style-position: inside;
234 list-style-position: inside;
235 }
235 }
236
236
237 .fancybox-skin {
237 .fancybox-skin {
238 position: relative;
238 position: relative;
239 background-color: #fff;
239 background-color: #fff;
240 color: #ddd;
240 color: #ddd;
241 text-shadow: none;
241 text-shadow: none;
242 }
242 }
243
243
244 .fancybox-image {
244 .fancybox-image {
245 border: 1px solid black;
245 border: 1px solid black;
246 }
246 }
247
247
248 .image-mode-tab {
248 .image-mode-tab {
249 display: table;
249 display: table;
250 margin: 5px;
250 margin: 5px;
251 padding: 5px;
251 padding: 5px;
252 background: rgb(221, 221, 221);
252 background: rgb(221, 221, 221);
253 border: 1px solid rgb(204, 204, 204);
253 border: 1px solid rgb(204, 204, 204);
254 border-radius: 5px 5px 5px 5px;
254 border-radius: 5px 5px 5px 5px;
255 }
255 }
256
256
257 .image-mode-tab > label {
257 .image-mode-tab > label {
258 margin: 0 1ex;
258 margin: 0 1ex;
259 }
259 }
260
260
261 .image-mode-tab > label > input {
261 .image-mode-tab > label > input {
262 margin-right: .5ex;
262 margin-right: .5ex;
263 }
263 }
264
264
265 #posts-table {
265 #posts-table {
266 margin: 5px;
266 margin: 5px;
267 }
267 }
268
268
269 .tag_info {
269 .tag_info {
270 display: table;
270 display: table;
271 }
271 }
272
272
273 .tag_info > h2 {
273 .tag_info > h2 {
274 margin: 0;
274 margin: 0;
275 }
275 }
276
276
277 .moderator_info {
277 .moderator_info {
278 color: #e99d41;
278 color: #e99d41;
279 border: dashed 1px;
279 border: dashed 1px;
280 padding: 3px;
280 padding: 3px;
281 }
281 }
282
282
283 .refmap {
283 .refmap {
284 font-size: 0.9em;
284 font-size: 0.9em;
285 color: #444;
285 color: #444;
286 margin-top: 1em;
286 margin-top: 1em;
287 }
287 }
288
288
289 input[type="submit"]:hover {
289 input[type="submit"]:hover {
290 background: #ccc;
290 background: #ccc;
291 }
291 }
292
292
293
293
294 .fav {
294 .fav {
295 color: rgb(255, 102, 0);
295 color: rgb(255, 102, 0);
296 }
296 }
297
297
298 .not_fav {
298 .not_fav {
299 color: #555;
299 color: #555;
300 }
300 }
301
301
302 .role {
302 .role {
303 text-decoration: underline;
303 text-decoration: underline;
304 } No newline at end of file
304 }
305
306 .form-email {
307 display: none;
308 }
@@ -1,287 +1,291 b''
1 * {
1 * {
2 font-size: inherit;
2 font-size: inherit;
3 margin: 0;
3 margin: 0;
4 padding: 0;
4 padding: 0;
5 }
5 }
6 html {
6 html {
7 background: #fff;
7 background: #fff;
8 color: #000;
8 color: #000;
9 font: medium sans-serif;
9 font: medium sans-serif;
10 }
10 }
11 a {
11 a {
12 color: inherit;
12 color: inherit;
13 text-decoration: underline;
13 text-decoration: underline;
14 }
14 }
15 li {
15 li {
16 list-style-position: inside;
16 list-style-position: inside;
17 }
17 }
18
18
19 #admin_panel {
19 #admin_panel {
20 background: #182F6F;
20 background: #182F6F;
21 color: #fff;
21 color: #fff;
22 padding: .5ex 1ex .5ex 1ex;
22 padding: .5ex 1ex .5ex 1ex;
23 }
23 }
24
24
25 .navigation_panel {
25 .navigation_panel {
26 background: #182F6F;
26 background: #182F6F;
27 color: #B4CFEC;
27 color: #B4CFEC;
28 margin-bottom: 1em;
28 margin-bottom: 1em;
29 padding: .5ex 1ex 1ex 1ex;
29 padding: .5ex 1ex 1ex 1ex;
30 }
30 }
31 .navigation_panel::after {
31 .navigation_panel::after {
32 clear: both;
32 clear: both;
33 content: ".";
33 content: ".";
34 display: block;
34 display: block;
35 height: 0;
35 height: 0;
36 line-height: 0;
36 line-height: 0;
37 visibility: hidden;
37 visibility: hidden;
38 }
38 }
39
39
40 .navigation_panel a:link, .navigation_panel a:visited, .navigation_panel a:hover {
40 .navigation_panel a:link, .navigation_panel a:visited, .navigation_panel a:hover {
41 text-decoration: none;
41 text-decoration: none;
42 }
42 }
43
43
44 .navigation_panel .link {
44 .navigation_panel .link {
45 border-right: 1px solid #fff;
45 border-right: 1px solid #fff;
46 color: #fff;
46 color: #fff;
47 font-weight: bold;
47 font-weight: bold;
48 margin-right: 1ex;
48 margin-right: 1ex;
49 padding-right: 1ex;
49 padding-right: 1ex;
50 }
50 }
51 .navigation_panel .link:last-child {
51 .navigation_panel .link:last-child {
52 border-left: 1px solid #fff;
52 border-left: 1px solid #fff;
53 border-right: none;
53 border-right: none;
54 float: right;
54 float: right;
55 margin-left: 1ex;
55 margin-left: 1ex;
56 margin-right: 0;
56 margin-right: 0;
57 padding-left: 1ex;
57 padding-left: 1ex;
58 padding-right: 0;
58 padding-right: 0;
59 }
59 }
60
60
61 .navigation_panel .tag {
61 .navigation_panel .tag {
62 color: #fff;
62 color: #fff;
63 }
63 }
64
64
65 .input_field {
65 .input_field {
66
66
67 }
67 }
68
68
69 .input_field_name {
69 .input_field_name {
70
70
71 }
71 }
72
72
73 .input_field_error {
73 .input_field_error {
74 color: #FF0000;
74 color: #FF0000;
75 }
75 }
76
76
77
77
78 .title {
78 .title {
79 color: #182F6F;
79 color: #182F6F;
80 font-weight: bold;
80 font-weight: bold;
81 }
81 }
82
82
83 .post-form-w {
83 .post-form-w {
84 background: #182F6F;
84 background: #182F6F;
85 border-radius: 1ex;
85 border-radius: 1ex;
86 color: #fff;
86 color: #fff;
87 margin: 1em 1ex;
87 margin: 1em 1ex;
88 padding: 1ex;
88 padding: 1ex;
89 }
89 }
90 .post-form {
90 .post-form {
91 display: table;
91 display: table;
92 border-collapse: collapse;
92 border-collapse: collapse;
93 width: 100%;
93 width: 100%;
94
94
95 }
95 }
96 .form-row {
96 .form-row {
97 display: table-row;
97 display: table-row;
98 }
98 }
99 .form-label, .form-input {
99 .form-label, .form-input {
100 display: table-cell;
100 display: table-cell;
101 vertical-align: top;
101 vertical-align: top;
102 }
102 }
103 .form-label {
103 .form-label {
104 padding: .25em 1ex .25em 0;
104 padding: .25em 1ex .25em 0;
105 }
105 }
106 .form-input {
106 .form-input {
107 padding: .25em 0;
107 padding: .25em 0;
108 }
108 }
109 .form-input > * {
109 .form-input > * {
110 background: #fff;
110 background: #fff;
111 color: #000;
111 color: #000;
112 border: none;
112 border: none;
113 padding: 0;
113 padding: 0;
114 resize: vertical;
114 resize: vertical;
115 width: 100%;
115 width: 100%;
116 }
116 }
117 .form-submit {
117 .form-submit {
118 border-bottom: 1px solid #666;
118 border-bottom: 1px solid #666;
119 margin-bottom: .5em;
119 margin-bottom: .5em;
120 padding-bottom: .5em;
120 padding-bottom: .5em;
121 }
121 }
122 .form-title {
122 .form-title {
123 font-weight: bold;
123 font-weight: bold;
124 margin-bottom: .5em;
124 margin-bottom: .5em;
125 }
125 }
126 .post-form .settings_item {
126 .post-form .settings_item {
127 margin: .5em 0;
127 margin: .5em 0;
128 }
128 }
129 .form-submit input {
129 .form-submit input {
130 margin-top: .5em;
130 margin-top: .5em;
131 padding: .2em 1ex;
131 padding: .2em 1ex;
132 }
132 }
133 .form-label {
133 .form-label {
134 text-align: right;
134 text-align: right;
135 }
135 }
136
136
137 .block {
137 .block {
138 display: inline-block;
138 display: inline-block;
139 vertical-align: top;
139 vertical-align: top;
140 }
140 }
141
141
142 .post_id {
142 .post_id {
143 color: #a00;
143 color: #a00;
144 }
144 }
145
145
146 .post {
146 .post {
147 clear: left;
147 clear: left;
148 margin: 0 1ex 1em 1ex;
148 margin: 0 1ex 1em 1ex;
149 overflow-x: auto;
149 overflow-x: auto;
150 word-wrap: break-word;
150 word-wrap: break-word;
151 }
151 }
152 .last-replies > .post, #posts > .post {
152 .last-replies > .post, #posts > .post {
153 border-bottom: 1px solid #182F6F;
153 border-bottom: 1px solid #182F6F;
154 padding-bottom: 1em;
154 padding-bottom: 1em;
155 }
155 }
156 #posts > .post:last-child {
156 #posts > .post:last-child {
157 border-bottom: none;
157 border-bottom: none;
158 padding-bottom: 0;
158 padding-bottom: 0;
159 }
159 }
160
160
161 .metadata {
161 .metadata {
162 background: #C0E4E8;
162 background: #C0E4E8;
163 border: 1px solid #7F9699;
163 border: 1px solid #7F9699;
164 border-radius: .4ex;
164 border-radius: .4ex;
165 display: table;
165 display: table;
166 margin-top: .5em;
166 margin-top: .5em;
167 padding: .4em;
167 padding: .4em;
168 }
168 }
169
169
170 .post ul, .post ol {
170 .post ul, .post ol {
171 margin: .5em 0 .5em 3ex;
171 margin: .5em 0 .5em 3ex;
172 }
172 }
173 .post li {
173 .post li {
174 margin: .2em 0;
174 margin: .2em 0;
175 }
175 }
176 .post p {
176 .post p {
177 margin: .5em 0;
177 margin: .5em 0;
178 }
178 }
179 .post blockquote {
179 .post blockquote {
180 border-left: 3px solid #182F6F;
180 border-left: 3px solid #182F6F;
181 margin: .5em 0 .5em 3ex;
181 margin: .5em 0 .5em 3ex;
182 padding-left: 1ex;
182 padding-left: 1ex;
183 }
183 }
184 .post blockquote > blockquote {
184 .post blockquote > blockquote {
185 padding-top: .1em;
185 padding-top: .1em;
186 }
186 }
187
187
188 .post > .image {
188 .post > .image {
189 float: left;
189 float: left;
190 margin-right: 1ex;
190 margin-right: 1ex;
191 }
191 }
192 .post > .metadata {
192 .post > .metadata {
193 clear: left;
193 clear: left;
194 }
194 }
195
195
196 .post > .message .get {
196 .post > .message .get {
197 color: #182F6F; font-weight: bold;
197 color: #182F6F; font-weight: bold;
198 }
198 }
199
199
200 .dead_post > .metadata {
200 .dead_post > .metadata {
201 background: #eee;
201 background: #eee;
202 }
202 }
203
203
204 .quote {
204 .quote {
205 color: #182F6F;
205 color: #182F6F;
206 }
206 }
207
207
208 .spoiler {
208 .spoiler {
209 background: black;
209 background: black;
210 color: black;
210 color: black;
211 }
211 }
212
212
213 .spoiler:hover {
213 .spoiler:hover {
214 background: #ffffff;
214 background: #ffffff;
215 }
215 }
216
216
217 .comment {
217 .comment {
218 color: #557055;
218 color: #557055;
219 }
219 }
220
220
221 .last-replies {
221 .last-replies {
222 margin-left: 6ex;
222 margin-left: 6ex;
223 }
223 }
224
224
225 .thread > .post > .message > .post-info {
225 .thread > .post > .message > .post-info {
226 border-bottom: 2px solid #182F6F;
226 border-bottom: 2px solid #182F6F;
227 padding-bottom: .5em;
227 padding-bottom: .5em;
228 }
228 }
229
229
230 .last-replies > .post:last-child {
230 .last-replies > .post:last-child {
231 border-bottom: none;
231 border-bottom: none;
232 padding-bottom: 0;
232 padding-bottom: 0;
233 }
233 }
234
234
235 :target .post_id {
235 :target .post_id {
236 background: #182F6F;
236 background: #182F6F;
237 color: #FFF;
237 color: #FFF;
238 text-decoration: none;
238 text-decoration: none;
239 }
239 }
240
240
241 .image-mode-tab {
241 .image-mode-tab {
242 background: #182F6F;
242 background: #182F6F;
243 color: #FFF;
243 color: #FFF;
244 display: table;
244 display: table;
245 margin: 1em auto 1em 0;
245 margin: 1em auto 1em 0;
246 padding: .2em .5ex;
246 padding: .2em .5ex;
247 }
247 }
248
248
249 .image-mode-tab > label {
249 .image-mode-tab > label {
250 margin: 0 1ex;
250 margin: 0 1ex;
251 }
251 }
252
252
253 .image-mode-tab > label > input {
253 .image-mode-tab > label > input {
254 margin-right: .5ex;
254 margin-right: .5ex;
255 }
255 }
256
256
257 .tag_info {
257 .tag_info {
258 margin: 1em 0;
258 margin: 1em 0;
259 text-align: center;
259 text-align: center;
260 }
260 }
261
261
262 .form-errors {
262 .form-errors {
263 margin-left: 1ex;
263 margin-left: 1ex;
264 }
264 }
265
265
266 .moderator_info {
266 .moderator_info {
267 font-weight: bold;
267 font-weight: bold;
268 float: right;
268 float: right;
269 }
269 }
270
270
271 .refmap {
271 .refmap {
272 border: 1px dashed #aaa;
272 border: 1px dashed #aaa;
273 padding: 0.5em;
273 padding: 0.5em;
274 display: table;
274 display: table;
275 }
275 }
276
276
277 .fav {
277 .fav {
278 color: blue;
278 color: blue;
279 }
279 }
280
280
281 .not_fav {
281 .not_fav {
282 color: #ccc;
282 color: #ccc;
283 }
283 }
284
284
285 .role {
285 .role {
286 text-decoration: underline;
286 text-decoration: underline;
287 } No newline at end of file
287 }
288
289 .form-email {
290 display: none;
291 }
@@ -1,191 +1,196 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load markup %}
4 {% load markup %}
5 {% load cache %}
5 {% load cache %}
6
6
7 {% block head %}
7 {% block head %}
8 {% if tag %}
8 {% if tag %}
9 <title>Neboard - {{ tag.name }}</title>
9 <title>Neboard - {{ tag.name }}</title>
10 {% else %}
10 {% else %}
11 <title>Neboard</title>
11 <title>Neboard</title>
12 {% endif %}
12 {% endif %}
13 {% endblock %}
13 {% endblock %}
14
14
15 {% block content %}
15 {% block content %}
16
16
17 {% if tag %}
17 {% if tag %}
18 <div class="tag_info">
18 <div class="tag_info">
19 <h2>{% trans 'Tag: ' %}{{ tag.name }}
19 <h2>{% trans 'Tag: ' %}{{ tag.name }}
20 {% if tag in user.fav_tags.all %}
20 {% if tag in user.fav_tags.all %}
21 <a href="{% url 'tag_unsubscribe' tag.name %}?next={{ request.path }}"
21 <a href="{% url 'tag_unsubscribe' tag.name %}?next={{ request.path }}"
22 class="fav">β˜…</a>
22 class="fav">β˜…</a>
23 {% else %}
23 {% else %}
24 <a href="{% url 'tag_subscribe' tag.name %}?next={{ request.path }}"
24 <a href="{% url 'tag_subscribe' tag.name %}?next={{ request.path }}"
25 class="not_fav">β˜…</a>
25 class="not_fav">β˜…</a>
26 {% endif %}
26 {% endif %}
27 </h2>
27 </h2>
28 </div>
28 </div>
29 {% endif %}
29 {% endif %}
30
30
31 {% if threads %}
31 {% if threads %}
32 {% for thread in threads %}
32 {% for thread in threads %}
33 <div class="thread">
33 <div class="thread">
34 {% if thread.bumpable %}
34 {% if thread.bumpable %}
35 <div class="post" id="{{ thread.thread.id }}">
35 <div class="post" id="{{ thread.thread.id }}">
36 {% else %}
36 {% else %}
37 <div class="post dead_post" id="{{ thread.thread.id }}">
37 <div class="post dead_post" id="{{ thread.thread.id }}">
38 {% endif %}
38 {% endif %}
39 {% if thread.thread.image %}
39 {% if thread.thread.image %}
40 <div class="image">
40 <div class="image">
41 <a class="fancy"
41 <a class="fancy"
42 href="{{ thread.thread.image.url }}"><img
42 href="{{ thread.thread.image.url }}"><img
43 src="{{ thread.thread.image.url_200x150 }}"
43 src="{{ thread.thread.image.url_200x150 }}"
44 alt="{% trans 'Post image' %}"
44 alt="{% trans 'Post image' %}"
45 data-width="{{ thread.thread.image_width }}"
45 data-width="{{ thread.thread.image_width }}"
46 data-height="{{ thread.thread.image_height }}" />
46 data-height="{{ thread.thread.image_height }}" />
47 </a>
47 </a>
48 </div>
48 </div>
49 {% endif %}
49 {% endif %}
50 <div class="message">
50 <div class="message">
51 <div class="post-info">
51 <div class="post-info">
52 <span class="title">{{ thread.thread.title }}</span>
52 <span class="title">{{ thread.thread.title }}</span>
53 <a class="post_id" href="{% url 'thread' thread.thread.id %}"
53 <a class="post_id" href="{% url 'thread' thread.thread.id %}"
54 >(#{{ thread.thread.id }})</a>
54 >(#{{ thread.thread.id }})</a>
55 [{{ thread.thread.pub_time }}]
55 [{{ thread.thread.pub_time }}]
56 [<a class="link" href="{% url 'thread' thread.thread.id %}#form"
56 [<a class="link" href="{% url 'thread' thread.thread.id %}#form"
57 >{% trans "Reply" %}</a>]
57 >{% trans "Reply" %}</a>]
58
58
59 {% if moderator %}
59 {% if moderator %}
60 <span class="moderator_info">
60 <span class="moderator_info">
61 [<a href="{% url 'delete' post_id=thread.thread.id %}?next={{ request.path }}"
61 [<a href="{% url 'delete' post_id=thread.thread.id %}?next={{ request.path }}"
62 >{% trans 'Delete' %}</a>]
62 >{% trans 'Delete' %}</a>]
63 ({{ thread.thread.poster_ip }})
63 ({{ thread.thread.poster_ip }})
64 [<a href="{% url 'ban' post_id=thread.thread.id %}?next={{ request.path }}"
64 [<a href="{% url 'ban' post_id=thread.thread.id %}?next={{ request.path }}"
65 >{% trans 'Ban IP' %}</a>]
65 >{% trans 'Ban IP' %}</a>]
66 </span>
66 </span>
67 {% endif %}
67 {% endif %}
68 </div>
68 </div>
69 {% autoescape off %}
69 {% autoescape off %}
70 {{ thread.thread.text.rendered|truncatewords_html:50 }}
70 {{ thread.thread.text.rendered|truncatewords_html:50 }}
71 {% endautoescape %}
71 {% endautoescape %}
72 </div>
72 </div>
73 <div class="metadata">
73 <div class="metadata">
74 {{ thread.thread.get_reply_count }} {% trans 'replies' %},
74 {{ thread.thread.get_reply_count }} {% trans 'replies' %},
75 {{ thread.thread.get_images_count }} {% trans 'images' %}.
75 {{ thread.thread.get_images_count }} {% trans 'images' %}.
76 {% if thread.thread.tags %}
76 {% if thread.thread.tags %}
77 <span class="tags">{% trans 'Tags' %}:
77 <span class="tags">{% trans 'Tags' %}:
78 {% for tag in thread.thread.tags.all %}
78 {% for tag in thread.thread.tags.all %}
79 <a class="tag" href="
79 <a class="tag" href="
80 {% url 'tag' tag_name=tag.name %}">
80 {% url 'tag' tag_name=tag.name %}">
81 {{ tag.name }}</a>
81 {{ tag.name }}</a>
82 {% endfor %}
82 {% endfor %}
83 </span>
83 </span>
84 {% endif %}
84 {% endif %}
85 </div>
85 </div>
86 </div>
86 </div>
87 {% if thread.thread.get_last_replies.exists %}
87 {% if thread.thread.get_last_replies.exists %}
88 <div class="last-replies">
88 <div class="last-replies">
89 {% for post in thread.thread.get_last_replies %}
89 {% for post in thread.thread.get_last_replies %}
90 {% if thread.bumpable %}
90 {% if thread.bumpable %}
91 <div class="post" id="{{ post.id }}">
91 <div class="post" id="{{ post.id }}">
92 {% else %}
92 {% else %}
93 <div class="post dead_post" id="{{ post.id }}">
93 <div class="post dead_post" id="{{ post.id }}">
94 {% endif %}
94 {% endif %}
95 {% if post.image %}
95 {% if post.image %}
96 <div class="image">
96 <div class="image">
97 <a class="fancy"
97 <a class="fancy"
98 href="{{ post.image.url }}"><img
98 href="{{ post.image.url }}"><img
99 src=" {{ post.image.url_200x150 }}"
99 src=" {{ post.image.url_200x150 }}"
100 alt="{% trans 'Post image' %}"
100 alt="{% trans 'Post image' %}"
101 data-width="{{ post.image_width }}"
101 data-width="{{ post.image_width }}"
102 data-height="{{ post.image_height }}"/>
102 data-height="{{ post.image_height }}"/>
103 </a>
103 </a>
104 </div>
104 </div>
105 {% endif %}
105 {% endif %}
106 <div class="message">
106 <div class="message">
107 <div class="post-info">
107 <div class="post-info">
108 <span class="title">{{ post.title }}</span>
108 <span class="title">{{ post.title }}</span>
109 <a class="post_id" href="
109 <a class="post_id" href="
110 {% url 'thread' thread.thread.id %}#{{ post.id }}">
110 {% url 'thread' thread.thread.id %}#{{ post.id }}">
111 (#{{ post.id }})</a>
111 (#{{ post.id }})</a>
112 [{{ post.pub_time }}]
112 [{{ post.pub_time }}]
113 </div>
113 </div>
114 {% autoescape off %}
114 {% autoescape off %}
115 {{ post.text.rendered|truncatewords_html:50 }}
115 {{ post.text.rendered|truncatewords_html:50 }}
116 {% endautoescape %}
116 {% endautoescape %}
117 </div>
117 </div>
118 </div>
118 </div>
119 {% endfor %}
119 {% endfor %}
120 </div>
120 </div>
121 {% endif %}
121 {% endif %}
122 </div>
122 </div>
123 {% endfor %}
123 {% endfor %}
124 {% else %}
124 {% else %}
125 <div class="post">
125 <div class="post">
126 {% trans 'No threads exist. Create the first one!' %}</div>
126 {% trans 'No threads exist. Create the first one!' %}</div>
127 {% endif %}
127 {% endif %}
128
128
129 <form enctype="multipart/form-data" method="post">{% csrf_token %}
129 <form enctype="multipart/form-data" method="post">{% csrf_token %}
130 <div class="post-form-w">
130 <div class="post-form-w">
131
131
132 <div class="form-title">{% trans "Create new thread" %}</div>
132 <div class="form-title">{% trans "Create new thread" %}</div>
133 <div class="post-form">
133 <div class="post-form">
134 <div class="form-row">
134 <div class="form-row">
135 <div class="form-label">{% trans 'Title' %}</div>
135 <div class="form-label">{% trans 'Title' %}</div>
136 <div class="form-input">{{ form.title }}</div>
136 <div class="form-input">{{ form.title }}</div>
137 <div class="form-errors">{{ form.title.errors }}</div>
137 <div class="form-errors">{{ form.title.errors }}</div>
138 </div>
138 </div>
139 <div class="form-row">
139 <div class="form-row">
140 <div class="form-label">{% trans 'Text' %}</div>
140 <div class="form-label">{% trans 'Text' %}</div>
141 <div class="form-input">{{ form.text }}</div>
141 <div class="form-input">{{ form.text }}</div>
142 <div class="form-errors">{{ form.text.errors }}</div>
142 <div class="form-errors">{{ form.text.errors }}</div>
143 </div>
143 </div>
144 <div class="form-row">
144 <div class="form-row">
145 <div class="form-label">{% trans 'Image' %}</div>
145 <div class="form-label">{% trans 'Image' %}</div>
146 <div class="form-input">{{ form.image }}</div>
146 <div class="form-input">{{ form.image }}</div>
147 <div class="form-errors">{{ form.image.errors }}</div>
147 <div class="form-errors">{{ form.image.errors }}</div>
148 </div>
148 </div>
149 <div class="form-row">
149 <div class="form-row">
150 <div class="form-label">{% trans 'Tags' %}</div>
150 <div class="form-label">{% trans 'Tags' %}</div>
151 <div class="form-input">{{ form.tags }}</div>
151 <div class="form-input">{{ form.tags }}</div>
152 <div class="form-errors">{{ form.tags.errors }}</div>
152 <div class="form-errors">{{ form.tags.errors }}</div>
153 </div>
153 </div>
154 <div class="form-row form-email">
155 <div class="form-label">{% trans 'e-mail' %}</div>
156 <div class="form-input">{{ form.email }}</div>
157 <div class="form-errors">{{ form.email.errors }}</div>
158 </div>
154 <div class="form-row">
159 <div class="form-row">
155 {{ form.captcha }}
160 {{ form.captcha }}
156 <div class="form-errors">{{ form.captcha.errors }}</div>
161 <div class="form-errors">{{ form.captcha.errors }}</div>
157 </div>
162 </div>
158 <div class="form-row">
163 <div class="form-row">
159 <div class="form-errors">{{ form.other.errors }}</div>
164 <div class="form-errors">{{ form.other.errors }}</div>
160 </div>
165 </div>
161 </div>
166 </div>
162 <div class="form-submit">
167 <div class="form-submit">
163 <input type="submit" value="{% trans "Post" %}"/></div>
168 <input type="submit" value="{% trans "Post" %}"/></div>
164 <div>
169 <div>
165 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
170 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
166 </div>
171 </div>
167 <div><a href="{% url "staticpage" name="help" %}">
172 <div><a href="{% url "staticpage" name="help" %}">
168 {% trans 'Text syntax' %}</a></div>
173 {% trans 'Text syntax' %}</a></div>
169 </div>
174 </div>
170 </form>
175 </form>
171
176
172 {% endblock %}
177 {% endblock %}
173
178
174 {% block metapanel %}
179 {% block metapanel %}
175
180
176 <span class="metapanel">
181 <span class="metapanel">
177 <b><a href="{% url "authors" %}">Neboard</a> 1.1</b>
182 <b><a href="{% url "authors" %}">Neboard</a> 1.1</b>
178 {% trans "Pages:" %}
183 {% trans "Pages:" %}
179 {% for page in pages %}
184 {% for page in pages %}
180 [<a href="
185 [<a href="
181 {% if tag %}
186 {% if tag %}
182 {% url "tag" tag_name=tag page=page %}
187 {% url "tag" tag_name=tag page=page %}
183 {% else %}
188 {% else %}
184 {% url "index" page=page %}
189 {% url "index" page=page %}
185 {% endif %}
190 {% endif %}
186 ">{{ page }}</a>]
191 ">{{ page }}</a>]
187 {% endfor %}
192 {% endfor %}
188 [<a href="rss/">RSS</a>]
193 [<a href="rss/">RSS</a>]
189 </span>
194 </span>
190
195
191 {% endblock %}
196 {% endblock %}
@@ -1,123 +1,128 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load markup %}
4 {% load markup %}
5 {% load cache %}
5 {% load cache %}
6
6
7 {% block head %}
7 {% block head %}
8 <title>Neboard - {{ posts.0.get_title }}</title>
8 <title>Neboard - {{ posts.0.get_title }}</title>
9 {% endblock %}
9 {% endblock %}
10
10
11 {% block content %}
11 {% block content %}
12 <script src="{{ STATIC_URL }}js/thread.js"></script>
12 <script src="{{ STATIC_URL }}js/thread.js"></script>
13
13
14 {% if posts %}
14 {% if posts %}
15 {% cache 600 thread_view posts.0.last_edit_time moderator %}
15 {% cache 600 thread_view posts.0.last_edit_time moderator %}
16 <div id="posts">
16 <div id="posts">
17 {% for post in posts %}
17 {% for post in posts %}
18 {% if bumpable %}
18 {% if bumpable %}
19 <div class="post" id="{{ post.id }}">
19 <div class="post" id="{{ post.id }}">
20 {% else %}
20 {% else %}
21 <div class="post dead_post" id="{{ post.id }}">
21 <div class="post dead_post" id="{{ post.id }}">
22 {% endif %}
22 {% endif %}
23 {% if post.image %}
23 {% if post.image %}
24 <div class="image">
24 <div class="image">
25 <a
25 <a
26 class="fancy"
26 class="fancy"
27 href="{{ post.image.url }}"><img
27 href="{{ post.image.url }}"><img
28 src="{{ post.image.url_200x150 }}"
28 src="{{ post.image.url_200x150 }}"
29 alt="{% trans 'Post image' %}"v
29 alt="{% trans 'Post image' %}"v
30 data-width="{{ post.image_width }}"
30 data-width="{{ post.image_width }}"
31 data-height="{{ post.image_height }}"/>
31 data-height="{{ post.image_height }}"/>
32 </a>
32 </a>
33 </div>
33 </div>
34 {% endif %}
34 {% endif %}
35 <div class="message">
35 <div class="message">
36 <div class="post-info">
36 <div class="post-info">
37 <span class="title">{{ post.title }}</span>
37 <span class="title">{{ post.title }}</span>
38 <a class="post_id" href="#{{ post.id }}">
38 <a class="post_id" href="#{{ post.id }}">
39 (#{{ post.id }})</a>
39 (#{{ post.id }})</a>
40 [{{ post.pub_time }}]
40 [{{ post.pub_time }}]
41 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
41 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
42 ; return false;">&gt;&gt;</a>]
42 ; return false;">&gt;&gt;</a>]
43
43
44 {% if moderator %}
44 {% if moderator %}
45 <span class="moderator_info">
45 <span class="moderator_info">
46 [<a href="{% url 'delete' post_id=post.id %}"
46 [<a href="{% url 'delete' post_id=post.id %}"
47 >{% trans 'Delete' %}</a>]
47 >{% trans 'Delete' %}</a>]
48 ({{ post.poster_ip }})
48 ({{ post.poster_ip }})
49 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
49 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
50 >{% trans 'Ban IP' %}</a>]
50 >{% trans 'Ban IP' %}</a>]
51 </span>
51 </span>
52 {% endif %}
52 {% endif %}
53 </div>
53 </div>
54 {% autoescape off %}
54 {% autoescape off %}
55 {{ post.text.rendered }}
55 {{ post.text.rendered }}
56 {% endautoescape %}
56 {% endautoescape %}
57 </div>
57 </div>
58 {% if post.id == posts.0.id %}
58 {% if post.id == posts.0.id %}
59 <div class="metadata">
59 <div class="metadata">
60 <span class="tags">{% trans 'Tags' %}:
60 <span class="tags">{% trans 'Tags' %}:
61 {% for tag in post.tags.all %}
61 {% for tag in post.tags.all %}
62 <a class="tag" href="{% url 'tag' tag.name %}">
62 <a class="tag" href="{% url 'tag' tag.name %}">
63 {{ tag.name }}</a>
63 {{ tag.name }}</a>
64 {% endfor %}
64 {% endfor %}
65 </span>
65 </span>
66 </div>
66 </div>
67 {% endif %}
67 {% endif %}
68 </div>
68 </div>
69 {% endfor %}
69 {% endfor %}
70 </div>
70 </div>
71 {% endcache %}
71 {% endcache %}
72 {% endif %}
72 {% endif %}
73
73
74 <form id="form" enctype="multipart/form-data" method="post"
74 <form id="form" enctype="multipart/form-data" method="post"
75 >{% csrf_token %}
75 >{% csrf_token %}
76 <div class="post-form-w">
76 <div class="post-form-w">
77 <div class="form-title">{% trans "Reply to thread" %} #{{ posts.0.id }}</div>
77 <div class="form-title">{% trans "Reply to thread" %} #{{ posts.0.id }}</div>
78 <div class="post-form">
78 <div class="post-form">
79 <div class="form-row">
79 <div class="form-row">
80 <div class="form-label">{% trans 'Title' %}</div>
80 <div class="form-label">{% trans 'Title' %}</div>
81 <div class="form-input">{{ form.title }}</div>
81 <div class="form-input">{{ form.title }}</div>
82 <div class="form-errors">{{ form.title.errors }}</div>
82 <div class="form-errors">{{ form.title.errors }}</div>
83 </div>
83 </div>
84 <div class="form-row">
84 <div class="form-row">
85 <div class="form-label">{% trans 'Text' %}</div>
85 <div class="form-label">{% trans 'Text' %}</div>
86 <div class="form-input">{{ form.text }}</div>
86 <div class="form-input">{{ form.text }}</div>
87 <div class="form-errors">{{ form.text.errors }}</div>
87 <div class="form-errors">{{ form.text.errors }}</div>
88 </div>
88 </div>
89 <div class="form-row">
89 <div class="form-row">
90 <div class="form-label">{% trans 'Image' %}</div>
90 <div class="form-label">{% trans 'Image' %}</div>
91 <div class="form-input">{{ form.image }}</div>
91 <div class="form-input">{{ form.image }}</div>
92 <div class="form-errors">{{ form.image.errors }}</div>
92 <div class="form-errors">{{ form.image.errors }}</div>
93 </div>
93 </div>
94 <div class="form-row form-email">
95 <div class="form-label">{% trans 'e-mail' %}</div>
96 <div class="form-input">{{ form.email }}</div>
97 <div class="form-errors">{{ form.email.errors }}</div>
98 </div>
94 <div class="form-row">
99 <div class="form-row">
95 {{ form.captcha }}
100 {{ form.captcha }}
96 <div class="form-errors">{{ form.captcha.errors }}</div>
101 <div class="form-errors">{{ form.captcha.errors }}</div>
97 </div>
102 </div>
98 <div class="form-row">
103 <div class="form-row">
99 <div class="form-errors">{{ form.other.errors }}</div>
104 <div class="form-errors">{{ form.other.errors }}</div>
100 </div>
105 </div>
101 </div>
106 </div>
102
107
103 <div class="form-submit"><input type="submit"
108 <div class="form-submit"><input type="submit"
104 value="{% trans "Post" %}"/></div>
109 value="{% trans "Post" %}"/></div>
105 <div><a href="{% url "staticpage" name="help" %}">
110 <div><a href="{% url "staticpage" name="help" %}">
106 {% trans 'Text syntax' %}</a></div>
111 {% trans 'Text syntax' %}</a></div>
107 </div>
112 </div>
108 </form>
113 </form>
109
114
110 {% endblock %}
115 {% endblock %}
111
116
112 {% block metapanel %}
117 {% block metapanel %}
113
118
114 <span class="metapanel">
119 <span class="metapanel">
115 {% cache 600 thread_meta posts.0.last_edit_time moderator %}
120 {% cache 600 thread_meta posts.0.last_edit_time moderator %}
116 {{ posts.0.get_reply_count }} {% trans 'replies' %},
121 {{ posts.0.get_reply_count }} {% trans 'replies' %},
117 {{ posts.0.get_images_count }} {% trans 'images' %}.
122 {{ posts.0.get_images_count }} {% trans 'images' %}.
118 {% trans 'Last update: ' %}{{ posts.0.last_edit_time }}
123 {% trans 'Last update: ' %}{{ posts.0.last_edit_time }}
119 [<a href="rss/">RSS</a>]
124 [<a href="rss/">RSS</a>]
120 {% endcache %}
125 {% endcache %}
121 </span>
126 </span>
122
127
123 {% endblock %}
128 {% endblock %}
General Comments 0
You need to be logged in to leave comments. Login now