##// END OF EJS Templates
Speed up loading favorite list. Add reflinks to the list to see favorite...
neko259 -
r1343:dff9bff4 default
parent child Browse files
Show More
@@ -1,129 +1,126
1 1 /*
2 2 @licstart The following is the entire license notice for the
3 3 JavaScript code in this page.
4 4
5 5
6 6 Copyright (C) 2013 neko259
7 7
8 8 The JavaScript code in this page is free software: you can
9 9 redistribute it and/or modify it under the terms of the GNU
10 10 General Public License (GNU GPL) as published by the Free Software
11 11 Foundation, either version 3 of the License, or (at your option)
12 12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15 15
16 16 As additional permission under GNU GPL version 3 section 7, you
17 17 may distribute non-source (e.g., minimized or compacted) forms of
18 18 that code without the copy of the GNU GPL normally required by
19 19 section 4, provided you include this license notice and a URL
20 20 through which recipients can access the Corresponding Source.
21 21
22 22 @licend The above is the entire license notice
23 23 for the JavaScript code in this page.
24 24 */
25 25
26 26 var FAV_POST_UPDATE_PERIOD = 10000;
27 27
28 28 /**
29 29 * An email is a hidden file to prevent spam bots from posting. It has to be
30 30 * hidden.
31 31 */
32 32 function hideEmailFromForm() {
33 33 $('.form-email').parent().parent().hide();
34 34 }
35 35
36 36 /**
37 37 * Highlight code blocks with code highlighter
38 38 */
39 39 function highlightCode(node) {
40 40 node.find('pre code').each(function(i, e) {
41 41 hljs.highlightBlock(e);
42 42 });
43 43 }
44 44
45 45 function updateFavPosts() {
46 46 var includePostBody = $('#fav-panel').is(":visible");
47 47 var url = '/api/new_posts/';
48 48 if (includePostBody) {
49 49 url += '?include_posts'
50 50 }
51 51 $.getJSON(url,
52 52 function(data) {
53 53 var allNewPostCount = 0;
54 54
55 55 if (includePostBody) {
56 56 var favoriteThreadPanel = $('#fav-panel');
57 57 favoriteThreadPanel.empty();
58 58 }
59 59
60 60 $.each(data, function (_, dict) {
61 61 var newPostCount = dict.new_post_count;
62 62 allNewPostCount += newPostCount;
63 63
64 64 if (includePostBody) {
65 var post = $(dict.post);
66
67 var id = post.find('.post_id');
68 var title = post.find('.title');
69
70 65 var favThreadNode = $('<div class="post"></div>');
71 favThreadNode.append(id);
66 favThreadNode.append($(dict.post_url));
72 67 favThreadNode.append(' ');
73 favThreadNode.append(title);
68 favThreadNode.append($('<span class="title">' + dict.title + '</span>'));
74 69
75 70 if (newPostCount > 0) {
76 71 favThreadNode.append(' (<a href="' + dict.newest_post_link + '">+' + newPostCount + "</a>)");
77 72 }
78 73
79 74 favoriteThreadPanel.append(favThreadNode);
75
76 addRefLinkPreview(favThreadNode[0]);
80 77 }
81 78 });
82 79
83 80 var newPostCountNode = $('#new-fav-post-count');
84 81 if (allNewPostCount > 0) {
85 82 newPostCountNode.text('(+' + allNewPostCount + ')');
86 83 newPostCountNode.show();
87 84 } else {
88 85 newPostCountNode.hide();
89 86 }
90 87 }
91 88 );
92 89 }
93 90
94 91 function initFavPanel() {
95 92 updateFavPosts();
96 93
97 94 if ($('#fav-panel-btn').length > 0) {
98 95 setInterval(updateFavPosts, FAV_POST_UPDATE_PERIOD);
99 96 $('#fav-panel-btn').click(function() {
100 97 $('#fav-panel').toggle();
101 98 updateFavPosts();
102 99
103 100 return false;
104 101 });
105 102
106 103 $(document).on('keyup.removepic', function(e) {
107 104 if(e.which === 27) {
108 105 $('#fav-panel').hide();
109 106 }
110 107 });
111 108 }
112 109 }
113 110
114 111 $( document ).ready(function() {
115 112 hideEmailFromForm();
116 113
117 114 $("a[href='#top']").click(function() {
118 115 $("html, body").animate({ scrollTop: 0 }, "slow");
119 116 return false;
120 117 });
121 118
122 119 addImgPreview();
123 120
124 121 addRefLinkPreview();
125 122
126 123 highlightCode($(document));
127 124
128 125 initFavPanel();
129 126 });
@@ -1,274 +1,274
1 1 from collections import OrderedDict
2 2 import json
3 3 import logging
4 4
5 5 from django.db import transaction
6 6 from django.http import HttpResponse
7 7 from django.shortcuts import get_object_or_404
8 8 from django.core import serializers
9 9 from boards.abstracts.settingsmanager import get_settings_manager
10 10
11 11 from boards.forms import PostForm, PlainErrorList
12 12 from boards.models import Post, Thread, Tag
13 13 from boards.utils import datetime_to_epoch
14 14 from boards.views.thread import ThreadView
15 15 from boards.models.user import Notification
16 16 from boards.mdx_neboard import Parser
17 17
18 18
19 19 __author__ = 'neko259'
20 20
21 21 PARAMETER_TRUNCATED = 'truncated'
22 22 PARAMETER_TAG = 'tag'
23 23 PARAMETER_OFFSET = 'offset'
24 24 PARAMETER_DIFF_TYPE = 'type'
25 25 PARAMETER_POST = 'post'
26 26 PARAMETER_UPDATED = 'updated'
27 27 PARAMETER_LAST_UPDATE = 'last_update'
28 28 PARAMETER_THREAD = 'thread'
29 29 PARAMETER_UIDS = 'uids'
30 30
31 31 DIFF_TYPE_HTML = 'html'
32 32 DIFF_TYPE_JSON = 'json'
33 33
34 34 STATUS_OK = 'ok'
35 35 STATUS_ERROR = 'error'
36 36
37 37 logger = logging.getLogger(__name__)
38 38
39 39
40 40 @transaction.atomic
41 41 def api_get_threaddiff(request):
42 42 """
43 43 Gets posts that were changed or added since time
44 44 """
45 45
46 46 thread_id = request.POST.get(PARAMETER_THREAD)
47 47 uids_str = request.POST.get(PARAMETER_UIDS).strip()
48 48 uids = uids_str.split(' ')
49 49
50 50 opening_post = get_object_or_404(Post, id=thread_id)
51 51 thread = opening_post.get_thread()
52 52
53 53 json_data = {
54 54 PARAMETER_UPDATED: [],
55 55 PARAMETER_LAST_UPDATE: None, # TODO Maybe this can be removed already?
56 56 }
57 57 posts = Post.objects.filter(threads__in=[thread]).exclude(uid__in=uids)
58 58
59 59 diff_type = request.GET.get(PARAMETER_DIFF_TYPE, DIFF_TYPE_HTML)
60 60
61 61 for post in posts:
62 62 json_data[PARAMETER_UPDATED].append(post.get_post_data(
63 63 format_type=diff_type, request=request))
64 64 json_data[PARAMETER_LAST_UPDATE] = str(thread.last_edit_time)
65 65
66 66 # If the tag is favorite, update the counter
67 67 settings_manager = get_settings_manager(request)
68 68 favorite = settings_manager.thread_is_fav(opening_post)
69 69 if favorite:
70 70 settings_manager.add_or_read_fav_thread(opening_post)
71 71
72 72 return HttpResponse(content=json.dumps(json_data))
73 73
74 74
75 75 def api_add_post(request, opening_post_id):
76 76 """
77 77 Adds a post and return the JSON response for it
78 78 """
79 79
80 80 opening_post = get_object_or_404(Post, id=opening_post_id)
81 81
82 82 logger.info('Adding post via api...')
83 83
84 84 status = STATUS_OK
85 85 errors = []
86 86
87 87 if request.method == 'POST':
88 88 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
89 89 form.session = request.session
90 90
91 91 if form.need_to_ban:
92 92 # Ban user because he is suspected to be a bot
93 93 # _ban_current_user(request)
94 94 status = STATUS_ERROR
95 95 if form.is_valid():
96 96 post = ThreadView().new_post(request, form, opening_post,
97 97 html_response=False)
98 98 if not post:
99 99 status = STATUS_ERROR
100 100 else:
101 101 logger.info('Added post #%d via api.' % post.id)
102 102 else:
103 103 status = STATUS_ERROR
104 104 errors = form.as_json_errors()
105 105
106 106 response = {
107 107 'status': status,
108 108 'errors': errors,
109 109 }
110 110
111 111 return HttpResponse(content=json.dumps(response))
112 112
113 113
114 114 def get_post(request, post_id):
115 115 """
116 116 Gets the html of a post. Used for popups. Post can be truncated if used
117 117 in threads list with 'truncated' get parameter.
118 118 """
119 119
120 120 post = get_object_or_404(Post, id=post_id)
121 121 truncated = PARAMETER_TRUNCATED in request.GET
122 122
123 123 return HttpResponse(content=post.get_view(truncated=truncated))
124 124
125 125
126 126 def api_get_threads(request, count):
127 127 """
128 128 Gets the JSON thread opening posts list.
129 129 Parameters that can be used for filtering:
130 130 tag, offset (from which thread to get results)
131 131 """
132 132
133 133 if PARAMETER_TAG in request.GET:
134 134 tag_name = request.GET[PARAMETER_TAG]
135 135 if tag_name is not None:
136 136 tag = get_object_or_404(Tag, name=tag_name)
137 137 threads = tag.get_threads().filter(archived=False)
138 138 else:
139 139 threads = Thread.objects.filter(archived=False)
140 140
141 141 if PARAMETER_OFFSET in request.GET:
142 142 offset = request.GET[PARAMETER_OFFSET]
143 143 offset = int(offset) if offset is not None else 0
144 144 else:
145 145 offset = 0
146 146
147 147 threads = threads.order_by('-bump_time')
148 148 threads = threads[offset:offset + int(count)]
149 149
150 150 opening_posts = []
151 151 for thread in threads:
152 152 opening_post = thread.get_opening_post()
153 153
154 154 # TODO Add tags, replies and images count
155 155 post_data = opening_post.get_post_data(include_last_update=True)
156 156 post_data['bumpable'] = thread.can_bump()
157 157 post_data['archived'] = thread.archived
158 158
159 159 opening_posts.append(post_data)
160 160
161 161 return HttpResponse(content=json.dumps(opening_posts))
162 162
163 163
164 164 # TODO Test this
165 165 def api_get_tags(request):
166 166 """
167 167 Gets all tags or user tags.
168 168 """
169 169
170 170 # TODO Get favorite tags for the given user ID
171 171
172 172 tags = Tag.objects.get_not_empty_tags()
173 173
174 174 term = request.GET.get('term')
175 175 if term is not None:
176 176 tags = tags.filter(name__contains=term)
177 177
178 178 tag_names = [tag.name for tag in tags]
179 179
180 180 return HttpResponse(content=json.dumps(tag_names))
181 181
182 182
183 183 # TODO The result can be cached by the thread last update time
184 184 # TODO Test this
185 185 def api_get_thread_posts(request, opening_post_id):
186 186 """
187 187 Gets the JSON array of thread posts
188 188 """
189 189
190 190 opening_post = get_object_or_404(Post, id=opening_post_id)
191 191 thread = opening_post.get_thread()
192 192 posts = thread.get_replies()
193 193
194 194 json_data = {
195 195 'posts': [],
196 196 'last_update': None,
197 197 }
198 198 json_post_list = []
199 199
200 200 for post in posts:
201 201 json_post_list.append(post.get_post_data())
202 202 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
203 203 json_data['posts'] = json_post_list
204 204
205 205 return HttpResponse(content=json.dumps(json_data))
206 206
207 207
208 208 def api_get_notifications(request, username):
209 209 last_notification_id_str = request.GET.get('last', None)
210 210 last_id = int(last_notification_id_str) if last_notification_id_str is not None else None
211 211
212 212 posts = Notification.objects.get_notification_posts(username=username,
213 213 last=last_id)
214 214
215 215 json_post_list = []
216 216 for post in posts:
217 217 json_post_list.append(post.get_post_data())
218 218 return HttpResponse(content=json.dumps(json_post_list))
219 219
220 220
221 221 def api_get_post(request, post_id):
222 222 """
223 223 Gets the JSON of a post. This can be
224 224 used as and API for external clients.
225 225 """
226 226
227 227 post = get_object_or_404(Post, id=post_id)
228 228
229 229 json = serializers.serialize("json", [post], fields=(
230 230 "pub_time", "_text_rendered", "title", "text", "image",
231 231 "image_width", "image_height", "replies", "tags"
232 232 ))
233 233
234 234 return HttpResponse(content=json)
235 235
236 236
237 237 def api_get_preview(request):
238 238 raw_text = request.POST['raw_text']
239 239
240 240 parser = Parser()
241 241 return HttpResponse(content=parser.parse(parser.preparse(raw_text)))
242 242
243 243
244 244 def api_get_new_posts(request):
245 245 """
246 246 Gets favorite threads and unread posts count.
247 247 """
248 248 posts = list()
249 249
250 250 include_posts = 'include_posts' in request.GET
251 251
252 252 settings_manager = get_settings_manager(request)
253 253 fav_threads = settings_manager.get_fav_threads()
254 254 fav_thread_ops = Post.objects.filter(id__in=fav_threads.keys())\
255 255 .order_by('-pub_time').prefetch_related('thread')
256 256
257 257 for op in fav_thread_ops:
258 258 last_read_post = fav_threads[str(op.id)]
259 259 new_posts = op.get_thread().get_replies_newer(last_read_post)
260 260 new_post_count = new_posts.count()
261 261 fav_thread_dict = dict()
262 262 fav_thread_dict['id'] = op.id
263 263 fav_thread_dict['new_post_count'] = new_post_count
264 264
265 265 if include_posts:
266 fav_thread_dict['post'] = op.get_post_data(
267 format_type=DIFF_TYPE_HTML)
266 fav_thread_dict['post_url'] = op.get_link_view()
267 fav_thread_dict['title'] = op.title
268 268 if new_post_count > 0:
269 269 fav_thread_dict['newest_post_link'] = new_posts.first()\
270 270 .get_absolute_url()
271 271
272 272 posts.append(fav_thread_dict)
273 273
274 274 return HttpResponse(content=json.dumps(posts))
General Comments 0
You need to be logged in to leave comments. Login now