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="{}">>>{}</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 |
|
|
|
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