##// END OF EJS Templates
Merged with the old validation changes.
neko259 -
r75:bb74538a merge default
parent child Browse files
Show More
@@ -1,63 +1,62 b''
1 1 import re
2 2 from django import forms
3 3 from neboard import settings
4 4
5 5
6 6 class PostForm(forms.Form):
7 7 MAX_TEXT_LENGTH = 10000
8 8 MAX_IMAGE_SIZE = 8 * 1024 * 1024
9 9
10 10 title = forms.CharField(max_length=50, required=False)
11 11 text = forms.CharField(widget=forms.Textarea, required=False)
12 12 image = forms.ImageField(required=False)
13 13
14 14 def clean_text(self):
15 15 text = self.cleaned_data['text']
16 16 if text:
17 17 if len(text) > self.MAX_TEXT_LENGTH:
18 18 raise forms.ValidationError('Too many text')
19 19 return text
20 20
21 21 def clean_image(self):
22 22 image = self.cleaned_data['image']
23 23 if image:
24 24 if image._size > self.MAX_IMAGE_SIZE:
25 25 raise forms.ValidationError('Too large image: more than ' +
26 26 str(self.MAX_IMAGE_SIZE) + ' bytes')
27 27 return image
28 28
29 29 def clean(self):
30 30 cleaned_data = super(PostForm, self).clean()
31 31
32 32 text = cleaned_data.get('text')
33 33 image = cleaned_data.get('image')
34 34
35 35 if (not text) and (not image):
36 36 raise forms.ValidationError('Enter either text or image')
37 37
38 38 return cleaned_data
39 39
40 40
41 41 class ThreadForm(PostForm):
42 42 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
43
44 43 tags = forms.CharField(max_length=100)
45 44
46 45 def clean_tags(self):
47 46 tags = self.cleaned_data['tags']
48 47
49 48 if tags:
50 49 if not self.regex_tags.match(tags):
51 50 raise forms.ValidationError(
52 51 'Inappropriate characters in tags')
53 52
54 53 return tags
55 54
56 55 def clean(self):
57 56 cleaned_data = super(ThreadForm, self).clean()
58 57
59 58 return cleaned_data
60 59
61 60
62 61 class SettingsForm(forms.Form):
63 62 theme = forms.ChoiceField(choices=settings.THEMES, widget=forms.RadioSelect) No newline at end of file
@@ -1,240 +1,253 b''
1 1 html {
2 2 background: #555;
3 3 color: #ffffff;
4 4 }
5 5
6 6 #admin_panel {
7 7 background: #FF0000;
8 8 color: #00FF00
9 9 }
10 10
11 .input_field {
12
13 }
14
15 .input_field_name {
16
17 }
18
19 .input_field_error {
20 color: #FF0000;
21 }
22
23
11 24 .title {
12 25 font-weight: bold;
13 26 color: #ffcc00;
14 27 }
15 28
16 29 .link, a {
17 30 color: #afdcec;
18 31 }
19 32
20 33 .block {
21 34 display: inline-block;
22 35 vertical-align: top;
23 36 }
24 37
25 38 .tag {
26 39 color: #b4cfec;
27 40 }
28 41
29 42 .post_id {
30 43 color: #fff380;
31 44 }
32 45
33 46 .post, .dead_post {
34 47 background: #333;
35 48 margin: 5px;
36 49 padding: 10px;
37 50 border-radius: 5px;
38 51 clear: left;
39 52 word-wrap: break-word;
40 53 }
41 54
42 55 .metadata {
43 56 padding: 5px;
44 57 margin-top: 10px;
45 58 border: solid 1px #666;
46 59 font-size: 0.9em;
47 60 color: #ddd;
48 61 display: table;
49 62 }
50 63
51 64 .navigation_panel {
52 65 background: #444;
53 66 margin: 5px;
54 67 padding: 10px;
55 68 border-radius: 5px;
56 69 color: #eee;
57 70 }
58 71
59 72 .navigation_panel .link {
60 73 border-right: 1px solid #fff;
61 74 font-weight: bold;
62 75 margin-right: 1ex;
63 76 padding-right: 1ex;
64 77 }
65 78 .navigation_panel .link:last-child {
66 79 border-left: 1px solid #fff;
67 80 border-right: none;
68 81 float: right;
69 82 margin-left: 1ex;
70 83 margin-right: 0;
71 84 padding-left: 1ex;
72 85 padding-right: 0;
73 86 }
74 87
75 88 .navigation_panel::after, .post::after {
76 89 clear: both;
77 90 content: ".";
78 91 display: block;
79 92 height: 0;
80 93 line-height: 0;
81 94 visibility: hidden;
82 95 }
83 96
84 97 p {
85 98 margin-top: .5em;
86 99 margin-bottom: .5em;
87 100 }
88 101
89 102 .post-form-w {
90 103 display: table;
91 104 background: #333344;
92 105 border-radius: 5px;
93 106 color: #fff;
94 107 padding: 10px;
95 108 margin: 5px
96 109 }
97 110
98 111 .form-row {
99 112 display: table-row;
100 113 }
101 114
102 115 .form-label, .form-input {
103 116 display: table-cell;
104 117 }
105 118
106 119 .form-label {
107 120 padding: .25em 1ex .25em 0;
108 121 vertical-align: top;
109 122 }
110 123
111 124 .form-input {
112 125 padding: .25em 0;
113 126 }
114 127
115 128 .post-form input, .post-form textarea {
116 129 background: #333;
117 130 color: #fff;
118 131 border: solid 1px;
119 132 padding: 0;
120 133 width: 100%;
121 134 }
122 135
123 136 .form-submit {
124 137 border-bottom: 2px solid #ddd;
125 138 margin-bottom: .5em;
126 139 padding-bottom: .5em;
127 140 }
128 141
129 142 .form-title {
130 143 font-weight: bold;
131 144 }
132 145
133 146 input[type="submit"] {
134 147 background: #222;
135 148 border: solid 1px #fff;
136 149 color: #fff;
137 150 }
138 151
139 152 blockquote {
140 153 border-left: solid 2px;
141 154 padding-left: 5px;
142 155 color: #B1FB17;
143 156 margin: 0;
144 157 }
145 158
146 159 .post > .image {
147 160 float: left; margin: 0 1ex .5ex 0;
148 161 }
149 162
150 163 .post > .metadata {
151 164 clear: left;
152 165 }
153 166
154 167 .get {
155 168 font-weight: bold;
156 169 color: #d55;
157 170 }
158 171
159 172 * {
160 173 text-decoration: none;
161 174 }
162 175
163 176 .dead_post {
164 177 background-color: #442222;
165 178 }
166 179
167 180 .quote {
168 181 color: greenyellow;
169 182 padding-left: 5px;
170 183 border-left: solid 2px greenyellow;
171 184 }
172 185
173 186 .spoiler {
174 187 background: white;
175 188 color: white;
176 189 }
177 190
178 191 .spoiler:hover {
179 192 background: black;
180 193 }
181 194
182 195 .comment {
183 196 color: darkseagreen;
184 197 }
185 198
186 199 a:hover {
187 200 text-decoration: underline;
188 201 }
189 202
190 203 .last-replies {
191 204 margin-left: 3ex;
192 205 }
193 206
194 207 .thread {
195 208 margin-bottom: 3ex;
196 209 }
197 210
198 211 .post:target {
199 212 border: solid 2px white;
200 213 }
201 214
202 215 pre{
203 216 white-space:pre-wrap
204 217 }
205 218
206 219 li {
207 220 list-style-position: inside;
208 221 }
209 222
210 223 .fancybox-skin {
211 224 position: relative;
212 225 background-color: #fff;
213 226 color: #ddd;
214 227 text-shadow: none;
215 228 }
216 229
217 230 .fancybox-image {
218 231 border: 1px solid black;
219 232 }
220 233
221 234 .image-mode-tab {
222 235 background: #444;
223 236 color: #eee;
224 237 display: table;
225 238 margin: 5px;
226 239 padding: 5px;
227 240 border-radius: 5px;
228 241 }
229 242
230 243 .image-mode-tab > label {
231 244 margin: 0 1ex;
232 245 }
233 246
234 247 .image-mode-tab > label > input {
235 248 margin-right: .5ex;
236 249 }
237 250
238 251 #posts-table {
239 252 margin: 5px;
240 253 } No newline at end of file
@@ -1,244 +1,257 b''
1 1 * {
2 2 font-size: inherit;
3 3 margin: 0;
4 4 padding: 0;
5 5 }
6 6 html {
7 7 background: #fff;
8 8 color: #000;
9 9 font: medium sans-serif;
10 10 }
11 11 a {
12 12 color: inherit;
13 13 text-decoration: underline;
14 14 }
15 15 li {
16 16 list-style-position: inside;
17 17 }
18 18
19 19 #admin_panel {
20 20 background: #182F6F;
21 21 color: #fff;
22 22 padding: .5ex 1ex .5ex 1ex;
23 23 }
24 24
25 25 .navigation_panel {
26 26 background: #182F6F;
27 27 color: #B4CFEC;
28 28 margin-bottom: 1em;
29 29 padding: .5ex 1ex 1ex 1ex;
30 30 }
31 31 .navigation_panel::after {
32 32 clear: both;
33 33 content: ".";
34 34 display: block;
35 35 height: 0;
36 36 line-height: 0;
37 37 visibility: hidden;
38 38 }
39 39
40 40 .navigation_panel a:link, .navigation_panel a:visited, .navigation_panel a:hover {
41 41 text-decoration: none;
42 42 }
43 43
44 44 .navigation_panel .link {
45 45 border-right: 1px solid #fff;
46 46 color: #fff;
47 47 font-weight: bold;
48 48 margin-right: 1ex;
49 49 padding-right: 1ex;
50 50 }
51 51 .navigation_panel .link:last-child {
52 52 border-left: 1px solid #fff;
53 53 border-right: none;
54 54 float: right;
55 55 margin-left: 1ex;
56 56 margin-right: 0;
57 57 padding-left: 1ex;
58 58 padding-right: 0;
59 59 }
60 60
61 61 .navigation_panel .tag {
62 62 color: #fff;
63 63 }
64 64
65 .input_field {
66
67 }
68
69 .input_field_name {
70
71 }
72
73 .input_field_error {
74 color: #FF0000;
75 }
76
77
65 78 .title {
66 79 color: #182F6F;
67 80 font-weight: bold;
68 81 }
69 82
70 83 .post-form-w {
71 84 background: #182F6F;
72 85 border-radius: 1ex;
73 86 color: #fff;
74 87 margin: 1em 1ex;
75 88 padding: 1ex;
76 89 }
77 90 .post-form {
78 91 display: table;
79 92 border-collapse: collapse;
80 93 width: 100%;
81 94
82 95 }
83 96 .form-row {
84 97 display: table-row;
85 98 }
86 99 .form-label, .form-input {
87 100 display: table-cell;
88 101 vertical-align: top;
89 102 }
90 103 .form-label {
91 104 padding: .25em 1ex .25em 0;
92 105 }
93 106 .form-input {
94 107 padding: .25em 0;
95 108 }
96 109 .form-input > * {
97 110 background: #fff;
98 111 color: #000;
99 112 border: none;
100 113 padding: 0;
101 114 resize: vertical;
102 115 width: 100%;
103 116 }
104 117 .form-submit {
105 118 border-bottom: 1px solid #666;
106 119 margin-bottom: .5em;
107 120 padding-bottom: .5em;
108 121 }
109 122 .form-title {
110 123 font-weight: bold;
111 124 margin-bottom: .5em;
112 125 }
113 126 .post-form .settings_item {
114 127 margin: .5em 0;
115 128 }
116 129 .form-submit input {
117 130 margin-top: .5em;
118 131 padding: .2em 1ex;
119 132 }
120 133 .form-label {
121 134 text-align: right;
122 135 }
123 136
124 137 .block {
125 138 display: inline-block;
126 139 vertical-align: top;
127 140 }
128 141
129 142 .post_id {
130 143 color: #a00;
131 144 }
132 145
133 146 .post {
134 147 clear: left;
135 148 margin: 0 1ex 1em 1ex;
136 149 overflow-x: auto;
137 150 word-wrap: break-word;
138 151 }
139 152 .last-replies > .post, #posts > .post {
140 153 border-bottom: 1px solid #182F6F;
141 154 padding-bottom: 1em;
142 155 }
143 156 #posts > .post:last-child {
144 157 border-bottom: none;
145 158 padding-bottom: 0;
146 159 }
147 160
148 161 .metadata {
149 162 background: #C0E4E8;
150 163 border: 1px solid #7F9699;
151 164 border-radius: .4ex;
152 165 display: table;
153 166 margin-top: .5em;
154 167 padding: .4em;
155 168 }
156 169
157 170 .post ul, .post ol {
158 171 margin: .5em 0 .5em 3ex;
159 172 }
160 173 .post li {
161 174 margin: .2em 0;
162 175 }
163 176 .post p {
164 177 margin: .5em 0;
165 178 }
166 179 .post blockquote {
167 180 border-left: 3px solid #182F6F;
168 181 margin: .5em 0 .5em 3ex;
169 182 padding-left: 1ex;
170 183 }
171 184 .post blockquote > blockquote {
172 185 padding-top: .1em;
173 186 }
174 187
175 188 .post > .image {
176 189 float: left;
177 190 margin-right: 1ex;
178 191 }
179 192 .post > .metadata {
180 193 clear: left;
181 194 }
182 195
183 196 .post > .message .get {
184 197 color: #182F6F; font-weight: bold;
185 198 }
186 199
187 200 .dead_post > .metadata {
188 201 background: #eee;
189 202 }
190 203
191 204 .quote {
192 205 color: #182F6F;
193 206 padding-left: 5px;
194 207 border-left: solid 2px blue;
195 208 }
196 209
197 210 .spoiler {
198 211 background: black;
199 212 color: black;
200 213 }
201 214
202 215 .spoiler:hover {
203 216 background: #ffffff;
204 217 }
205 218
206 219 .comment {
207 220 color: #557055;
208 221 }
209 222
210 223 .last-replies {
211 224 margin-left: 6ex;
212 225 }
213 226
214 227 .thread > .post > .message > .post-info {
215 228 border-bottom: 2px solid #182F6F;
216 229 padding-bottom: .5em;
217 230 }
218 231
219 232 .last-replies > .post:last-child {
220 233 border-bottom: none;
221 234 padding-bottom: 0;
222 235 }
223 236
224 237 :target .post_id {
225 238 background: #182F6F;
226 239 color: #FFF;
227 240 text-decoration: none;
228 241 }
229 242
230 243 .image-mode-tab {
231 244 background: #182F6F;
232 245 color: #FFF;
233 246 display: table;
234 247 margin: 1em auto 1em 0;
235 248 padding: .2em .5ex;
236 249 }
237 250
238 251 .image-mode-tab > label {
239 252 margin: 0 1ex;
240 253 }
241 254
242 255 .image-mode-tab > label > input {
243 256 margin-right: .5ex;
244 257 } No newline at end of file
@@ -1,154 +1,158 b''
1 1 {% extends "base.html" %}
2 2
3 3 {% load i18n %}
4 4 {% load markup %}
5 5
6 6 {% block head %}
7 7 {% if tag %}
8 8 <title>Neboard - {{ tag }}</title>
9 9 {% else %}
10 10 <title>Neboard</title>
11 11 {% endif %}
12 12 {% endblock %}
13 13
14 14 {% block content %}
15 15
16 16 {% if tag %}
17 17 <div class="tag_info">
18 18 <h2>{{ tag }}</h2>
19 19 </div>
20 20 {% endif %}
21 21
22 22 {% if threads %}
23 23 {% for thread in threads %}
24 24 <div class="thread">
25 25 {% if thread.can_bump %}
26 26 <div class="post">
27 27 {% else %}
28 28 <div class="post dead_post">
29 29 {% endif %}
30 30 {% if thread.image %}
31 31 <div class="image">
32 32 <a class="fancy"
33 33 href="{{ thread.image.url }}"><img
34 34 src="{{ thread.image.url_200x150 }}" />
35 35 </a>
36 36 </div>
37 37 {% endif %}
38 38 <div class="message">
39 39 <div class="post-info">
40 40 <span class="title">{{ thread.title }}</span>
41 41 <a class="post_id" href="{% url 'thread' thread.id %}">
42 42 (#{{ thread.id }})</a>
43 43 [{{ thread.pub_time }}]
44 44 [<a class="link" href="{% url 'thread' thread.id %}#form"
45 45 >{% trans "Reply" %}</a>]
46 46 </div>
47 47 {% autoescape off %}
48 48 {{ thread.text.rendered|truncatewords_html:50 }}
49 49 {% endautoescape %}
50 50 </div>
51 51 <div class="metadata">
52 52 {{ thread.get_reply_count }} {% trans 'replies' %},
53 53 {{ thread.get_images_count }} {% trans 'images' %}.
54 54 {% if thread.tags.all %}
55 55 <span class="tags">{% trans 'Tags' %}:
56 56 {% for tag in thread.tags.all %}
57 57 <a class="tag" href="
58 58 {% url 'tag' tag_name=tag.name %}">
59 59 {{ tag.name }}</a>
60 60 {% endfor %}
61 61 </span>
62 62 {% endif %}
63 63 </div>
64 64 </div>
65 65 {% if thread.get_last_replies %}
66 66 <div class="last-replies">
67 67 {% for post in thread.get_last_replies %}
68 68 {% if thread.can_bump %}
69 69 <div class="post">
70 70 {% else %}
71 71 <div class="post dead_post">
72 72 {% endif %}
73 73 {% if post.image %}
74 74 <div class="image">
75 75 <a class="fancy"
76 76 href="{{ post.image.url }}"><img
77 77 src="{{ post.image.url_200x150 }}" />
78 78 </a>
79 79 </div>
80 80 {% endif %}
81 81 <div class="message">
82 82 <div class="post-info">
83 83 <span class="title">{{ post.title }}</span>
84 84 <a class="post_id" href="
85 85 {% url 'thread' thread.id %}#{{ post.id }}">
86 86 (#{{ post.id }})</a>
87 87 [{{ post.pub_time }}]
88 88 </div>
89 89 {% autoescape off %}
90 90 {{ post.text.rendered|truncatewords_html:50 }}
91 91 {% endautoescape %}
92 92 </div>
93 93 </div>
94 94 {% endfor %}
95 95 </div>
96 96 {% endif %}
97 97 </div>
98 98 {% endfor %}
99 99 {% else %}
100 100 No threads found.
101 101 <hr />
102 102 {% endif %}
103 103
104 104 <form enctype="multipart/form-data" method="post">{% csrf_token %}
105 105 <div class="post-form-w">
106 106 <div class="form-title">{% trans "Create new thread" %}</div>
107 107 <div class="post-form">
108 108 <div class="form-row">
109 109 <div class="form-label">{% trans 'Title' %}</div>
110 110 <div class="form-input">{{ form.title }}</div>
111 <div class="form-errors">{{ form.title.errors }}</div>
111 112 </div>
112 113 <div class="form-row">
113 114 <div class="form-label">{% trans 'Text' %}</div>
114 115 <div class="form-input">{{ form.text }}</div>
116 <div class="form-errors">{{ form.text.errors }}</div>
115 117 </div>
116 118 <div class="form-row">
117 119 <div class="form-label">{% trans 'Image' %}</div>
118 120 <div class="form-input">{{ form.image }}</div>
121 <div class="form-errors">{{ form.image.errors }}</div>
119 122 </div>
120 123 <div class="form-row">
121 124 <div class="form-label">{% trans 'Tags' %}</div>
122 125 <div class="form-input">{{ form.tags }}</div>
126 <div class="form-errors">{{ form.tags.errors }}</div>
123 127 </div>
124 128 </div>
125 129 <div class="form-submit"><input type="submit"
126 130 value="{% trans "Post" %}"/></div>
127 131 <div>Tags must be delimited by spaces. Text or image is required
128 132 </div>
129 133 <div>Use <a
130 134 href="http://daringfireball.net/projects/markdown/basics">
131 135 markdown</a> syntax for posting.</div>
132 136 </div>
133 137 </form>
134 138
135 139 {% endblock %}
136 140
137 141 {% block metapanel %}
138 142
139 143 <span class="metapanel">
140 144 <b><a href="https://bitbucket.org/neko259/neboard/">Neboard</a>
141 145 2013-05 (dev)</b>
142 146 {% trans "Pages:" %}
143 147 {% for page in pages %}
144 148 [<a href="
145 149 {% if tag %}
146 150 {% url "tag" tag_name=tag page=page %}
147 151 {% else %}
148 152 {% url "index" page=page %}
149 153 {% endif %}
150 154 ">{{ page }}</a>]
151 155 {% endfor %}
152 156 </span>
153 157
154 158 {% endblock %}
@@ -1,102 +1,106 b''
1 1 {% extends "base.html" %}
2 2
3 3 {% load i18n %}
4 4 {% load markup %}
5 5
6 6 {% block head %}
7 7 <title>Neboard - {{ posts.0.title }}</title>
8 8 {% endblock %}
9 9
10 10 {% block content %}
11 11 <script src="{{ STATIC_URL }}js/thread.js"></script>
12 12
13 13 {% if posts %}
14 14 <div id="posts">
15 15 {% for post in posts %}
16 16 {% if posts.0.can_bump %}
17 17 <div class="post" id="{{ post.id }}">
18 18 {% else %}
19 19 <div class="post dead_post" id="{{ post.id }}">
20 20 {% endif %}
21 21 {% if post.image %}
22 22 <div class="image">
23 23 <a
24 24 class="fancy"
25 25 href="{{ post.image.url }}"><img
26 26 src="{{ post.image.url_200x150 }}" />
27 27 </a>
28 28 </div>
29 29 {% endif %}
30 30 <div class="message">
31 31 <div class="post-info">
32 32 <span class="title">{{ post.title }}</span>
33 33 <a class="post_id" href="#{{ post.id }}">
34 34 (#{{ post.id }})</a>
35 35 [{{ post.pub_time }}]
36 36 {% if post.is_get %}
37 37 <span class="get">
38 38 {% trans "Get!" %}
39 39 </span>
40 40 {% endif %}
41 41 </div>
42 42 {% autoescape off %}
43 43 {{ post.text.rendered }}
44 44 {% endautoescape %}
45 45 </div>
46 46 {% if post.tags.all %}
47 47 <div class="metadata">
48 48 <span class="tags">{% trans 'Tags' %}:
49 49 {% for tag in post.tags.all %}
50 50 <a class="tag" href="{% url 'tag' tag.name %}">
51 51 {{ tag.name }}</a>
52 52 {% endfor %}
53 53 </span>
54 54 </div>
55 55 {% endif %}
56 56 </div>
57 57 {% endfor %}
58 58 </div>
59 59 {% else %}
60 60 No thread found.
61 61 <hr />
62 62 {% endif %}
63 63
64 <<<<<<< local
64 65 <form id="form" enctype="multipart/form-data" method="post"
65 66 >{% csrf_token %}
66 67 <div class="post-form-w">
67 68 <div class="form-title">{% trans "Reply to thread" %}</div>
68 69 <div class="post-form">
69 70 <div class="form-row">
70 71 <div class="form-label">{% trans 'Title' %}</div>
71 72 <div class="form-input">{{ form.title }}</div>
73 <div class="form-errors">{{ form.title.errors }}</div>
72 74 </div>
73 75 <div class="form-row">
74 76 <div class="form-label">{% trans 'Text' %}</div>
75 77 <div class="form-input">{{ form.text }}</div>
78 <div class="form-errors">{{ form.text.errors }}</div>
76 79 </div>
77 80 <div class="form-row">
78 81 <div class="form-label">{% trans 'Image' %}</div>
79 82 <div class="form-input">{{ form.image }}</div>
83 <div class="form-errors">{{ form.image.errors }}</div>
80 84 </div>
81 85 </div>
82 86 <div class="form-submit"><input type="submit"
83 87 value="{% trans "Post" %}"/></div>
84 88 <div>Use <a
85 89 href="http://daringfireball.net/projects/markdown/basics">
86 90 markdown</a> syntax for posting.</div>
87 91 <div>Example: *<i>italic</i>*, **<b>bold</b>**</div>
88 92 <div>Insert quotes with "&gt;"</div>
89 93 </div>
90 94 </form>
91 95
92 96 {% endblock %}
93 97
94 98 {% block metapanel %}
95 99
96 100 <span class="metapanel">
97 101 {{ posts.0.get_reply_count }} {% trans 'replies' %},
98 102 {{ posts.0.get_images_count }} {% trans 'images' %}.
99 103 {% trans 'Last update: ' %}{{ posts.0.last_edit_time }}
100 104 </span>
101 105
102 106 {% endblock %} No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now