##// END OF EJS Templates
Merged with thread autoupdate branch
neko259 -
r374:bd40633e merge default
parent child Browse files
Show More
@@ -0,0 +1,116 b''
1 /*
2 @licstart The following is the entire license notice for the
3 JavaScript code in this page.
4
5
6 Copyright (C) 2013 neko259
7
8 The JavaScript code in this page is free software: you can
9 redistribute it and/or modify it under the terms of the GNU
10 General Public License (GNU GPL) as published by the Free Software
11 Foundation, either version 3 of the License, or (at your option)
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15
16 As additional permission under GNU GPL version 3 section 7, you
17 may distribute non-source (e.g., minimized or compacted) forms of
18 that code without the copy of the GNU GPL normally required by
19 section 4, provided you include this license notice and a URL
20 through which recipients can access the Corresponding Source.
21
22 @licend The above is the entire license notice
23 for the JavaScript code in this page.
24 */
25
26 var THREAD_UPDATE_DELAY = 10000;
27
28 var loading = false;
29 var lastUpdateTime = null;
30
31 function blink(node) {
32 var blinkCount = 2;
33 var blinkDelay = 250;
34
35 var nodeToAnimate = node;
36 for (var i = 0; i < blinkCount; i++) {
37 nodeToAnimate = nodeToAnimate.fadeOut(blinkDelay).fadeIn(blinkDelay);
38 }
39 }
40
41 function updateThread() {
42 if (loading) {
43 return;
44 }
45
46 loading = true;
47
48 var threadPosts = $('div.thread').children('.post');
49
50 var lastPost = threadPosts.last();
51 var threadId = threadPosts.first().attr('id');
52
53 var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/';
54 $.getJSON(diffUrl)
55 .success(function(data) {
56 var bottom = isPageBottom();
57
58 var addedPosts = data.added;
59
60 for (var i = 0; i < addedPosts.length; i++) {
61 var postText = addedPosts[i];
62
63 var post = $(postText);
64 post.appendTo(lastPost.parent());
65 addRefLinkPreview(post[0]);
66
67 lastPost = post;
68 blink(post);
69 }
70
71 var updatedPosts = data.updated;
72 for (var i = 0; i < updatedPosts.length; i++) {
73 var postText = updatedPosts[i];
74
75 var post = $(postText);
76 var postId = post.attr('id');
77
78 var oldPost = $('div.thread').children('.post[id=' + postId + ']');
79
80 oldPost.replaceWith(post);
81 addRefLinkPreview(post[0]);
82
83 blink(post);
84 }
85
86 // TODO Process deleted posts
87
88 lastUpdateTime = data.last_update;
89 loading = false;
90
91 if (bottom) {
92 var $target = $('html,body');
93 $target.animate({scrollTop: $target.height()}, 1000);
94 }
95 })
96 .error(function(data) {
97 // TODO Show error message that server is unavailable?
98
99 loading = false;
100 });
101 }
102
103 function isPageBottom() {
104 var scroll = $(window).scrollTop() / ($(document).height()
105 - $(window).height())
106
107 return scroll == 1
108 }
109
110 function initAutoupdate() {
111 loading = false;
112
113 lastUpdateTime = $('.metapanel').attr('data-last-update');
114
115 setInterval(updateThread, THREAD_UPDATE_DELAY);
116 }
@@ -47,15 +47,17 b' class PostManager(models.Manager):'
47 47
48 48 def create_post(self, title, text, image=None, thread=None,
49 49 ip=NO_IP, tags=None, user=None):
50 posting_time = timezone.now()
51
50 52 post = self.create(title=title,
51 53 text=text,
52 pub_time=timezone.now(),
54 pub_time=posting_time,
53 55 thread=thread,
54 56 image=image,
55 57 poster_ip=ip,
56 58 poster_user_agent=UNKNOWN_UA,
57 last_edit_time=timezone.now(),
58 bump_time=timezone.now(),
59 last_edit_time=posting_time,
60 bump_time=posting_time,
59 61 user=user)
60 62
61 63 if tags:
@@ -66,7 +68,7 b' class PostManager(models.Manager):'
66 68 if thread:
67 69 thread.replies.add(post)
68 70 thread.bump()
69 thread.last_edit_time = timezone.now()
71 thread.last_edit_time = posting_time
70 72 thread.save()
71 73
72 74 #cache_key = thread.get_cache_key()
@@ -179,7 +181,10 b' class PostManager(models.Manager):'
179 181 id = reply_number.group(1)
180 182 ref_post = self.filter(id=id)
181 183 if ref_post.count() > 0:
182 ref_post[0].referenced_posts.add(post)
184 referenced_post = ref_post[0]
185 referenced_post.referenced_posts.add(post)
186 referenced_post.last_edit_time = post.pub_time
187 referenced_post.save()
183 188
184 189 def _get_page_count(self, thread_count):
185 190 return int(math.ceil(thread_count / float(settings.THREADS_PER_PAGE)))
@@ -312,7 +317,7 b' class Post(models.Model):'
312 317 def can_bump(self):
313 318 """Check if the thread can be bumped by replying"""
314 319
315 post_count = self.get_reply_count() + 1
320 post_count = self.get_reply_count()
316 321
317 322 return post_count <= settings.MAX_POSTS_PER_THREAD
318 323
@@ -57,7 +57,7 b' function showPostPreview(e) {'
57 57 };
58 58
59 59
60 cln.innerHTML = gettext('Loading...');
60 cln.innerHTML = "<div class=\"post\">" + gettext('Loading...') + "</div>";
61 61
62 62 //если пост найден в дереве.
63 63 if($('div[id='+pNum+']').length > 0) {
@@ -72,7 +72,7 b' function showPostPreview(e) {'
72 72 //ajax api
73 73 else {
74 74 $.ajax({
75 url: '/api/post/' + pNum
75 url: '/api/post/' + pNum + '/?truncated'
76 76 })
77 77 .success(function(data) {
78 78 // TODO get a json, not post itself
@@ -83,7 +83,8 b' function showPostPreview(e) {'
83 83
84 84 })
85 85 .error(function() {
86 cln.innerHTML = gettext('Post not found');
86 cln.innerHTML = "<div class=\"post\">"
87 + gettext('Post not found') + "</div>";
87 88 });
88 89 }
89 90
@@ -77,4 +77,5 b' function addQuickReply(postId) {'
77 77
78 78 $(document).ready(function(){
79 79 addGalleryPanel();
80 initAutoupdate();
80 81 });
@@ -1,14 +1,19 b''
1 1 {% load i18n %}
2 2 {% load board %}
3 3
4 {% if can_bump %}
4 5 <div class="post" id="{{ post.id }}">
6 {% else %}
7 <div class="post dead_post" id="{{ post.id }}">
8 {% endif %}
9
5 10 {% if post.image %}
6 11 <div class="image">
7 12 <a
8 13 class="thumb"
9 14 href="{{ post.image.url }}"><img
10 15 src="{{ post.image.url_200x150 }}"
11 alt="{% trans 'Post image' %}"v
16 alt="{{ post.id }}"
12 17 data-width="{{ post.image_width }}"
13 18 data-height="{{ post.image_height }}"/>
14 19 </a>
@@ -18,8 +23,10 b''
18 23 <div class="post-info">
19 24 <span class="title">{{ post.title }}</span>
20 25 <a class="post_id" href="#{{ post.id }}">
21 (#{{ post.id }})</a>
26 ({{ post.id }})</a>
22 27 [{{ post.pub_time }}]
28 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
29 ; return false;">&gt;&gt;</a>]
23 30
24 31 {% if moderator %}
25 32 <span class="moderator_info">
@@ -32,8 +39,13 b''
32 39 {% endif %}
33 40 </div>
34 41 {% autoescape off %}
42 {% if truncated %}
43 {{ post.text.rendered|truncatewords_html:50 }}
44 {% else %}
35 45 {{ post.text.rendered }}
46 {% endif %}
36 47 {% endautoescape %}
48 {% if post.is_referenced %}
37 49 <div class="refmap">
38 50 {% trans "Replies" %}:
39 51 {% for ref_post in post.get_sorted_referenced_posts %}
@@ -41,6 +53,7 b''
41 53 >{% if not forloop.last %},{% endif %}
42 54 {% endfor %}
43 55 </div>
56 {% endif %}
44 57 </div>
45 58 {% if post.tags.exists %}
46 59 <div class="metadata">
@@ -13,6 +13,7 b''
13 13 {% block content %}
14 14 {% get_current_language as LANGUAGE_CODE %}
15 15
16 <script src="{% static 'js/thread_update.js' %}"></script>
16 17 <script src="{% static 'js/thread.js' %}"></script>
17 18
18 19 {% if posts %}
@@ -151,7 +152,7 b''
151 152
152 153 {% get_current_language as LANGUAGE_CODE %}
153 154
154 <span class="metapanel">
155 <span class="metapanel" data-last-update="{{ last_update }}">
155 156 {% cache 600 thread_meta posts.0.last_edit_time moderator LANGUAGE_CODE %}
156 157 {{ posts.0.get_reply_count }} {% trans 'replies' %},
157 158 {{ posts.0.get_images_count }} {% trans 'images' %}.
@@ -53,4 +53,6 b" urlpatterns = patterns('',"
53 53
54 54 # API
55 55 url(r'^api/post/(?P<post_id>\w+)/$', views.get_post, name="get_post"),
56 url(r'^api/diff_thread/(?P<thread_id>\w+)/(?P<last_update_time>\w+)/$',
57 views.api_get_threaddiff, name="get_thread_diff"),
56 58 )
@@ -1,5 +1,11 b''
1 1 import hashlib
2 import json
2 3 import string
4 import time
5 import calendar
6
7 from datetime import datetime
8
3 9 from django.core import serializers
4 10 from django.core.urlresolvers import reverse
5 11 from django.http import HttpResponseRedirect
@@ -8,6 +14,7 b' from django.template import RequestConte'
8 14 from django.shortcuts import render, redirect, get_object_or_404
9 15 from django.utils import timezone
10 16 from django.db import transaction
17 import math
11 18
12 19 from boards import forms
13 20 import boards
@@ -210,6 +217,7 b' def thread(request, post_id):'
210 217 context['bumplimit_progress'] = str(
211 218 float(context['posts_left']) /
212 219 neboard.settings.MAX_POSTS_PER_THREAD * 100)
220 context["last_update"] = _datetime_to_epoch(posts[0].last_edit_time)
213 221
214 222 return render(request, 'boards/thread.html', context)
215 223
@@ -408,13 +416,43 b' def api_get_post(request, post_id):'
408 416 return HttpResponse(content=json)
409 417
410 418
419 def api_get_threaddiff(request, thread_id, last_update_time):
420 """Get posts that were changed or added since time"""
421
422 thread = get_object_or_404(Post, id=thread_id)
423
424 filter_time = datetime.fromtimestamp(float(last_update_time) / 1000000,
425 timezone.get_current_timezone())
426
427 json_data = {
428 'added': [],
429 'updated': [],
430 'last_update': None,
431 }
432 added_posts = Post.objects.filter(thread=thread, pub_time__gt=filter_time)
433 updated_posts = Post.objects.filter(thread=thread,
434 pub_time__lt=filter_time,
435 last_edit_time__gt=filter_time)
436 for post in added_posts:
437 json_data['added'].append(get_post(request, post.id).content.strip())
438 for post in updated_posts:
439 json_data['updated'].append(get_post(request, post.id).content.strip())
440 json_data['last_update'] = _datetime_to_epoch(thread.last_edit_time)
441
442 return HttpResponse(content=json.dumps(json_data))
443
444
411 445 def get_post(request, post_id):
412 446 """Get the html of a post. Used for popups."""
413 447
414 448 post = get_object_or_404(Post, id=post_id)
449 thread = post.thread
415 450
416 451 context = RequestContext(request)
417 452 context["post"] = post
453 context["can_bump"] = thread.can_bump()
454 if "truncated" in request.GET:
455 context["truncated"] = True
418 456
419 457 return render(request, 'boards/post.html', context)
420 458
@@ -518,3 +556,9 b' def _remove_invalid_links(text):'
518 556 text = string.replace(text, '>>' + id, id)
519 557
520 558 return text
559
560
561 def _datetime_to_epoch(datetime):
562 return int(time.mktime(timezone.localtime(
563 datetime,timezone.get_current_timezone()).timetuple())
564 * 1000000 + datetime.microsecond) No newline at end of file
@@ -219,7 +219,7 b' LAST_REPLIES_COUNT = 3'
219 219 ENABLE_CAPTCHA = False
220 220 # if user tries to post before CAPTCHA_DEFAULT_SAFE_TIME. Captcha will be shown
221 221 CAPTCHA_DEFAULT_SAFE_TIME = 30 # seconds
222 POSTING_DELAY = 30 # seconds
222 POSTING_DELAY = 20 # seconds
223 223
224 224
225 225 def custom_show_toolbar(request):
@@ -9,6 +9,8 b' denied". Use second only for autoban for'
9 9 [DONE] Clean up tests and make them run ALWAYS
10 10 [DONE] Use transactions in tests
11 11
12 [IN PROGRESS] Thread autoupdate (JS + API)
13
12 14 [NOT STARTED] Tree view (JS)
13 15 [NOT STARTED] Adding tags to images filename
14 16 [NOT STARTED] Federative network for s2s communication
@@ -16,7 +18,6 b' denied". Use second only for autoban for'
16 18 [NOT STARTED] Bitmessage gate
17 19 [NOT STARTED] Notification engine
18 20 [NOT STARTED] Javascript disabling engine
19 [NOT STARTED] Thread autoupdate (JS + API)
20 21 [NOT STARTED] Group tags by first letter in all tags list
21 22 [NOT STARTED] Show board speed in the lower panel (posts per day)
22 23 [NOT STARTED] Character counter in the post field
@@ -30,6 +31,7 b' and move everything that is used only in'
30 31 post or its part (delimited by N characters) into quote of the new post.
31 32 [NOT STARTED] Ban confirmation page with reason
32 33 [NOT STARTED] Post deletion confirmation page
34 [NOT STARTED] Moderating page. Tags editing and adding
33 35
34 36 = Bugs =
35 37 [DONE] Fix bug with creating threads from tag view
General Comments 0
You need to be logged in to leave comments. Login now