mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-09 00:58:16 -06:00
Separate read & dimiss actions
This commit is contained in:
parent
a21d4fecbc
commit
9c875716f7
@ -78,7 +78,13 @@ class Notification(models.Model):
|
|||||||
return super().__str__()
|
return super().__str__()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return self.object.get_absolute_url()
|
return reverse('extras:notifications')
|
||||||
|
|
||||||
|
def get_read_url(self):
|
||||||
|
return reverse('extras:notification_read', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
|
def get_dismiss_url(self):
|
||||||
|
return reverse('extras:notification_dismiss', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
super().clean()
|
||||||
|
@ -266,14 +266,35 @@ class BookmarkTable(NetBoxTable):
|
|||||||
default_columns = ('object', 'object_type', 'created')
|
default_columns = ('object', 'object_type', 'created')
|
||||||
|
|
||||||
|
|
||||||
class NotificationTable(NetBoxTable):
|
class SubscriptionTable(NetBoxTable):
|
||||||
object_type = columns.ContentTypeColumn(
|
object_type = columns.ContentTypeColumn(
|
||||||
verbose_name=_('Object Types'),
|
verbose_name=_('Object Type'),
|
||||||
)
|
)
|
||||||
object = tables.Column(
|
object = tables.Column(
|
||||||
verbose_name=_('Object'),
|
verbose_name=_('Object'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
actions = columns.ActionsColumn(
|
||||||
|
actions=('delete',)
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta(NetBoxTable.Meta):
|
||||||
|
model = Subscription
|
||||||
|
fields = ('pk', 'object', 'object_type', 'created')
|
||||||
|
default_columns = ('object', 'object_type', 'created')
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationTable(NetBoxTable):
|
||||||
|
object_type = columns.ContentTypeColumn(
|
||||||
|
verbose_name=_('Object Type'),
|
||||||
|
)
|
||||||
|
object = tables.Column(
|
||||||
|
verbose_name=_('Object'),
|
||||||
|
linkify={
|
||||||
|
'viewname': 'extras:notification_read',
|
||||||
|
'args': [tables.A('pk')],
|
||||||
|
}
|
||||||
|
)
|
||||||
created = columns.DateTimeColumn(
|
created = columns.DateTimeColumn(
|
||||||
timespec='minutes',
|
timespec='minutes',
|
||||||
verbose_name=_('Created'),
|
verbose_name=_('Created'),
|
||||||
@ -290,6 +311,9 @@ class NotificationTable(NetBoxTable):
|
|||||||
model = Notification
|
model = Notification
|
||||||
fields = ('pk', 'object', 'object_type', 'created', 'read')
|
fields = ('pk', 'object', 'object_type', 'created', 'read')
|
||||||
default_columns = ('object', 'object_type', 'created', 'read')
|
default_columns = ('object', 'object_type', 'created', 'read')
|
||||||
|
row_attrs = {
|
||||||
|
'data-unread': lambda record: not record.read,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class NotificationGroupTable(NetBoxTable):
|
class NotificationGroupTable(NetBoxTable):
|
||||||
@ -304,24 +328,6 @@ class NotificationGroupTable(NetBoxTable):
|
|||||||
default_columns = ('name', 'description')
|
default_columns = ('name', 'description')
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionTable(NetBoxTable):
|
|
||||||
object_type = columns.ContentTypeColumn(
|
|
||||||
verbose_name=_('Object Types'),
|
|
||||||
)
|
|
||||||
object = tables.Column(
|
|
||||||
verbose_name=_('Object'),
|
|
||||||
linkify=True
|
|
||||||
)
|
|
||||||
actions = columns.ActionsColumn(
|
|
||||||
actions=('delete',)
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta(NetBoxTable.Meta):
|
|
||||||
model = Subscription
|
|
||||||
fields = ('pk', 'object', 'object_type', 'created')
|
|
||||||
default_columns = ('object', 'object_type', 'created')
|
|
||||||
|
|
||||||
|
|
||||||
class WebhookTable(NetBoxTable):
|
class WebhookTable(NetBoxTable):
|
||||||
name = tables.Column(
|
name = tables.Column(
|
||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
|
@ -428,9 +428,24 @@ class NotificationsView(LoginRequiredMixin, View):
|
|||||||
|
|
||||||
@register_model_view(Notification, 'read')
|
@register_model_view(Notification, 'read')
|
||||||
class NotificationReadView(LoginRequiredMixin, View):
|
class NotificationReadView(LoginRequiredMixin, View):
|
||||||
|
"""
|
||||||
|
Mark the Notification read and redirect the user to its attached object.
|
||||||
|
"""
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
request.user.notifications.filter(pk=pk).update(read=timezone.now())
|
notification = get_object_or_404(Notification, pk=pk)
|
||||||
|
notification.read = timezone.now()
|
||||||
|
notification.save()
|
||||||
|
|
||||||
|
return redirect(notification.object.get_absolute_url())
|
||||||
|
|
||||||
|
|
||||||
|
@register_model_view(Notification, 'dismiss')
|
||||||
|
class NotificationDismissView(LoginRequiredMixin, View):
|
||||||
|
"""
|
||||||
|
A convenience view which allows deleting notifications with one click.
|
||||||
|
"""
|
||||||
|
def get(self, request, pk):
|
||||||
|
request.user.notifications.filter(pk=pk).delete()
|
||||||
|
|
||||||
notifications = request.user.notifications.unread()[:10]
|
notifications = request.user.notifications.unread()[:10]
|
||||||
return render(request, 'htmx/notifications.html', {
|
return render(request, 'htmx/notifications.html', {
|
||||||
|
BIN
netbox/project-static/dist/netbox.css
vendored
BIN
netbox/project-static/dist/netbox.css
vendored
Binary file not shown.
8
netbox/project-static/styles/custom/_notifications.scss
Normal file
8
netbox/project-static/styles/custom/_notifications.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@use 'sass:map';
|
||||||
|
|
||||||
|
// Highlight unread notifications
|
||||||
|
tr[data-unread=True] {
|
||||||
|
td {
|
||||||
|
background-color: rgba(map.get($theme-colors, "green"), 0.15);
|
||||||
|
}
|
||||||
|
}
|
@ -24,3 +24,4 @@
|
|||||||
@import 'custom/interfaces';
|
@import 'custom/interfaces';
|
||||||
@import 'custom/markdown';
|
@import 'custom/markdown';
|
||||||
@import 'custom/misc';
|
@import 'custom/misc';
|
||||||
|
@import 'custom/notifications';
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
<div class="list-group-item p-2">
|
<div class="list-group-item p-2">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col text-truncate">
|
<div class="col text-truncate">
|
||||||
<a href="{{ notification.get_absolute_url }}" class="text-body d-block">{{ notification.object }}</a>
|
<a href="{{ notification.get_read_url }}" class="text-body d-block">{{ notification.object }}</a>
|
||||||
<div class="d-block text-secondary fs-5">{{ notification.get_event_display }} {{ notification.created|timesince }} {% trans "ago" %}</div>
|
<div class="d-block text-secondary fs-5">{{ notification.get_event_display }} {{ notification.created|timesince }} {% trans "ago" %}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<a href="#" hx-get="{% url 'extras:notification_read' pk=notification.pk %}" hx-target="closest .notifications" class="list-group-item-actions text-secondary" title="{% trans "Mark read" %}">
|
<a href="#" hx-get="{{ notification.get_dismiss_url }}" hx-target="closest .notifications" class="list-group-item-actions text-secondary" title="{% trans "Dismiss" %}">
|
||||||
<i class="mdi mdi-close"></i>
|
<i class="mdi mdi-close"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user