Skip to content

Commit

Permalink
Notifications: allow dismiss user's notifications (#11130)
Browse files Browse the repository at this point in the history
* Notifications: move logic to self link to the model

* Notifications: allow dismiss user's notifications

* Reuse the template
  • Loading branch information
humitos committed Feb 21, 2024
1 parent e7849c7 commit eab2500
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 78 deletions.
45 changes: 1 addition & 44 deletions readthedocs/api/v3/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,50 +66,7 @@ class NotificationLinksSerializer(BaseLinksSerializer):
_self = serializers.SerializerMethodField()

def get__self(self, obj):
content_type_name = obj.attached_to_content_type.name
if content_type_name == "user":
url = "users-notifications-detail"
path = reverse(
url,
kwargs={
"notification_pk": obj.pk,
"parent_lookup_user__username": obj.attached_to.username,
},
)

elif content_type_name == "build":
url = "projects-builds-notifications-detail"
project_slug = obj.attached_to.project.slug
path = reverse(
url,
kwargs={
"notification_pk": obj.pk,
"parent_lookup_project__slug": project_slug,
"parent_lookup_build__id": obj.attached_to_id,
},
)

elif content_type_name == "project":
url = "projects-notifications-detail"
project_slug = obj.attached_to.slug
path = reverse(
url,
kwargs={
"notification_pk": obj.pk,
"parent_lookup_project__slug": project_slug,
},
)

elif content_type_name == "organization":
url = "organizations-notifications-detail"
path = reverse(
url,
kwargs={
"notification_pk": obj.pk,
"parent_lookup_organization__slug": obj.attached_to.slug,
},
)

path = obj.get_absolute_url()
return self._absolute_url(path)


Expand Down
18 changes: 14 additions & 4 deletions readthedocs/core/static-src/core/js/site.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
/* Site-specific javascript */

// Notifications that can both dismiss and point to a separate URL
// Dismiss a notification
module.exports.handle_notification_dismiss = function () {
$(document).ready(function () {
$('ul.notifications li.notification > a').click(function (ev) {
var url = $(this).attr('href');
var dismiss_url = $(this).parent().attr('data-dismiss-url');
var csrf_token = $(this).parent().attr('data-csrf-token');
if (dismiss_url) {
ev.preventDefault();
$.get(dismiss_url, function (data, text_status, xhr) {
window.location.href = url;
$.ajax({
type: "PATCH",
url: dismiss_url,
data: {
state: "dismissed",
},
headers: {
"X-CSRFToken": csrf_token,
},
}).then((data) => {
$(this).parent().hide();
});
}
else {
$(this).hide();
$(this).parent().hide();
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion readthedocs/core/static/core/js/site.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions readthedocs/notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_noop as _
from django_extensions.db.models import TimeStampedModel

Expand Down Expand Up @@ -95,3 +96,49 @@ def get_message(self):
)

return message

def get_absolute_url(self):
content_type_name = self.attached_to_content_type.name
if content_type_name == "user":
url = "users-notifications-detail"
path = reverse(
url,
kwargs={
"notification_pk": self.pk,
"parent_lookup_user__username": self.attached_to.username,
},
)

elif content_type_name == "build":
url = "projects-builds-notifications-detail"
project_slug = self.attached_to.project.slug
path = reverse(
url,
kwargs={
"notification_pk": self.pk,
"parent_lookup_project__slug": project_slug,
"parent_lookup_build__id": self.attached_to_id,
},
)

elif content_type_name == "project":
url = "projects-notifications-detail"
project_slug = self.attached_to.slug
path = reverse(
url,
kwargs={
"notification_pk": self.pk,
"parent_lookup_project__slug": project_slug,
},
)

elif content_type_name == "organization":
url = "organizations-notifications-detail"
path = reverse(
url,
kwargs={
"notification_pk": self.pk,
"parent_lookup_organization__slug": self.attached_to.slug,
},
)
return path
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@
{% block organization-bar-details %}active{% endblock %}

{% block content %}
{% if notifications %}
<ul class="notifications">
{% for notification in notifications %}
<li class="notification">
{{ notification.get_message.get_rendered_body|safe }}
</li>
{% endfor %}
</ul>
{% endif %}
{% include "core/notifications.html" with notifications=notifications %}

<div class="col-major organization-major">
<div class="module organization organization-detail">
Expand Down
10 changes: 1 addition & 9 deletions readthedocs/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,7 @@
We need to use a CustomUser to have access to "user.notifications"
See https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-AUTH_USER_MODEL
{% endcomment %}
{% if user_notifications %}
<ul class="notifications">
{% for notification in user_notifications %}
<li class="notification">
{{ notification.get_message.get_rendered_body|safe }}
</li>
{% endfor %}
</ul>
{% endif %}
{% include "core/notifications.html" with notifications=user_notifications %}

<!-- BEGIN notify -->
{% block notify %}
Expand Down
20 changes: 20 additions & 0 deletions readthedocs/templates/core/notifications.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% load i18n %}

{% if notifications %}
<ul class="notifications">
{% for notification in notifications %}
<li class="notification"
{% if notification.dismissable%}
data-dismiss-url="{{ notification.get_absolute_url }}"
data-csrf-token="{{ csrf_token }}"
{% endif %}>
{% if notification.dismissable %}
<a class="notification-action" href="#">
<span class="icon close" aria-label="{% trans 'Close notification' %}"></span>
</a>
{% endif %}
{{ notification.get_message.get_rendered_body|safe }}
</li>
{% endfor %}
</ul>
{% endif %}
11 changes: 0 additions & 11 deletions readthedocs/templates/core/project_bar_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ <h1>

<div class="options">

{% comment %}
All projects with "skip=True" needs to be attached a notification using the new system.
This notification will be shown here using the same style we used before.
{% endcomment %}

{% for notification in notifications %}
<p class="build-failure">
{{ notification.get_message.get_rendered_body|safe }}
</p>
{% endfor %}

<ul>
<li class="{{ overview_active }}"><a href="{{ project.get_absolute_url }}">{% trans "Overview" %}</a></li>

Expand Down
1 change: 1 addition & 0 deletions readthedocs/templates/projects/project_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
{% endblock %}

{% block content %}
{% include "core/notifications.html" with notifications=notifications %}
{% include "core/project_details.html" %}
{% endblock %}

0 comments on commit eab2500

Please sign in to comment.