##// END OF EJS Templates
Favorite threads with new posts counter
neko259 -
r1323:46a185c5 default
parent child Browse files
Show More
@@ -11,6 +11,7 b" PERMISSION_MODERATE = 'moderator'"
11 11
12 12 SETTING_THEME = 'theme'
13 13 SETTING_FAVORITE_TAGS = 'favorite_tags'
14 SETTING_FAVORITE_THREADS = 'favorite_threads'
14 15 SETTING_HIDDEN_TAGS = 'hidden_tags'
15 16 SETTING_PERMISSIONS = 'permissions'
16 17 SETTING_USERNAME = 'username'
@@ -118,6 +119,23 b' class SettingsManager:'
118 119 tags.remove(tag.name)
119 120 self.set_setting(SETTING_HIDDEN_TAGS, tags)
120 121
122 def get_fav_threads(self) -> dict:
123 return self.get_setting(SETTING_FAVORITE_THREADS, default=dict())
124
125 def add_or_read_fav_thread(self, opening_post):
126 threads = self.get_fav_threads()
127 threads[str(opening_post.id)] = opening_post.get_thread().get_replies()\
128 .last().id
129 self.set_setting(SETTING_FAVORITE_THREADS, threads)
130
131 def del_fav_thread(self, opening_post):
132 threads = self.get_fav_threads()
133 if self.thread_is_fav(opening_post):
134 del threads[str(opening_post.id)]
135 self.set_setting(SETTING_FAVORITE_THREADS, threads)
136
137 def thread_is_fav(self, opening_post):
138 return str(opening_post.id) in self.get_fav_threads()
121 139
122 140 class SessionSettingsManager(SettingsManager):
123 141 """
@@ -19,6 +19,7 b" CONTEXT_NEW_NOTIFICATIONS_COUNT = 'new_n"
19 19 CONTEXT_USERNAME = 'username'
20 20 CONTEXT_TAGS_STR = 'tags_str'
21 21 CONTEXT_IMAGE_VIEWER = 'image_viewer'
22 CONTEXT_FAV_THREADS = 'fav_threads'
22 23
23 24
24 25 def get_notifications(context, request):
@@ -43,6 +44,9 b' def user_and_ui_processor(request):'
43 44 settings_manager = get_settings_manager(request)
44 45 fav_tags = settings_manager.get_fav_tags()
45 46 context[CONTEXT_TAGS] = fav_tags
47
48 _get_fav_threads(context, settings_manager)
49
46 50 context[CONTEXT_TAGS_STR] = Tag.objects.get_tag_url_list(fav_tags)
47 51 theme = settings_manager.get_theme()
48 52 context[CONTEXT_THEME] = theme
@@ -61,3 +65,15 b' def user_and_ui_processor(request):'
61 65 get_notifications(context, request)
62 66
63 67 return context
68
69
70 def _get_fav_threads(context, settings_manager):
71 fav_threads_setting = settings_manager.get_fav_threads()
72 if fav_threads_setting:
73 fav_threads = Post.objects.filter(
74 id__in=fav_threads_setting.keys()).only('url', 'id', 'thread')\
75 .select_related('thread')
76 context[CONTEXT_FAV_THREADS] = [
77 (post, post.get_thread().get_replies_newer(
78 fav_threads_setting[str(post.id)]).count())
79 for post in fav_threads]
@@ -253,7 +253,6 b' class Post(models.Model, Viewable):'
253 253 post_url += '#' + str(self.id)
254 254 return post_url
255 255
256
257 256 def get_thread(self):
258 257 return self.thread
259 258
@@ -449,7 +448,7 b' class Post(models.Model, Viewable):'
449 448 """
450 449
451 450 result = '<a href="{}">&gt;&gt;{}</a>'.format(self.get_absolute_url(),
452 self.id)
451 self.id)
453 452 if self.is_opening():
454 453 result = '<b>{}</b>'.format(result)
455 454
@@ -228,3 +228,7 b' class Thread(models.Model):'
228 228
229 229 def get_required_tags(self):
230 230 return self.get_tags().filter(required=True)
231
232 def get_replies_newer(self, post_id):
233 return self.get_replies().filter(id__gt=post_id)
234
@@ -510,6 +510,11 b' ul {'
510 510 border: 1px solid #777;
511 511 background: #000;
512 512 padding: 4px;
513 opacity: 0.3;
514 }
515
516 #up:hover {
517 opacity: 1;
513 518 }
514 519
515 520 .user-cast {
@@ -439,11 +439,11 b' function updateNodeAttr(oldNode, newNode'
439 439 if (form.length > 0) {
440 440 var options = {
441 441 beforeSubmit: function(arr, $form, options) {
442 showAsErrors($('form'), gettext('Sending message...'));
442 showAsErrors($('#form'), gettext('Sending message...'));
443 443 },
444 444 success: updateOnPost,
445 445 error: function() {
446 showAsErrors($('form'), gettext('Server error!'));
446 showAsErrors($('#form'), gettext('Server error!'));
447 447 },
448 448 url: '/api/add_post/' + threadId + '/'
449 449 };
@@ -28,6 +28,7 b''
28 28 <script src="{% url 'js_info_dict' %}"></script>
29 29
30 30 <div class="navigation_panel header">
31 <div>
31 32 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
32 33 {% if tags_str %}
33 34 {% autoescape off %}
@@ -51,6 +52,18 b''
51 52 {% endif %}
52 53
53 54 <a class="right-link link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
55 </div>
56 {% if fav_threads %}
57 <div>
58 <span class="fav">β˜…</span>
59 {% for thread in fav_threads %}
60 {% comment %}
61 If there are new posts in the thread, show their count.
62 {% endcomment %}
63 {{ thread.0.get_link_view|safe }}{% if thread.1 %} (+{{ thread.1 }}){% endif %}{% if not forloop.last %}, {% endif %}
64 {% endfor %}
65 </div>
66 {% endif %}
54 67 </div>
55 68
56 69 {% block content %}{% endblock %}
@@ -9,6 +9,19 b''
9 9 {% get_current_language as LANGUAGE_CODE %}
10 10 {% get_current_timezone as TIME_ZONE %}
11 11
12 <div class="tag_info">
13 <h2>
14 <form action="{% url 'thread' opening_post.id %}" method="post" class="post-button-form">
15 {% if is_favorite %}
16 <button name="method" value="unsubscribe" class="fav">β˜…</button>
17 {% else %}
18 <button name="method" value="subscribe" class="not_fav">β˜…</button>
19 {% endif %}
20 </form>
21 {{ opening_post.get_title|striptags|truncatewords:10 }}
22 </h2>
23 </div>
24
12 25 {% if bumpable and thread.has_post_limit %}
13 26 <div class="bar-bg">
14 27 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
@@ -5,6 +5,7 b' from django.db import transaction'
5 5 from django.http import HttpResponse
6 6 from django.shortcuts import get_object_or_404
7 7 from django.core import serializers
8 from boards.abstracts.settingsmanager import get_settings_manager
8 9
9 10 from boards.forms import PostForm, PlainErrorList
10 11 from boards.models import Post, Thread, Tag
@@ -45,7 +46,8 b' def api_get_threaddiff(request):'
45 46 uids_str = request.POST.get(PARAMETER_UIDS).strip()
46 47 uids = uids_str.split(' ')
47 48
48 thread = get_object_or_404(Post, id=thread_id).get_thread()
49 opening_post = get_object_or_404(Post, id=thread_id)
50 thread = opening_post.get_thread()
49 51
50 52 json_data = {
51 53 PARAMETER_UPDATED: [],
@@ -60,6 +62,12 b' def api_get_threaddiff(request):'
60 62 request))
61 63 json_data[PARAMETER_LAST_UPDATE] = str(thread.last_edit_time)
62 64
65 # If the tag is favorite, update the counter
66 settings_manager = get_settings_manager(request)
67 favorite = settings_manager.thread_is_fav(opening_post)
68 if favorite:
69 settings_manager.add_or_read_fav_thread(opening_post)
70
63 71 return HttpResponse(content=json.dumps(json_data))
64 72
65 73
@@ -7,9 +7,11 b' from django.utils import timezone'
7 7 from django.utils.dateformat import format
8 8
9 9 from boards import utils, settings
10 from boards.abstracts.settingsmanager import get_settings_manager
10 11 from boards.forms import PostForm, PlainErrorList
11 12 from boards.models import Post
12 13 from boards.views.base import BaseBoardView, CONTEXT_FORM
14 from boards.views.mixins import DispatcherMixin
13 15 from boards.views.posting_mixin import PostMixin
14 16
15 17 import neboard
@@ -24,6 +26,7 b" CONTEXT_WS_PORT = 'ws_port'"
24 26 CONTEXT_WS_TIME = 'ws_token_time'
25 27 CONTEXT_MODE = 'mode'
26 28 CONTEXT_OP = 'opening_post'
29 CONTEXT_FAVORITE = 'is_favorite'
27 30
28 31 FORM_TITLE = 'title'
29 32 FORM_TEXT = 'text'
@@ -31,7 +34,7 b" FORM_IMAGE = 'image'"
31 34 FORM_THREADS = 'threads'
32 35
33 36
34 class ThreadView(BaseBoardView, PostMixin, FormMixin):
37 class ThreadView(BaseBoardView, PostMixin, FormMixin, DispatcherMixin):
35 38
36 39 def get(self, request, post_id, form: PostForm=None):
37 40 try:
@@ -39,10 +42,21 b' class ThreadView(BaseBoardView, PostMixi'
39 42 except ObjectDoesNotExist:
40 43 raise Http404
41 44
45 if 'method' in request.POST:
46 self.dispatch_method(request, opening_post)
47
48 return redirect('thread', post_id) # FIXME Different for different modes
49
50 # If the tag is favorite, update the counter
51 settings_manager = get_settings_manager(request)
52 favorite = settings_manager.thread_is_fav(opening_post)
53 if favorite:
54 settings_manager.add_or_read_fav_thread(opening_post)
55
42 56 # If this is not OP, don't show it as it is
43 57 if not opening_post.is_opening():
44 58 return redirect(opening_post.get_thread().get_opening_post()
45 .get_absolute_url())
59 .get_absolute_url())
46 60
47 61 if not form:
48 62 form = PostForm(error_class=PlainErrorList)
@@ -56,6 +70,7 b' class ThreadView(BaseBoardView, PostMixi'
56 70 params[CONTEXT_THREAD] = thread_to_show
57 71 params[CONTEXT_MODE] = self.get_mode()
58 72 params[CONTEXT_OP] = opening_post
73 params[CONTEXT_FAVORITE] = favorite
59 74
60 75 if settings.get_bool('External', 'WebsocketsEnabled'):
61 76 token_time = format(timezone.now(), u'U')
@@ -138,3 +153,11 b' class ThreadView(BaseBoardView, PostMixi'
138 153
139 154 def get_mode(self) -> str:
140 155 pass
156
157 def subscribe(self, request, opening_post):
158 settings_manager = get_settings_manager(request)
159 settings_manager.add_or_read_fav_thread(opening_post)
160
161 def unsubscribe(self, request, opening_post):
162 settings_manager = get_settings_manager(request)
163 settings_manager.del_fav_thread(opening_post)
General Comments 0
You need to be logged in to leave comments. Login now