diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py index 63bdbf7db..a8dc40bf0 100644 --- a/netbox/extras/choices.py +++ b/netbox/extras/choices.py @@ -79,6 +79,21 @@ class CustomLinkButtonClassChoices(ButtonColorChoices): (LINK, 'Link'), ) + +# +# Bookmarks +# + +class BookmarkOrderingChoices(ChoiceSet): + + ORDERING_NEWEST = '-created' + ORDERING_OLDEST = 'created' + + CHOICES = ( + (ORDERING_NEWEST, 'Newest'), + (ORDERING_OLDEST, 'Oldest'), + ) + # # ObjectChanges # @@ -98,7 +113,7 @@ class ObjectChangeActionChoices(ChoiceSet): # -# Jounral entries +# Journal entries # class JournalEntryKindChoices(ChoiceSet): diff --git a/netbox/extras/dashboard/widgets.py b/netbox/extras/dashboard/widgets.py index b3a4d090c..3b9ce6c46 100644 --- a/netbox/extras/dashboard/widgets.py +++ b/netbox/extras/dashboard/widgets.py @@ -15,6 +15,7 @@ from django.template.loader import render_to_string from django.urls import NoReverseMatch, resolve, reverse from django.utils.translation import gettext as _ +from extras.choices import BookmarkOrderingChoices from extras.utils import FeatureQuery from utilities.forms import BootstrapMixin from utilities.permissions import get_permission_for_model @@ -23,6 +24,7 @@ from utilities.utils import content_type_identifier, content_type_name, get_view from .utils import register_widget __all__ = ( + 'BookmarksWidget', 'DashboardWidget', 'NoteWidget', 'ObjectCountsWidget', @@ -318,3 +320,42 @@ class RSSFeedWidget(DashboardWidget): return { 'feed': feed, } + + +@register_widget +class BookmarksWidget(DashboardWidget): + default_title = _('Bookmarks') + default_config = { + 'order_by': BookmarkOrderingChoices.ORDERING_NEWEST, + } + description = _('Show your personal bookmarks') + template_name = 'extras/dashboard/widgets/bookmarks.html' + + class ConfigForm(WidgetConfigForm): + object_types = forms.MultipleChoiceField( + # TODO: Restrict the choices by FeatureQuery('bookmarks') + choices=get_content_type_labels, + required=False + ) + order_by = forms.ChoiceField( + choices=BookmarkOrderingChoices + ) + max_items = forms.IntegerField( + min_value=1, + required=False + ) + + def render(self, request): + from extras.models import Bookmark + + bookmarks = Bookmark.objects.filter(user=request.user).order_by(self.config['order_by']) + if object_types := self.config.get('object_types'): + models = get_models_from_content_types(object_types) + conent_types = ContentType.objects.get_for_models(*models).values() + bookmarks = bookmarks.filter(object_type__in=conent_types) + if max_items := self.config.get('max_items'): + bookmarks = bookmarks[:max_items] + + return render_to_string(self.template_name, { + 'bookmarks': bookmarks, + }) diff --git a/netbox/templates/extras/dashboard/widgets/bookmarks.html b/netbox/templates/extras/dashboard/widgets/bookmarks.html new file mode 100644 index 000000000..2189cc55f --- /dev/null +++ b/netbox/templates/extras/dashboard/widgets/bookmarks.html @@ -0,0 +1,9 @@ +{% if bookmarks %} +