##// END OF EJS Templates
Add notifications for threads created in favorite tags
neko259 -
r2054:fca209ed default
parent child Browse files
Show More
@@ -1,83 +1,84 b''
1 1 from boards.abstracts.settingsmanager import get_settings_manager, \
2 2 SETTING_LAST_NOTIFICATION_ID, SETTING_IMAGE_VIEWER, SETTING_ONLY_FAVORITES
3 3 from boards.models import Banner
4 4 from boards.models.user import Notification
5 5 from boards import settings
6 6 from boards.models import Post, Tag, Thread
7 7 from boards.settings import SECTION_FORMS, SECTION_VIEW, SECTION_VERSION
8 8
9 9 THEME_CSS = 'css/{}/base_page.css'
10 10
11 11 CONTEXT_SITE_NAME = 'site_name'
12 12 CONTEXT_VERSION = 'version'
13 13 CONTEXT_THEME_CSS = 'theme_css'
14 14 CONTEXT_THEME = 'theme'
15 15 CONTEXT_PPD = 'posts_per_day'
16 16 CONTEXT_USER = 'user'
17 17 CONTEXT_NEW_NOTIFICATIONS_COUNT = 'new_notifications_count'
18 18 CONTEXT_USERNAMES = 'usernames'
19 19 CONTEXT_TAGS_STR = 'tags_str'
20 20 CONTEXT_IMAGE_VIEWER = 'image_viewer'
21 21 CONTEXT_HAS_FAV_THREADS = 'has_fav_threads'
22 22 CONTEXT_POW_DIFFICULTY = 'pow_difficulty'
23 23 CONTEXT_NEW_POST_COUNT = 'new_post_count'
24 24 CONTEXT_BANNERS = 'banners'
25 25 CONTEXT_ONLY_FAVORITES = 'only_favorites'
26 26
27 27
28 28 def get_notifications(context, settings_manager):
29 29 usernames = settings_manager.get_notification_usernames()
30 fav_tags = settings_manager.get_fav_tags()
30 31 new_notifications_count = 0
31 if usernames:
32 if usernames or fav_tags:
32 33 last_notification_id = settings_manager.get_setting(
33 34 SETTING_LAST_NOTIFICATION_ID)
34 35
35 36 new_notifications_count = Notification.objects.get_notification_posts(
36 usernames=usernames, last=last_notification_id).only('id').count()
37 usernames=usernames, last=last_notification_id, fav_tags=fav_tags).only('id').count()
37 38 context[CONTEXT_NEW_NOTIFICATIONS_COUNT] = new_notifications_count
38 39 context[CONTEXT_USERNAMES] = usernames
39 40
40 41
41 42 def get_new_post_count(context, settings_manager):
42 43 last_posts = settings_manager.get_last_posts()
43 44 count = Thread.objects.get_new_post_count(last_posts)
44 45 if count > 0:
45 46 context[CONTEXT_NEW_POST_COUNT] = '(+{})'.format(count)
46 47
47 48
48 49 def user_and_ui_processor(request):
49 50 context = dict()
50 51
51 52 context[CONTEXT_PPD] = float(Post.objects.get_posts_per_day())
52 53
53 54 settings_manager = get_settings_manager(request)
54 55 fav_tags = settings_manager.get_fav_tags()
55 56
56 57 context[CONTEXT_TAGS_STR] = Tag.objects.get_tag_url_list(fav_tags)
57 58 theme = settings_manager.get_theme()
58 59 context[CONTEXT_THEME] = theme
59 60
60 61 # TODO Use static here
61 62 context[CONTEXT_THEME_CSS] = THEME_CSS.format(theme)
62 63
63 64 context[CONTEXT_VERSION] = settings.get(SECTION_VERSION, 'Version')
64 65 context[CONTEXT_SITE_NAME] = settings.get(SECTION_VERSION, 'SiteName')
65 66
66 67 if settings.get_bool(SECTION_FORMS, 'LimitFirstPosting'):
67 68 context[CONTEXT_POW_DIFFICULTY] = settings.get_int(SECTION_FORMS, 'PowDifficulty')
68 69
69 70 context[CONTEXT_IMAGE_VIEWER] = settings_manager.get_setting(
70 71 SETTING_IMAGE_VIEWER,
71 72 default=settings.get(SECTION_VIEW, 'DefaultImageViewer'))
72 73
73 74 context[CONTEXT_HAS_FAV_THREADS] =\
74 75 len(settings_manager.get_last_posts()) > 0
75 76
76 77 context[CONTEXT_BANNERS] = Banner.objects.order_by('-id')
77 78 context[CONTEXT_ONLY_FAVORITES] = settings_manager.get_setting(
78 79 SETTING_ONLY_FAVORITES, default=False)
79 80
80 81 get_notifications(context, settings_manager)
81 82 get_new_post_count(context, settings_manager)
82 83
83 84 return context
@@ -1,55 +1,56 b''
1 1 from django.db import models
2 from django.db.models import Q
2 3 import boards
3 4
4 5 __author__ = 'neko259'
5 6
6 7 BAN_REASON_AUTO = 'Auto'
7 8 BAN_REASON_MAX_LENGTH = 200
8 9
9 10 SESSION_KEY_MAX_LENGTH = 100
10 11
11 12
12 13 class Ban(models.Model):
13 14
14 15 class Meta:
15 16 app_label = 'boards'
16 17
17 18 ip = models.GenericIPAddressField()
18 19 reason = models.CharField(default=BAN_REASON_AUTO,
19 20 max_length=BAN_REASON_MAX_LENGTH)
20 21 can_read = models.BooleanField(default=True)
21 22
22 23 def __str__(self):
23 24 return self.ip
24 25
25 26
26 27 class NotificationManager(models.Manager):
27 def get_notification_posts(self, usernames: list, last: int = None):
28 def get_notification_posts(self, usernames: list, last: int = None, fav_tags=None):
28 29 lower_names = [username.lower() for username in usernames]
29 30 posts = boards.models.post.Post.objects.filter(
30 notification__name__in=lower_names).distinct()
31 Q(notification__name__in=lower_names) | Q(thread__tags__in=fav_tags)).distinct()
31 32 if last is not None:
32 33 posts = posts.filter(id__gt=last)
33 34 posts = posts.order_by('-id')
34 35
35 36 return posts
36 37
37 38
38 39 class Notification(models.Model):
39 40
40 41 class Meta:
41 42 app_label = 'boards'
42 43
43 44 objects = NotificationManager()
44 45
45 46 post = models.ForeignKey('Post', on_delete=models.CASCADE)
46 47 name = models.TextField()
47 48
48 49
49 50 class UserSettings(models.Model):
50 51 class Meta:
51 52 app_label = 'boards'
52 53
53 54 session_key = models.CharField(max_length=SESSION_KEY_MAX_LENGTH, unique=True)
54 55 fav_tags = models.ManyToManyField('Tag', related_name='settings_as_fav')
55 56 hidden_tags = models.ManyToManyField('Tag', related_name='settings_as_hidden')
@@ -1,104 +1,104 b''
1 1 {% load staticfiles %}
2 2 {% load i18n %}
3 3 {% load l10n %}
4 4 {% load static from staticfiles %}
5 5
6 6 <!DOCTYPE html>
7 7 <html>
8 8 <head>
9 9 <link rel="stylesheet" type="text/css" href="{% static 'css/base.css' %}" media="all"/>
10 10 <link rel="stylesheet" type="text/css" href="{% static 'css/3party/highlight.css' %}" media="all"/>
11 11 <link rel="stylesheet" type="text/css" href="{% static 'css/3party/jquery-ui.min.css' %}" media="all"/>
12 12 <link rel="stylesheet" type="text/css" href="{% static 'css/3party/jquery.contextMenu.min.css' %}" media="all"/>
13 13 <link rel="stylesheet" type="text/css" href="{% static theme_css %}" media="all"/>
14 14
15 15 {% if rss_url %}
16 16 <link rel="alternate" type="application/rss+xml" href="{{ rss_url|safe }}" title="{% trans 'Feed' %}"/>
17 17 {% endif %}
18 18
19 19 <link rel="icon" type="image/png"
20 20 href="{% static 'favicon.png' %}">
21 21
22 22 <meta name="viewport" content="width=device-width, initial-scale=1"/>
23 23 <meta charset="utf-8"/>
24 24
25 25 {% block head %}{% endblock %}
26 26 </head>
27 27 <body data-image-viewer="{{ image_viewer|safe }}"
28 28 data-pow-difficulty="{{ pow_difficulty|safe }}"
29 29 data-update-script="{% static 'js/updates.js' %}">
30 30 <script src="{% static 'js/jquery-2.2.0.min.js' %}"></script>
31 31 <script>
32 32 var PERMS = {
33 33 'change_post': '{{ perms.boards.change_post }}' === 'True',
34 34 'delete_post': '{{ perms.boards.delete_post }}' === 'True',
35 35 'change_thread': '{{ perms.boards.change_thread }}' === 'True',
36 36 'delete_thread': '{{ perms.boards.delete_thread }}' === 'True'
37 37 }
38 38 </script>
39 39
40 40 <header class="navigation_panel">
41 41 <a class="link" href="{% url 'landing' %}">{{ site_name|safe }}</a>
42 42 <a href="{% url 'index' %}" title="{% trans "All threads" %}">~~~</a>,
43 43 {% if tags_str %}
44 44 <form action="{% url 'index' %}" method="post" class="post-button-form">{% csrf_token %}
45 45 {% if only_favorites %}
46 46 <button name="method" value="toggle_fav" class="fav">β˜…</button>,
47 47 {% else %}
48 48 <button name="method" value="toggle_fav" class="not_fav">β˜…</button>,
49 49 {% endif %}
50 50 </form>
51 51 {{ tags_str|safe }},
52 52 {% endif %}
53 53 <a href="{% url 'search' %}" title="{% trans 'Search' %}">{% trans 'search' %}</a>,
54 54 <a href="{% url 'feed' %}" title="{% trans 'Feed' %}">{% trans 'feed' %}</a>,
55 55 <a href="{% url 'random' %}" title="{% trans 'Random images' %}">{% trans 'images' %}</a>{% if has_fav_threads %},
56 56
57 57 <a href="{% url 'feed' %}?favorites" id="fav-panel-btn">{% trans 'favorites' %} <span id="new-fav-post-count" {% if not new_post_count %}style="display: none" {% endif %}>{{ new_post_count|safe }}</span></a>
58 58 {% endif %}
59 59
60 {% if usernames %}
60 {% if usernames or tags_str %}
61 61 <a class="right-link link" href="{% url 'notifications' %}" title="{% trans 'Notifications' %}">
62 62 {% trans 'Notifications' %}
63 63 {% ifnotequal new_notifications_count 0 %}
64 64 (<b>{{ new_notifications_count|safe }}</b>)
65 65 {% endifnotequal %}
66 66 </a>
67 67 {% endif %}
68 68
69 69 <a class="right-link link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
70 70 </header>
71 71
72 72 <div id="fav-panel"><div class="post">{% trans "Loading..." %}</div></div>
73 73
74 74 <script src="{% static 'js/3party/jquery-ui.min.js' %}"></script>
75 75 <script src="{% static 'js/3party/jquery.contextMenu.min.js' %}"></script>
76 76
77 77 {% block content %}{% endblock %}
78 78
79 79 <script src="{% static 'js/jquery.mousewheel.js' %}"></script>
80 80 <script src="{% static 'js/3party/highlight.min.js' %}"></script>
81 81
82 82 <script src="{% url 'js_info_dict' %}"></script>
83 83
84 84 <script src="{% static 'js/popup.js' %}"></script>
85 85 <script src="{% static 'js/image.js' %}"></script>
86 86 <script src="{% static 'js/refpopup.js' %}"></script>
87 87 <script src="{% static 'js/main.js' %}"></script>
88 88
89 89 <footer class="navigation_panel">
90 90 <b><a href="{% url "authors" %}">{{ site_name|safe }}</a> {{ version|safe }}</b>
91 91 {% block metapanel %}{% endblock %}
92 92 {% if rss_url %}
93 93 [<a href="{{ rss_url|safe }}">RSS</a>]
94 94 {% endif %}
95 95 [<a href="{% url 'admin:index' %}">{% trans 'Admin' %}</a>]
96 96 [<a href="{% url 'index' %}?order=pub">{% trans 'New threads' %}</a>]
97 97 {% with ppd=posts_per_day|floatformat:2 %}
98 98 {% blocktrans %}Speed: {{ ppd }} posts per day{% endblocktrans %}
99 99 {% endwith %}
100 100 <a class="link" href="#top" id="up">{% trans 'Up' %}</a>
101 101 </footer>
102 102
103 103 </body>
104 104 </html>
@@ -1,48 +1,50 b''
1 1 from django.shortcuts import render
2 2
3 3 from boards.abstracts.constants import PARAM_PAGE
4 4 from boards.abstracts.paginator import get_paginator
5 5 from boards.abstracts.settingsmanager import get_settings_manager, \
6 6 SETTING_LAST_NOTIFICATION_ID
7 7 from boards.models.user import Notification
8 8 from boards.views.base import BaseBoardView
9 9
10 10 DEFAULT_PAGE = '1'
11 11
12 12 TEMPLATE = 'boards/notifications.html'
13 13 PARAM_USERNAMES = 'notification_usernames'
14 14 RESULTS_PER_PAGE = 10
15 15
16 16
17 17 class NotificationView(BaseBoardView):
18 18
19 19 def get(self, request, username=None):
20 20 params = self.get_context_data()
21 21
22 22 settings_manager = get_settings_manager(request)
23 23
24 24 # If we open our notifications, reset the "new" count
25 25 if username is None:
26 26 notification_usernames = settings_manager.get_notification_usernames()
27 27 else:
28 28 notification_usernames = [username]
29 29
30 fav_tags = settings_manager.get_fav_tags()
31
30 32 posts = Notification.objects.get_notification_posts(
31 usernames=notification_usernames)
33 usernames=notification_usernames, fav_tags=fav_tags)
32 34
33 35 if username is None:
34 36 last = posts.first()
35 37 if last is not None:
36 38 last_id = last.id
37 39 settings_manager.set_setting(SETTING_LAST_NOTIFICATION_ID,
38 40 last_id)
39 41
40 42
41 43 paginator = get_paginator(posts, RESULTS_PER_PAGE)
42 44
43 45 page = int(request.GET.get(PARAM_PAGE, DEFAULT_PAGE))
44 46
45 47 params[PARAM_PAGE] = paginator.page(page)
46 48 params[PARAM_USERNAMES] = notification_usernames
47 49
48 50 return render(request, TEMPLATE, params)
General Comments 0
You need to be logged in to leave comments. Login now