##// END OF EJS Templates
Small style and forms rendering changes
neko259 -
r426:7ce7bc5e default
parent child Browse files
Show More
@@ -1,253 +1,256 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.post import TITLE_MAX_LENGTH
7 from boards.models.post import TITLE_MAX_LENGTH
8 from boards.models import User
8 from boards.models import User
9 from neboard import settings
9 from neboard import settings
10 from boards import utils
10 from boards import utils
11 import boards.settings as board_settings
11 import boards.settings as board_settings
12
12
13 LAST_POST_TIME = "last_post_time"
13 LAST_POST_TIME = "last_post_time"
14 LAST_LOGIN_TIME = "last_login_time"
14 LAST_LOGIN_TIME = "last_login_time"
15
15
16
16
17 class PlainErrorList(ErrorList):
17 class PlainErrorList(ErrorList):
18 def __unicode__(self):
18 def __unicode__(self):
19 return self.as_text()
19 return self.as_text()
20
20
21 def as_text(self):
21 def as_text(self):
22 return ''.join([u'(!) %s ' % e for e in self])
22 return ''.join([u'(!) %s ' % e for e in self])
23
23
24
24
25 class NeboardForm(forms.Form):
25 class NeboardForm(forms.Form):
26
26
27 def as_p(self):
27 def as_div(self):
28 "Returns this form rendered as HTML <p>s."
28 "Returns this form rendered as HTML <as_div>s."
29 return self._html_output(
29 return self._html_output(
30 # TODO Do not show hidden rows in the list here
30 # TODO Do not show hidden rows in the list here
31 normal_row='<div class="form-row">'
31 normal_row='<div class="form-row">'
32 '<div class="form-label">'
32 '<div class="form-label">'
33 '%(label)s'
33 '%(label)s'
34 '</div>'
34 '</div>'
35 '<div class="form-input">'
35 '<div class="form-input">'
36 '%(field)s'
36 '%(field)s'
37 '</div>'
37 '</div>'
38 '%(help_text)s'
38 '%(help_text)s'
39 '</div>',
39 '</div>',
40 error_row='<div class="form-row"><div class="form-label"></div><div class="form-errors">%s</div></div>',
40 error_row='<div class="form-row">'
41 row_ender='</p>',
41 '<div class="form-label"></div>'
42 help_text_html=' <span class="helptext">%s</span>',
42 '<div class="form-errors">%s</div>'
43 '</div>',
44 row_ender='</div>',
45 help_text_html='%s',
43 errors_on_separate_row=True)
46 errors_on_separate_row=True)
44
47
45 class PostForm(NeboardForm):
48 class PostForm(NeboardForm):
46
49
47 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False,
50 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False,
48 label=_('Title'))
51 label=_('Title'))
49 text = forms.CharField(widget=forms.Textarea, required=False,
52 text = forms.CharField(widget=forms.Textarea, required=False,
50 label=_('Text'))
53 label=_('Text'))
51 image = forms.ImageField(required=False, label=_('Image'))
54 image = forms.ImageField(required=False, label=_('Image'))
52
55
53 # This field is for spam prevention only
56 # This field is for spam prevention only
54 email = forms.CharField(max_length=100, required=False, label=_('e-mail'),
57 email = forms.CharField(max_length=100, required=False, label=_('e-mail'),
55 widget=forms.TextInput(attrs={
58 widget=forms.TextInput(attrs={
56 'class': 'form-email'}))
59 'class': 'form-email'}))
57
60
58 session = None
61 session = None
59 need_to_ban = False
62 need_to_ban = False
60
63
61 def clean_title(self):
64 def clean_title(self):
62 title = self.cleaned_data['title']
65 title = self.cleaned_data['title']
63 if title:
66 if title:
64 if len(title) > TITLE_MAX_LENGTH:
67 if len(title) > TITLE_MAX_LENGTH:
65 raise forms.ValidationError(_('Title must have less than %s '
68 raise forms.ValidationError(_('Title must have less than %s '
66 'characters') %
69 'characters') %
67 str(TITLE_MAX_LENGTH))
70 str(TITLE_MAX_LENGTH))
68 return title
71 return title
69
72
70 def clean_text(self):
73 def clean_text(self):
71 text = self.cleaned_data['text']
74 text = self.cleaned_data['text']
72 if text:
75 if text:
73 if len(text) > board_settings.MAX_TEXT_LENGTH:
76 if len(text) > board_settings.MAX_TEXT_LENGTH:
74 raise forms.ValidationError(_('Text must have less than %s '
77 raise forms.ValidationError(_('Text must have less than %s '
75 'characters') %
78 'characters') %
76 str(board_settings
79 str(board_settings
77 .MAX_TEXT_LENGTH))
80 .MAX_TEXT_LENGTH))
78 return text
81 return text
79
82
80 def clean_image(self):
83 def clean_image(self):
81 image = self.cleaned_data['image']
84 image = self.cleaned_data['image']
82 if image:
85 if image:
83 if image._size > board_settings.MAX_IMAGE_SIZE:
86 if image._size > board_settings.MAX_IMAGE_SIZE:
84 raise forms.ValidationError(
87 raise forms.ValidationError(
85 _('Image must be less than %s bytes')
88 _('Image must be less than %s bytes')
86 % str(board_settings.MAX_IMAGE_SIZE))
89 % str(board_settings.MAX_IMAGE_SIZE))
87 return image
90 return image
88
91
89 def clean(self):
92 def clean(self):
90 cleaned_data = super(PostForm, self).clean()
93 cleaned_data = super(PostForm, self).clean()
91
94
92 if not self.session:
95 if not self.session:
93 raise forms.ValidationError('Humans have sessions')
96 raise forms.ValidationError('Humans have sessions')
94
97
95 if cleaned_data['email']:
98 if cleaned_data['email']:
96 self.need_to_ban = True
99 self.need_to_ban = True
97 raise forms.ValidationError('A human cannot enter a hidden field')
100 raise forms.ValidationError('A human cannot enter a hidden field')
98
101
99 if not self.errors:
102 if not self.errors:
100 self._clean_text_image()
103 self._clean_text_image()
101
104
102 if not self.errors and self.session:
105 if not self.errors and self.session:
103 self._validate_posting_speed()
106 self._validate_posting_speed()
104
107
105 return cleaned_data
108 return cleaned_data
106
109
107 def _clean_text_image(self):
110 def _clean_text_image(self):
108 text = self.cleaned_data.get('text')
111 text = self.cleaned_data.get('text')
109 image = self.cleaned_data.get('image')
112 image = self.cleaned_data.get('image')
110
113
111 if (not text) and (not image):
114 if (not text) and (not image):
112 error_message = _('Either text or image must be entered.')
115 error_message = _('Either text or image must be entered.')
113 self._errors['text'] = self.error_class([error_message])
116 self._errors['text'] = self.error_class([error_message])
114
117
115 def _validate_posting_speed(self):
118 def _validate_posting_speed(self):
116 can_post = True
119 can_post = True
117
120
118 if LAST_POST_TIME in self.session:
121 if LAST_POST_TIME in self.session:
119 now = time.time()
122 now = time.time()
120 last_post_time = self.session[LAST_POST_TIME]
123 last_post_time = self.session[LAST_POST_TIME]
121
124
122 current_delay = int(now - last_post_time)
125 current_delay = int(now - last_post_time)
123
126
124 if current_delay < settings.POSTING_DELAY:
127 if current_delay < settings.POSTING_DELAY:
125 error_message = _('Wait %s seconds after last posting') % str(
128 error_message = _('Wait %s seconds after last posting') % str(
126 settings.POSTING_DELAY - current_delay)
129 settings.POSTING_DELAY - current_delay)
127 self._errors['text'] = self.error_class([error_message])
130 self._errors['text'] = self.error_class([error_message])
128
131
129 can_post = False
132 can_post = False
130
133
131 if can_post:
134 if can_post:
132 self.session[LAST_POST_TIME] = time.time()
135 self.session[LAST_POST_TIME] = time.time()
133
136
134
137
135 class ThreadForm(PostForm):
138 class ThreadForm(PostForm):
136
139
137 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
140 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
138
141
139 tags = forms.CharField(max_length=100, label=_('Tags'))
142 tags = forms.CharField(max_length=100, label=_('Tags'))
140
143
141 def clean_tags(self):
144 def clean_tags(self):
142 tags = self.cleaned_data['tags']
145 tags = self.cleaned_data['tags']
143
146
144 if tags:
147 if tags:
145 if not self.regex_tags.match(tags):
148 if not self.regex_tags.match(tags):
146 raise forms.ValidationError(
149 raise forms.ValidationError(
147 _('Inappropriate characters in tags.'))
150 _('Inappropriate characters in tags.'))
148
151
149 return tags
152 return tags
150
153
151 def clean(self):
154 def clean(self):
152 cleaned_data = super(ThreadForm, self).clean()
155 cleaned_data = super(ThreadForm, self).clean()
153
156
154 return cleaned_data
157 return cleaned_data
155
158
156
159
157 class PostCaptchaForm(PostForm):
160 class PostCaptchaForm(PostForm):
158 captcha = CaptchaField()
161 captcha = CaptchaField()
159
162
160 def __init__(self, *args, **kwargs):
163 def __init__(self, *args, **kwargs):
161 self.request = kwargs['request']
164 self.request = kwargs['request']
162 del kwargs['request']
165 del kwargs['request']
163
166
164 super(PostCaptchaForm, self).__init__(*args, **kwargs)
167 super(PostCaptchaForm, self).__init__(*args, **kwargs)
165
168
166 def clean(self):
169 def clean(self):
167 cleaned_data = super(PostCaptchaForm, self).clean()
170 cleaned_data = super(PostCaptchaForm, self).clean()
168
171
169 success = self.is_valid()
172 success = self.is_valid()
170 utils.update_captcha_access(self.request, success)
173 utils.update_captcha_access(self.request, success)
171
174
172 if success:
175 if success:
173 return cleaned_data
176 return cleaned_data
174 else:
177 else:
175 raise forms.ValidationError(_("Captcha validation failed"))
178 raise forms.ValidationError(_("Captcha validation failed"))
176
179
177
180
178 class ThreadCaptchaForm(ThreadForm):
181 class ThreadCaptchaForm(ThreadForm):
179 captcha = CaptchaField()
182 captcha = CaptchaField()
180
183
181 def __init__(self, *args, **kwargs):
184 def __init__(self, *args, **kwargs):
182 self.request = kwargs['request']
185 self.request = kwargs['request']
183 del kwargs['request']
186 del kwargs['request']
184
187
185 super(ThreadCaptchaForm, self).__init__(*args, **kwargs)
188 super(ThreadCaptchaForm, self).__init__(*args, **kwargs)
186
189
187 def clean(self):
190 def clean(self):
188 cleaned_data = super(ThreadCaptchaForm, self).clean()
191 cleaned_data = super(ThreadCaptchaForm, self).clean()
189
192
190 success = self.is_valid()
193 success = self.is_valid()
191 utils.update_captcha_access(self.request, success)
194 utils.update_captcha_access(self.request, success)
192
195
193 if success:
196 if success:
194 return cleaned_data
197 return cleaned_data
195 else:
198 else:
196 raise forms.ValidationError(_("Captcha validation failed"))
199 raise forms.ValidationError(_("Captcha validation failed"))
197
200
198
201
199 class SettingsForm(NeboardForm):
202 class SettingsForm(NeboardForm):
200
203
201 theme = forms.ChoiceField(choices=settings.THEMES,
204 theme = forms.ChoiceField(choices=settings.THEMES,
202 label=_('Theme'))
205 label=_('Theme'))
203
206
204
207
205 class ModeratorSettingsForm(SettingsForm):
208 class ModeratorSettingsForm(SettingsForm):
206
209
207 moderate = forms.BooleanField(required=False, label=_('Enable moderation '
210 moderate = forms.BooleanField(required=False, label=_('Enable moderation '
208 'panel'))
211 'panel'))
209
212
210
213
211 class LoginForm(NeboardForm):
214 class LoginForm(NeboardForm):
212
215
213 user_id = forms.CharField()
216 user_id = forms.CharField()
214
217
215 session = None
218 session = None
216
219
217 def clean_user_id(self):
220 def clean_user_id(self):
218 user_id = self.cleaned_data['user_id']
221 user_id = self.cleaned_data['user_id']
219 if user_id:
222 if user_id:
220 users = User.objects.filter(user_id=user_id)
223 users = User.objects.filter(user_id=user_id)
221 if len(users) == 0:
224 if len(users) == 0:
222 raise forms.ValidationError(_('No such user found'))
225 raise forms.ValidationError(_('No such user found'))
223
226
224 return user_id
227 return user_id
225
228
226 def _validate_login_speed(self):
229 def _validate_login_speed(self):
227 can_post = True
230 can_post = True
228
231
229 if LAST_LOGIN_TIME in self.session:
232 if LAST_LOGIN_TIME in self.session:
230 now = time.time()
233 now = time.time()
231 last_login_time = self.session[LAST_LOGIN_TIME]
234 last_login_time = self.session[LAST_LOGIN_TIME]
232
235
233 current_delay = int(now - last_login_time)
236 current_delay = int(now - last_login_time)
234
237
235 if current_delay < board_settings.LOGIN_TIMEOUT:
238 if current_delay < board_settings.LOGIN_TIMEOUT:
236 error_message = _('Wait %s minutes after last login') % str(
239 error_message = _('Wait %s minutes after last login') % str(
237 (board_settings.LOGIN_TIMEOUT - current_delay) / 60)
240 (board_settings.LOGIN_TIMEOUT - current_delay) / 60)
238 self._errors['user_id'] = self.error_class([error_message])
241 self._errors['user_id'] = self.error_class([error_message])
239
242
240 can_post = False
243 can_post = False
241
244
242 if can_post:
245 if can_post:
243 self.session[LAST_LOGIN_TIME] = time.time()
246 self.session[LAST_LOGIN_TIME] = time.time()
244
247
245 def clean(self):
248 def clean(self):
246 if not self.session:
249 if not self.session:
247 raise forms.ValidationError('Humans have sessions')
250 raise forms.ValidationError('Humans have sessions')
248
251
249 self._validate_login_speed()
252 self._validate_login_speed()
250
253
251 cleaned_data = super(LoginForm, self).clean()
254 cleaned_data = super(LoginForm, self).clean()
252
255
253 return cleaned_data
256 return cleaned_data
@@ -1,359 +1,357 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
24 .title {
23 .title {
25 font-weight: bold;
24 font-weight: bold;
26 color: #ffcc00;
25 color: #ffcc00;
27 font-size: 2ex;
26 font-size: 2ex;
28 }
27 }
29
28
30 .link, a {
29 .link, a {
31 color: #afdcec;
30 color: #afdcec;
32 }
31 }
33
32
34 .block {
33 .block {
35 display: inline-block;
34 display: inline-block;
36 vertical-align: top;
35 vertical-align: top;
37 }
36 }
38
37
39 .tag {
38 .tag {
40 color: #b4cfec;
39 color: #b4cfec;
41 }
40 }
42
41
43 .post_id {
42 .post_id {
44 color: #fff380;
43 color: #fff380;
45 }
44 }
46
45
47 .post, .dead_post, #posts-table {
46 .post, .dead_post, #posts-table {
48 background: #333;
47 background: #333;
49 margin: 5px;
48 margin: 5px;
50 padding: 10px;
49 padding: 10px;
51 border: solid 1px #888;
50 border: solid 1px #888;
52 clear: left;
51 clear: left;
53 word-wrap: break-word;
52 word-wrap: break-word;
54 }
53 }
55
54
56 .metadata {
55 .metadata {
57 padding-top: 5px;
56 padding-top: 5px;
58 margin-top: 10px;
57 margin-top: 10px;
59 border-top: solid 1px #666;
58 border-top: solid 1px #666;
60 font-size: 0.9em;
59 font-size: 0.9em;
61 color: #ddd;
60 color: #ddd;
62 }
61 }
63
62
64 .navigation_panel, .tag_info {
63 .navigation_panel, .tag_info {
65 background: #444;
64 background: #444;
66 margin: 5px;
65 margin: 5px;
67 padding: 10px;
66 padding: 10px;
68 border: solid 1px #888;
67 border: solid 1px #888;
69 color: #eee;
68 color: #eee;
70 }
69 }
71
70
72 .navigation_panel .link {
71 .navigation_panel .link {
73 border-right: 1px solid #fff;
72 border-right: 1px solid #fff;
74 font-weight: bold;
73 font-weight: bold;
75 margin-right: 1ex;
74 margin-right: 1ex;
76 padding-right: 1ex;
75 padding-right: 1ex;
77 }
76 }
78 .navigation_panel .link:last-child {
77 .navigation_panel .link:last-child {
79 border-left: 1px solid #fff;
78 border-left: 1px solid #fff;
80 border-right: none;
79 border-right: none;
81 float: right;
80 float: right;
82 margin-left: 1ex;
81 margin-left: 1ex;
83 margin-right: 0;
82 margin-right: 0;
84 padding-left: 1ex;
83 padding-left: 1ex;
85 padding-right: 0;
84 padding-right: 0;
86 }
85 }
87
86
88 .navigation_panel::after, .post::after {
87 .navigation_panel::after, .post::after {
89 clear: both;
88 clear: both;
90 content: ".";
89 content: ".";
91 display: block;
90 display: block;
92 height: 0;
91 height: 0;
93 line-height: 0;
92 line-height: 0;
94 visibility: hidden;
93 visibility: hidden;
95 }
94 }
96
95
97 p {
96 p {
98 margin-top: .5em;
97 margin-top: .5em;
99 margin-bottom: .5em;
98 margin-bottom: .5em;
100 }
99 }
101
100
102 .post-form-w {
101 .post-form-w {
103 display: table;
102 display: table;
104 background: #333344;
103 background: #333344;
105 border: solid 1px #888;
104 border: solid 1px #888;
106 color: #fff;
105 color: #fff;
107 padding: 10px;
106 padding: 10px;
108 margin: 5px;
107 margin: 5px;
109 }
108 }
110
109
111 .form-row {
110 .form-row {
112 display: table-row;
111 display: table-row;
113 }
112 }
114
113
115 .form-label, .form-input, .form-errors {
114 .form-label, .form-input, .form-errors {
116 display: table-cell;
115 display: table-cell;
117 }
116 }
118
117
119 .form-label {
118 .form-label {
120 padding: .25em 1ex .25em 0;
119 padding: .25em 1ex .25em 0;
121 vertical-align: top;
120 vertical-align: top;
122 }
121 }
123
122
124 .form-input {
123 .form-input {
125 padding: .25em 0;
124 padding: .25em 0;
126 }
125 }
127
126
128 .form-errors {
127 .form-errors {
129 padding-left: 1ex;
128 font-weight: bolder;
130 font-weight: bold;
131 vertical-align: middle;
129 vertical-align: middle;
132 }
130 }
133
131
134 .post-form input, .post-form textarea {
132 .post-form input, .post-form textarea {
135 background: #333;
133 background: #333;
136 color: #fff;
134 color: #fff;
137 border: solid 1px;
135 border: solid 1px;
138 padding: 0;
136 padding: 0;
139 width: 100%;
137 width: 100%;
140 font: medium sans;
138 font: medium sans;
141 }
139 }
142
140
143 .form-submit {
141 .form-submit {
144 border-bottom: 2px solid #ddd;
142 display: table;
145 margin-bottom: .5em;
143 margin-bottom: 1ex;
146 padding-bottom: .5em;
147 }
144 }
148
145
149 .form-title {
146 .form-title {
150 font-weight: bold;
147 font-weight: bold;
151 font-size: 2.5ex;
148 font-size: 2.5ex;
152 text-decoration: underline;
149 text-decoration: underline;
153 }
150 }
154
151
155 input[type="submit"] {
152 input[type="submit"] {
156 background: #222;
153 background: #222;
157 border: solid 1px #fff;
154 border: solid 2px #fff;
158 color: #fff;
155 color: #fff;
156 padding: 0.5ex;
157 }
158
159 input[type="submit"]:hover {
160 background: #060;
159 }
161 }
160
162
161 blockquote {
163 blockquote {
162 border-left: solid 2px;
164 border-left: solid 2px;
163 padding-left: 5px;
165 padding-left: 5px;
164 color: #B1FB17;
166 color: #B1FB17;
165 margin: 0;
167 margin: 0;
166 }
168 }
167
169
168 .post > .image {
170 .post > .image {
169 float: left;
171 float: left;
170 margin: 0 1ex .5ex 0;
172 margin: 0 1ex .5ex 0;
171 min-width: 1px;
173 min-width: 1px;
172 text-align: center;
174 text-align: center;
173 display: table-row;
175 display: table-row;
174
176
175 height: 150px;
177 height: 150px;
176 }
178 }
177
179
178 .post > .metadata {
180 .post > .metadata {
179 clear: left;
181 clear: left;
180 }
182 }
181
183
182 .get {
184 .get {
183 font-weight: bold;
185 font-weight: bold;
184 color: #d55;
186 color: #d55;
185 }
187 }
186
188
187 * {
189 * {
188 text-decoration: none;
190 text-decoration: none;
189 }
191 }
190
192
191 .dead_post {
193 .dead_post {
192 background-color: #442222;
194 background-color: #442222;
193 }
195 }
194
196
195 .mark_btn {
197 .mark_btn {
196 padding: 2px 4px;
198 padding: 2px 4px;
197 border: 1px solid;
199 border: 1px solid;
198 }
200 }
199
201
200 .mark_btn:hover {
202 .mark_btn:hover {
201 background: #555;
203 background: #555;
202 }
204 }
203
205
204 .quote {
206 .quote {
205 color: #92cf38;
207 color: #92cf38;
206 font-style: italic;
208 font-style: italic;
207 }
209 }
208
210
209 .spoiler {
211 .spoiler {
210 background: white;
212 background: white;
211 color: white;
213 color: white;
212 }
214 }
213
215
214 .spoiler:hover {
216 .spoiler:hover {
215 color: black;
217 color: black;
216 }
218 }
217
219
218 .comment {
220 .comment {
219 color: #eb2;
221 color: #eb2;
220 font-style: italic;
222 font-style: italic;
221 }
223 }
222
224
223 a:hover {
225 a:hover {
224 text-decoration: underline;
226 text-decoration: underline;
225 }
227 }
226
228
227 .last-replies {
229 .last-replies {
228 margin-left: 3ex;
230 margin-left: 3ex;
229 }
231 }
230
232
231 .thread {
233 .thread {
232 margin-bottom: 3ex;
234 margin-bottom: 3ex;
233 }
235 }
234
236
235 .post:target {
237 .post:target {
236 border: solid 2px white;
238 border: solid 2px white;
237 }
239 }
238
240
239 pre{
241 pre{
240 white-space:pre-wrap
242 white-space:pre-wrap
241 }
243 }
242
244
243 li {
245 li {
244 list-style-position: inside;
246 list-style-position: inside;
245 }
247 }
246
248
247 .fancybox-skin {
249 .fancybox-skin {
248 position: relative;
250 position: relative;
249 background-color: #fff;
251 background-color: #fff;
250 color: #ddd;
252 color: #ddd;
251 text-shadow: none;
253 text-shadow: none;
252 }
254 }
253
255
254 .fancybox-image {
256 .fancybox-image {
255 border: 1px solid black;
257 border: 1px solid black;
256 }
258 }
257
259
258 .image-mode-tab {
260 .image-mode-tab {
259 background: #444;
261 background: #444;
260 color: #eee;
262 color: #eee;
261 display: table;
263 display: table;
262 margin: 5px;
264 margin: 5px;
263 padding: 5px;
265 padding: 5px;
264 border: 1px solid #888;
266 border: 1px solid #888;
265 }
267 }
266
268
267 .image-mode-tab > label {
269 .image-mode-tab > label {
268 margin: 0 1ex;
270 margin: 0 1ex;
269 }
271 }
270
272
271 .image-mode-tab > label > input {
273 .image-mode-tab > label > input {
272 margin-right: .5ex;
274 margin-right: .5ex;
273 }
275 }
274
276
275 #posts-table {
277 #posts-table {
276 margin: 5px;
278 margin: 5px;
277 }
279 }
278
280
279 .tag_info {
281 .tag_info {
280 display: table;
282 display: table;
281 }
283 }
282
284
283 .tag_info > h2 {
285 .tag_info > h2 {
284 margin: 0;
286 margin: 0;
285 }
287 }
286
288
287 .post-info {
289 .post-info {
288 color: #ddd;
290 color: #ddd;
289 }
291 }
290
292
291 .moderator_info {
293 .moderator_info {
292 color: #e99d41;
294 color: #e99d41;
293 border: dashed 1px;
295 border: dashed 1px;
294 padding: 3px;
296 padding: 3px;
295 }
297 }
296
298
297 .refmap {
299 .refmap {
298 font-size: 0.9em;
300 font-size: 0.9em;
299 color: #ccc;
301 color: #ccc;
300 margin-top: 1em;
302 margin-top: 1em;
301 }
303 }
302
304
303 input[type="submit"]:hover {
304 background: #555;
305 }
306
307 .fav {
305 .fav {
308 color: yellow;
306 color: yellow;
309 }
307 }
310
308
311 .not_fav {
309 .not_fav {
312 color: #ccc;
310 color: #ccc;
313 }
311 }
314
312
315 .role {
313 .role {
316 text-decoration: underline;
314 text-decoration: underline;
317 }
315 }
318
316
319 .form-email {
317 .form-email {
320 display: none;
318 display: none;
321 }
319 }
322
320
323 .footer {
321 .footer {
324 margin: 5px;
322 margin: 5px;
325 }
323 }
326
324
327 .bar-value {
325 .bar-value {
328 background: rgba(50, 55, 164, 0.45);
326 background: rgba(50, 55, 164, 0.45);
329 font-size: 0.9em;
327 font-size: 0.9em;
330 height: 1.5em;
328 height: 1.5em;
331 }
329 }
332
330
333 .bar-bg {
331 .bar-bg {
334 position: relative;
332 position: relative;
335 border: solid 1px #888;
333 border: solid 1px #888;
336 margin: 5px;
334 margin: 5px;
337 overflow: hidden;
335 overflow: hidden;
338 }
336 }
339
337
340 .bar-text {
338 .bar-text {
341 padding: 2px;
339 padding: 2px;
342 position: absolute;
340 position: absolute;
343 left: 0;
341 left: 0;
344 top: 0;
342 top: 0;
345 }
343 }
346
344
347 .page_link {
345 .page_link {
348 display: table;
346 display: table;
349 background: #444;
347 background: #444;
350 margin: 5px;
348 margin: 5px;
351 border: solid 1px #888;
349 border: solid 1px #888;
352 padding: 5px;
350 padding: 5px;
353 font-weight: bolder;
351 font-weight: bolder;
354 color: #eee;
352 color: #eee;
355 }
353 }
356
354
357 .skipped_replies {
355 .skipped_replies {
358 margin: 5px;
356 margin: 5px;
359 }
357 }
@@ -1,241 +1,242 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load cache %}
4 {% load cache %}
5 {% load board %}
5 {% load board %}
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
13
14 {% if prev_page %}
14 {% if prev_page %}
15 <link rel="next" href="
15 <link rel="next" href="
16 {% if tag %}
16 {% if tag %}
17 {% url "tag" tag_name=tag page=prev_page %}
17 {% url "tag" tag_name=tag page=prev_page %}
18 {% else %}
18 {% else %}
19 {% url "index" page=prev_page %}
19 {% url "index" page=prev_page %}
20 {% endif %}
20 {% endif %}
21 " />
21 " />
22 {% endif %}
22 {% endif %}
23 {% if next_page %}
23 {% if next_page %}
24 <link rel="next" href="
24 <link rel="next" href="
25 {% if tag %}
25 {% if tag %}
26 {% url "tag" tag_name=tag page=next_page %}
26 {% url "tag" tag_name=tag page=next_page %}
27 {% else %}
27 {% else %}
28 {% url "index" page=next_page %}
28 {% url "index" page=next_page %}
29 {% endif %}
29 {% endif %}
30 " />
30 " />
31 {% endif %}
31 {% endif %}
32
32
33 {% endblock %}
33 {% endblock %}
34
34
35 {% block content %}
35 {% block content %}
36
36
37 {% get_current_language as LANGUAGE_CODE %}
37 {% get_current_language as LANGUAGE_CODE %}
38
38
39 {% if tag %}
39 {% if tag %}
40 <div class="tag_info">
40 <div class="tag_info">
41 <h2>
41 <h2>
42 {% if tag in user.fav_tags.all %}
42 {% if tag in user.fav_tags.all %}
43 <a href="{% url 'tag_unsubscribe' tag.name %}?next={{ request.path }}"
43 <a href="{% url 'tag_unsubscribe' tag.name %}?next={{ request.path }}"
44 class="fav">β˜…</a>
44 class="fav">β˜…</a>
45 {% else %}
45 {% else %}
46 <a href="{% url 'tag_subscribe' tag.name %}?next={{ request.path }}"
46 <a href="{% url 'tag_subscribe' tag.name %}?next={{ request.path }}"
47 class="not_fav">β˜…</a>
47 class="not_fav">β˜…</a>
48 {% endif %}
48 {% endif %}
49 #{{ tag.name }}
49 #{{ tag.name }}
50 </h2>
50 </h2>
51 </div>
51 </div>
52 {% endif %}
52 {% endif %}
53
53
54 {% if threads %}
54 {% if threads %}
55 {% if prev_page %}
55 {% if prev_page %}
56 <div class="page_link">
56 <div class="page_link">
57 <a href="
57 <a href="
58 {% if tag %}
58 {% if tag %}
59 {% url "tag" tag_name=tag page=prev_page %}
59 {% url "tag" tag_name=tag page=prev_page %}
60 {% else %}
60 {% else %}
61 {% url "index" page=prev_page %}
61 {% url "index" page=prev_page %}
62 {% endif %}
62 {% endif %}
63 ">{% trans "Previous page" %}</a>
63 ">{% trans "Previous page" %}</a>
64 </div>
64 </div>
65 {% endif %}
65 {% endif %}
66
66
67 {% for thread in threads %}
67 {% for thread in threads %}
68 {% cache 600 thread_short thread.id thread.thread.last_edit_time moderator LANGUAGE_CODE %}
68 {% cache 600 thread_short thread.id thread.thread.last_edit_time moderator LANGUAGE_CODE %}
69 <div class="thread">
69 <div class="thread">
70 {% if thread.bumpable %}
70 {% if thread.bumpable %}
71 <div class="post" id="{{ thread.op.id }}">
71 <div class="post" id="{{ thread.op.id }}">
72 {% else %}
72 {% else %}
73 <div class="post dead_post" id="{{ thread.op.id }}">
73 <div class="post dead_post" id="{{ thread.op.id }}">
74 {% endif %}
74 {% endif %}
75 {% if thread.op.image %}
75 {% if thread.op.image %}
76 <div class="image">
76 <div class="image">
77 <a class="thumb"
77 <a class="thumb"
78 href="{{ thread.op.image.url }}"><img
78 href="{{ thread.op.image.url }}"><img
79 src="{{ thread.op.image.url_200x150 }}"
79 src="{{ thread.op.image.url_200x150 }}"
80 alt="{{ thread.op.id }}"
80 alt="{{ thread.op.id }}"
81 data-width="{{ thread.op.image_width }}"
81 data-width="{{ thread.op.image_width }}"
82 data-height="{{ thread.op.image_height }}"/>
82 data-height="{{ thread.op.image_height }}"/>
83 </a>
83 </a>
84 </div>
84 </div>
85 {% endif %}
85 {% endif %}
86 <div class="message">
86 <div class="message">
87 <div class="post-info">
87 <div class="post-info">
88 <span class="title">{{ thread.op.title }}</span>
88 <span class="title">{{ thread.op.title }}</span>
89 <a class="post_id" href="{% url 'thread' thread.op.id %}"
89 <a class="post_id" href="{% url 'thread' thread.op.id %}"
90 >({{ thread.op.id }})</a>
90 >({{ thread.op.id }})</a>
91 [{{ thread.op.pub_time }}]
91 [{{ thread.op.pub_time }}]
92 [<a class="link" href="
92 [<a class="link" href="
93 {% url 'thread' thread.op.id %}#form"
93 {% url 'thread' thread.op.id %}#form"
94 >{% trans "Reply" %}</a>]
94 >{% trans "Reply" %}</a>]
95
95
96 {% if moderator %}
96 {% if moderator %}
97 <span class="moderator_info">
97 <span class="moderator_info">
98 [<a href="
98 [<a href="
99 {% url 'delete' post_id=thread.op.id %}?next={{ request.path }}"
99 {% url 'delete' post_id=thread.op.id %}?next={{ request.path }}"
100 >{% trans 'Delete' %}</a>]
100 >{% trans 'Delete' %}</a>]
101 ({{ thread.thread.poster_ip }})
101 ({{ thread.thread.poster_ip }})
102 [<a href="
102 [<a href="
103 {% url 'ban' post_id=thread.op.id %}?next={{ request.path }}"
103 {% url 'ban' post_id=thread.op.id %}?next={{ request.path }}"
104 >{% trans 'Ban IP' %}</a>]
104 >{% trans 'Ban IP' %}</a>]
105 </span>
105 </span>
106 {% endif %}
106 {% endif %}
107 </div>
107 </div>
108 {% autoescape off %}
108 {% autoescape off %}
109 {{ thread.op.text.rendered|truncatewords_html:50 }}
109 {{ thread.op.text.rendered|truncatewords_html:50 }}
110 {% endautoescape %}
110 {% endautoescape %}
111 {% if thread.op.is_referenced %}
111 {% if thread.op.is_referenced %}
112 <div class="refmap">
112 <div class="refmap">
113 {% trans "Replies" %}:
113 {% trans "Replies" %}:
114 {% for ref_post in thread.op.get_sorted_referenced_posts %}
114 {% for ref_post in thread.op.get_sorted_referenced_posts %}
115 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
115 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
116 >{% if not forloop.last %},{% endif %}
116 >{% if not forloop.last %},{% endif %}
117 {% endfor %}
117 {% endfor %}
118 </div>
118 </div>
119 {% endif %}
119 {% endif %}
120 </div>
120 </div>
121 <div class="metadata">
121 <div class="metadata">
122 {{ thread.thread.get_images_count }} {% trans 'images' %}.
122 {{ thread.thread.get_images_count }} {% trans 'images' %}.
123 {% if thread.thread.tags %}
123 {% if thread.thread.tags %}
124 <span class="tags">
124 <span class="tags">
125 {% for tag in thread.thread.get_tags %}
125 {% for tag in thread.thread.get_tags %}
126 <a class="tag" href="
126 <a class="tag" href="
127 {% url 'tag' tag_name=tag.name %}">
127 {% url 'tag' tag_name=tag.name %}">
128 #{{ tag.name }}</a
128 #{{ tag.name }}</a
129 >{% if not forloop.last %},{% endif %}
129 >{% if not forloop.last %},{% endif %}
130 {% endfor %}
130 {% endfor %}
131 </span>
131 </span>
132 {% endif %}
132 {% endif %}
133 </div>
133 </div>
134 </div>
134 </div>
135 {% if thread.last_replies.exists %}
135 {% if thread.last_replies.exists %}
136 {% if thread.skipped_replies %}
136 {% if thread.skipped_replies %}
137 <div class="skipped_replies">
137 <div class="skipped_replies">
138 <a href="{% url 'thread' thread.op.id %}">
138 <a href="{% url 'thread' thread.op.id %}">
139 {% blocktrans with count=thread.skipped_replies %}Skipped {{ count }} replies. Open thread to see all replies.{% endblocktrans %}
139 {% blocktrans with count=thread.skipped_replies %}Skipped {{ count }} replies. Open thread to see all replies.{% endblocktrans %}
140 </a>
140 </a>
141 </div>
141 </div>
142 {% endif %}
142 {% endif %}
143 <div class="last-replies">
143 <div class="last-replies">
144 {% for post in thread.last_replies %}
144 {% for post in thread.last_replies %}
145 {% if thread.bumpable %}
145 {% if thread.bumpable %}
146 <div class="post" id="{{ post.id }}">
146 <div class="post" id="{{ post.id }}">
147 {% else %}
147 {% else %}
148 <div class="post dead_post" id="{{ post.id }}">
148 <div class="post dead_post" id="{{ post.id }}">
149 {% endif %}
149 {% endif %}
150 {% if post.image %}
150 {% if post.image %}
151 <div class="image">
151 <div class="image">
152 <a class="thumb"
152 <a class="thumb"
153 href="{{ post.image.url }}"><img
153 href="{{ post.image.url }}"><img
154 src=" {{ post.image.url_200x150 }}"
154 src=" {{ post.image.url_200x150 }}"
155 alt="{{ post.id }}"
155 alt="{{ post.id }}"
156 data-width="{{ post.image_width }}"
156 data-width="{{ post.image_width }}"
157 data-height="{{ post.image_height }}"/>
157 data-height="{{ post.image_height }}"/>
158 </a>
158 </a>
159 </div>
159 </div>
160 {% endif %}
160 {% endif %}
161 <div class="message">
161 <div class="message">
162 <div class="post-info">
162 <div class="post-info">
163 <span class="title">{{ post.title }}</span>
163 <span class="title">{{ post.title }}</span>
164 <a class="post_id" href="
164 <a class="post_id" href="
165 {% url 'thread' thread.op.id %}#{{ post.id }}">
165 {% url 'thread' thread.op.id %}#{{ post.id }}">
166 ({{ post.id }})</a>
166 ({{ post.id }})</a>
167 [{{ post.pub_time }}]
167 [{{ post.pub_time }}]
168 </div>
168 </div>
169 {% autoescape off %}
169 {% autoescape off %}
170 {{ post.text.rendered|truncatewords_html:50 }}
170 {{ post.text.rendered|truncatewords_html:50 }}
171 {% endautoescape %}
171 {% endautoescape %}
172 </div>
172 </div>
173 {% if post.is_referenced %}
173 {% if post.is_referenced %}
174 <div class="refmap">
174 <div class="refmap">
175 {% trans "Replies" %}:
175 {% trans "Replies" %}:
176 {% for ref_post in post.get_sorted_referenced_posts %}
176 {% for ref_post in post.get_sorted_referenced_posts %}
177 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
177 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
178 >{% if not forloop.last %},{% endif %}
178 >{% if not forloop.last %},{% endif %}
179 {% endfor %}
179 {% endfor %}
180 </div>
180 </div>
181 {% endif %}
181 {% endif %}
182 </div>
182 </div>
183 {% endfor %}
183 {% endfor %}
184 </div>
184 </div>
185 {% endif %}
185 {% endif %}
186 </div>
186 </div>
187 {% endcache %}
187 {% endcache %}
188 {% endfor %}
188 {% endfor %}
189
189
190 {% if next_page %}
190 {% if next_page %}
191 <div class="page_link">
191 <div class="page_link">
192 <a href="
192 <a href="
193 {% if tag %}
193 {% if tag %}
194 {% url "tag" tag_name=tag page=next_page %}
194 {% url "tag" tag_name=tag page=next_page %}
195 {% else %}
195 {% else %}
196 {% url "index" page=next_page %}
196 {% url "index" page=next_page %}
197 {% endif %}
197 {% endif %}
198 ">{% trans "Next page" %}</a>
198 ">{% trans "Next page" %}</a>
199 </div>
199 </div>
200 {% endif %}
200 {% endif %}
201 {% else %}
201 {% else %}
202 <div class="post">
202 <div class="post">
203 {% trans 'No threads exist. Create the first one!' %}</div>
203 {% trans 'No threads exist. Create the first one!' %}</div>
204 {% endif %}
204 {% endif %}
205
205
206 <div class="post-form-w">
206 <div class="post-form-w">
207 <div class="post-form">
207 <div class="post-form">
208 <div class="form-title">{% trans "Create new thread" %}</div>
208 <div class="form-title">{% trans "Create new thread" %}</div>
209 <form enctype="multipart/form-data" method="post">{% csrf_token %}
209 <form enctype="multipart/form-data" method="post">{% csrf_token %}
210 {{ form.as_p }}
210 {{ form.as_div }}
211 <div class="form-submit">
211 <div class="form-submit">
212 <input type="submit" value="{% trans "Post" %}"/></div>
212 <input type="submit" value="{% trans "Post" %}"/>
213 <div>
213 </div>
214 </form>
214 </form>
215 <div>
215 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
216 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
216 </div>
217 </div>
217 <div><a href="{% url "staticpage" name="help" %}">
218 <div><a href="{% url "staticpage" name="help" %}">
218 {% trans 'Text syntax' %}</a></div>
219 {% trans 'Text syntax' %}</a></div>
219 </div>
220 </div>
220 </div>
221 </div>
221
222
222 {% endblock %}
223 {% endblock %}
223
224
224 {% block metapanel %}
225 {% block metapanel %}
225
226
226 <span class="metapanel">
227 <span class="metapanel">
227 <b><a href="{% url "authors" %}">Neboard</a> 1.4</b>
228 <b><a href="{% url "authors" %}">Neboard</a> 1.4</b>
228 {% trans "Pages:" %}
229 {% trans "Pages:" %}
229 {% for page in pages %}
230 {% for page in pages %}
230 [<a href="
231 [<a href="
231 {% if tag %}
232 {% if tag %}
232 {% url "tag" tag_name=tag page=page %}
233 {% url "tag" tag_name=tag page=page %}
233 {% else %}
234 {% else %}
234 {% url "index" page=page %}
235 {% url "index" page=page %}
235 {% endif %}
236 {% endif %}
236 ">{{ page }}</a>]
237 ">{{ page }}</a>]
237 {% endfor %}
238 {% endfor %}
238 [<a href="rss/">RSS</a>]
239 [<a href="rss/">RSS</a>]
239 </span>
240 </span>
240
241
241 {% endblock %}
242 {% endblock %}
@@ -1,36 +1,37 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load humanize %}
4 {% load humanize %}
5
5
6 {% block head %}
6 {% block head %}
7 <title>Neboard settings</title>
7 <title>Neboard settings</title>
8 {% endblock %}
8 {% endblock %}
9
9
10 {% block content %}
10 {% block content %}
11
11
12 <div class="post">
12 <div class="post">
13 <p>
13 <p>
14 {% trans 'User:' %} <b>{{ user.user_id }}</b>.
14 {% trans 'User:' %} <b>{{ user.user_id }}</b>.
15 {% if user.is_moderator %}
15 {% if user.is_moderator %}
16 {% trans 'You are moderator.' %}
16 {% trans 'You are moderator.' %}
17 {% endif %}
17 {% endif %}
18 </p>
18 </p>
19 <p>{% trans 'Posts:' %} {{ user.get_post_count }}</p>
19 <p>{% trans 'Posts:' %} {{ user.get_post_count }}</p>
20 <p>{% trans 'First access:' %} {{ user.registration_time|naturaltime }}</p>
20 <p>{% trans 'First access:' %} {{ user.registration_time|naturaltime }}</p>
21 {% if user.get_last_access_time %}
21 {% if user.get_last_access_time %}
22 <p>{% trans 'Last access:' %} {{ user.get_last_access_time|naturaltime }}</p>
22 <p>{% trans 'Last access:' %} {{ user.get_last_access_time|naturaltime }}</p>
23 {% endif %}
23 {% endif %}
24 </div>
24 </div>
25
25
26 <div class="post-form-w">
26 <div class="post-form-w">
27 <div class="post-form">
27 <div class="post-form">
28 <form method="post">{% csrf_token %}
28 <form method="post">{% csrf_token %}
29 {{ form.as_p }}
29 {{ form.as_div }}
30 <hr />
30 <div class="form-submit">
31 <input type="submit" value="{% trans "Save" %}" />
31 <input type="submit" value="{% trans "Save" %}" />
32 </div>
32 </form>
33 </form>
33 </div>
34 </div>
34 </div>
35 </div>
35
36
36 {% endblock %}
37 {% endblock %}
@@ -1,127 +1,127 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load cache %}
4 {% load cache %}
5 {% load static from staticfiles %}
5 {% load static from staticfiles %}
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_replies.0.get_title }}</title>
10 {% endblock %}
10 {% endblock %}
11
11
12 {% block content %}
12 {% block content %}
13 {% spaceless %}
13 {% spaceless %}
14 {% get_current_language as LANGUAGE_CODE %}
14 {% get_current_language as LANGUAGE_CODE %}
15
15
16 <script src="{% static 'js/thread_update.js' %}"></script>
16 <script src="{% static 'js/thread_update.js' %}"></script>
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 {% if bumpable %}
20 {% if bumpable %}
21 <div class="bar-bg">
21 <div class="bar-bg">
22 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
22 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
23 </div>
23 </div>
24 <div class="bar-text">
24 <div class="bar-text">
25 <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %}
25 <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %}
26 </div>
26 </div>
27 </div>
27 </div>
28 {% endif %}
28 {% endif %}
29 <div class="thread">
29 <div class="thread">
30 {% for post in thread.get_replies %}
30 {% for post in thread.get_replies %}
31 {% if bumpable %}
31 {% if bumpable %}
32 <div class="post" id="{{ post.id }}">
32 <div class="post" id="{{ post.id }}">
33 {% else %}
33 {% else %}
34 <div class="post dead_post" id="{{ post.id }}">
34 <div class="post dead_post" id="{{ post.id }}">
35 {% endif %}
35 {% endif %}
36 {% if post.image %}
36 {% if post.image %}
37 <div class="image">
37 <div class="image">
38 <a
38 <a
39 class="thumb"
39 class="thumb"
40 href="{{ post.image.url }}"><img
40 href="{{ post.image.url }}"><img
41 src="{{ post.image.url_200x150 }}"
41 src="{{ post.image.url_200x150 }}"
42 alt="{{ post.id }}"
42 alt="{{ post.id }}"
43 data-width="{{ post.image_width }}"
43 data-width="{{ post.image_width }}"
44 data-height="{{ post.image_height }}"/>
44 data-height="{{ post.image_height }}"/>
45 </a>
45 </a>
46 </div>
46 </div>
47 {% endif %}
47 {% endif %}
48 <div class="message">
48 <div class="message">
49 <div class="post-info">
49 <div class="post-info">
50 <span class="title">{{ post.title }}</span>
50 <span class="title">{{ post.title }}</span>
51 <a class="post_id" href="#{{ post.id }}">
51 <a class="post_id" href="#{{ post.id }}">
52 ({{ post.id }})</a>
52 ({{ post.id }})</a>
53 [{{ post.pub_time }}]
53 [{{ post.pub_time }}]
54 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
54 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
55 ; return false;">&gt;&gt;</a>]
55 ; return false;">&gt;&gt;</a>]
56
56
57 {% if moderator %}
57 {% if moderator %}
58 <span class="moderator_info">
58 <span class="moderator_info">
59 [<a href="{% url 'delete' post_id=post.id %}"
59 [<a href="{% url 'delete' post_id=post.id %}"
60 >{% trans 'Delete' %}</a>]
60 >{% trans 'Delete' %}</a>]
61 ({{ post.poster_ip }})
61 ({{ post.poster_ip }})
62 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
62 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
63 >{% trans 'Ban IP' %}</a>]
63 >{% trans 'Ban IP' %}</a>]
64 </span>
64 </span>
65 {% endif %}
65 {% endif %}
66 </div>
66 </div>
67 {% autoescape off %}
67 {% autoescape off %}
68 {{ post.text.rendered }}
68 {{ post.text.rendered }}
69 {% endautoescape %}
69 {% endautoescape %}
70 {% if post.is_referenced %}
70 {% if post.is_referenced %}
71 <div class="refmap">
71 <div class="refmap">
72 {% trans "Replies" %}:
72 {% trans "Replies" %}:
73 {% for ref_post in post.get_sorted_referenced_posts %}
73 {% for ref_post in post.get_sorted_referenced_posts %}
74 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
74 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
75 >{% if not forloop.last %},{% endif %}
75 >{% if not forloop.last %},{% endif %}
76 {% endfor %}
76 {% endfor %}
77 </div>
77 </div>
78 {% endif %}
78 {% endif %}
79 </div>
79 </div>
80 {% if forloop.first %}
80 {% if forloop.first %}
81 <div class="metadata">
81 <div class="metadata">
82 <span class="tags">
82 <span class="tags">
83 {% for tag in thread.get_tags %}
83 {% for tag in thread.get_tags %}
84 <a class="tag" href="{% url 'tag' tag.name %}">
84 <a class="tag" href="{% url 'tag' tag.name %}">
85 #{{ tag.name }}</a
85 #{{ tag.name }}</a
86 >{% if not forloop.last %},{% endif %}
86 >{% if not forloop.last %},{% endif %}
87 {% endfor %}
87 {% endfor %}
88 </span>
88 </span>
89 </div>
89 </div>
90 {% endif %}
90 {% endif %}
91 </div>
91 </div>
92 {% endfor %}
92 {% endfor %}
93 </div>
93 </div>
94 {% endcache %}
94 {% endcache %}
95
95
96 <div class="post-form-w">
96 <div class="post-form-w">
97 <div class="form-title">{% trans "Reply to thread" %} #{{ thread.get_opening_post.id }}</div>
97 <div class="form-title">{% trans "Reply to thread" %} #{{ thread.get_opening_post.id }}</div>
98 <div class="post-form">
98 <div class="post-form">
99 <form id="form" enctype="multipart/form-data" method="post"
99 <form id="form" enctype="multipart/form-data" method="post"
100 >{% csrf_token %}
100 >{% csrf_token %}
101 {{ form.as_p }}
101 {{ form.as_div }}
102 <div class="form-submit">
102 <div class="form-submit">
103 <input type="submit" value="{% trans "Post" %}"/>
103 <input type="submit" value="{% trans "Post" %}"/>
104 </div>
104 </div>
105 </form>
105 </form>
106 <div><a href="{% url "staticpage" name="help" %}">
106 <div><a href="{% url "staticpage" name="help" %}">
107 {% trans 'Text syntax' %}</a></div>
107 {% trans 'Text syntax' %}</a></div>
108 </div>
108 </div>
109 </div>
109 </div>
110
110
111 {% endspaceless %}
111 {% endspaceless %}
112 {% endblock %}
112 {% endblock %}
113
113
114 {% block metapanel %}
114 {% block metapanel %}
115
115
116 {% get_current_language as LANGUAGE_CODE %}
116 {% get_current_language as LANGUAGE_CODE %}
117
117
118 <span class="metapanel" data-last-update="{{ last_update }}">
118 <span class="metapanel" data-last-update="{{ last_update }}">
119 {% cache 600 thread_meta thread.last_edit_time moderator LANGUAGE_CODE %}
119 {% cache 600 thread_meta thread.last_edit_time moderator LANGUAGE_CODE %}
120 <span id="reply-count">{{ thread.get_reply_count }}</span> {% trans 'replies' %},
120 <span id="reply-count">{{ thread.get_reply_count }}</span> {% trans 'replies' %},
121 <span id="image-count">{{ thread.get_images_count }}</span> {% trans 'images' %}.
121 <span id="image-count">{{ thread.get_images_count }}</span> {% trans 'images' %}.
122 {% trans 'Last update: ' %}{{ thread.last_edit_time }}
122 {% trans 'Last update: ' %}{{ thread.last_edit_time }}
123 [<a href="rss/">RSS</a>]
123 [<a href="rss/">RSS</a>]
124 {% endcache %}
124 {% endcache %}
125 </span>
125 </span>
126
126
127 {% endblock %}
127 {% endblock %}
General Comments 0
You need to be logged in to leave comments. Login now