diff --git a/netbox/core/tables/__init__.py b/netbox/core/tables/__init__.py index de6a07c52..cec7342f9 100644 --- a/netbox/core/tables/__init__.py +++ b/netbox/core/tables/__init__.py @@ -4,4 +4,3 @@ from .data import * from .jobs import * from .tasks import * from .plugins import * -from .plugin import * diff --git a/netbox/core/tables/plugin.py b/netbox/core/tables/plugin.py deleted file mode 100644 index 054ceba01..000000000 --- a/netbox/core/tables/plugin.py +++ /dev/null @@ -1,40 +0,0 @@ -from datetime import datetime -from django.contrib.humanize.templatetags.humanize import naturalday -import django_tables2 as tables -from django.utils.translation import gettext_lazy as _ -from netbox.tables import BaseTable - -__all__ = ( - 'CertifiedPluginTable', -) - - -class CertifiedPluginTable(BaseTable): - version = tables.Column( - verbose_name=_('Version') - ) - last_updated = tables.Column( - accessor=tables.A('date'), - verbose_name=_('Last Updated') - ) - min_version = tables.Column( - accessor=tables.A('netbox_min_version'), - verbose_name=_('Minimum NetBox Version') - ) - max_version = tables.Column( - accessor=tables.A('netbox_max_version'), - verbose_name=_('Maximum NetBox Version') - ) - - class Meta(BaseTable.Meta): - empty_text = _('No plugin data found') - fields = ( - 'version', 'last_updated', 'min_version', 'max_version', - ) - default_columns = ( - 'version', 'last_updated', 'min_version', 'max_version', - ) - orderable = False - - def render_last_updated(self, value, record): - return naturalday(datetime.fromisoformat(value)) diff --git a/netbox/core/tables/plugins.py b/netbox/core/tables/plugins.py index 21e90cd6b..760b6c809 100644 --- a/netbox/core/tables/plugins.py +++ b/netbox/core/tables/plugins.py @@ -1,13 +1,17 @@ +from datetime import datetime import django_tables2 as tables +from django.contrib.humanize.templatetags.humanize import naturalday from django.utils.translation import gettext_lazy as _ from netbox.tables import BaseTable __all__ = ( - 'PluginTable', + 'CertifiedPluginTable', + 'InstalledPluginTable', + 'PluginVersionTable', ) -class PluginTable(BaseTable): +class InstalledPluginTable(BaseTable): name = tables.Column( accessor=tables.A('verbose_name'), verbose_name=_('Name') @@ -37,3 +41,71 @@ class PluginTable(BaseTable): default_columns = ( 'name', 'version', 'package', 'description', ) + + +class PluginVersionTable(BaseTable): + version = tables.Column( + verbose_name=_('Version') + ) + last_updated = tables.Column( + accessor=tables.A('date'), + verbose_name=_('Last Updated') + ) + min_version = tables.Column( + accessor=tables.A('netbox_min_version'), + verbose_name=_('Minimum NetBox Version') + ) + max_version = tables.Column( + accessor=tables.A('netbox_max_version'), + verbose_name=_('Maximum NetBox Version') + ) + + class Meta(BaseTable.Meta): + empty_text = _('No plugin data found') + fields = ( + 'version', 'last_updated', 'min_version', 'max_version', + ) + default_columns = ( + 'version', 'last_updated', 'min_version', 'max_version', + ) + orderable = False + + def render_last_updated(self, value, record): + return naturalday(datetime.fromisoformat(value)) + + +class CertifiedPluginTable(BaseTable): + name = tables.Column( + linkify=('core:plugin', [tables.A('slug')]), + verbose_name=_('Name') + ) + status = tables.Column( + verbose_name=_('Status') + ) + author = tables.Column( + verbose_name=_('Author') + ) + is_local = tables.BooleanColumn( + verbose_name=_('Local') + ) + is_installed = tables.BooleanColumn( + verbose_name=_('Installed') + ) + is_certified = tables.BooleanColumn( + verbose_name=_('Certified') + ) + created = tables.Column( + verbose_name=_('Published') + ) + updated = tables.Column( + verbose_name=_('Updated') + ) + + class Meta(BaseTable.Meta): + empty_text = _('No plugin data found') + fields = ( + 'name', 'status', 'author', 'is_local', 'is_installed', 'is_certified', 'created', 'updated', + ) + default_columns = ( + 'name', 'status', 'author', 'is_local', 'is_installed', 'is_certified', 'created', 'updated', + ) diff --git a/netbox/core/views.py b/netbox/core/views.py index a048bd560..766f6e5e6 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -41,7 +41,7 @@ from utilities.views import ContentTypePermissionRequiredMixin, GetRelatedModels from . import filtersets, forms, tables from .choices import PluginSortChoices, PluginStatusChoices from .models import * -from .tables import CertifiedPluginTable +from .tables import CertifiedPluginTable, PluginVersionTable # @@ -648,7 +648,7 @@ class SystemView(UserPassesTestMixin, View): response['Content-Disposition'] = 'attachment; filename="netbox.json"' return response - plugins_table = tables.PluginTable(plugins, orderable=False) + plugins_table = tables.InstalledPluginTable(plugins, orderable=False) plugins_table.configure(request) return render(request, 'core/system.html', { @@ -675,8 +675,8 @@ def get_local_plugins(plugins): 'tag_line': plugin_config.description, 'description_short': plugin_config.description, 'author': plugin_config.author or _('Unknown Author'), - 'created': datetime.min.replace(tzinfo=timezone.utc), - 'updated': datetime.min.replace(tzinfo=timezone.utc), + 'created': None, + 'updated': None, 'is_local': True, 'is_installed': True, 'is_certified': False, @@ -768,8 +768,8 @@ def get_catalog_plugins(plugins): def get_plugins(): - if plugins := cache.get('plugins-catalog-feed'): - return plugins + # if plugins := cache.get('plugins-catalog-feed'): + # return plugins plugins = {} plugins = get_local_plugins(plugins) @@ -785,30 +785,22 @@ class PluginListView(UserPassesTestMixin, View): return self.request.user.is_staff def get(self, request): - sort = request.GET.get('sort', PluginSortChoices.SORT_NAME_AZ) - status = request.GET.get('status', PluginStatusChoices.STATUS_ALL) q = request.GET.get('q', None) plugins = get_plugins() - if status == PluginStatusChoices.STATUS_INSTALLED: - plugins = [v for k, v in plugins.items() if v['is_installed']] - else: - plugins = [v for k, v in plugins.items()] - if sort == PluginSortChoices.SORT_NAME_ZA: - plugins = sorted(plugins, key=lambda d: d['name'], reverse=True) - elif sort == PluginSortChoices.SORT_UPDATED: - plugins = sorted(plugins, key=lambda d: d['updated']) - elif sort == PluginSortChoices.SORT_PUBLISHED: - plugins = sorted(plugins, key=lambda d: d['created']) - else: - plugins = sorted(plugins, key=lambda d: d['name']) + plugins = [v for k, v in plugins.items()] + + table = CertifiedPluginTable(plugins, user=request.user) + table.configure(request) + + # If this is an HTMX request, return only the rendered table HTML + if htmx_partial(request): + return render(request, 'htmx/table.html', { + 'table': table, + }) return render(request, 'core/plugin_list.html', { - 'plugins': plugins, - 'sort_choices': dict(PluginSortChoices), - 'status_choices': dict(PluginStatusChoices), - 'sort': sort, - 'status': status, + 'table': table, }) @@ -822,7 +814,7 @@ class PluginView(UserPassesTestMixin, View): plugins = get_plugins() plugin = plugins[name] - table = CertifiedPluginTable(plugin['versions'], user=request.user) + table = PluginVersionTable(plugin['versions'], user=request.user) table.configure(request) return render(request, 'core/plugin.html', { diff --git a/netbox/templates/core/htmx/plugins.html b/netbox/templates/core/htmx/plugins.html index 6a1b2f8c7..da0fe1dad 100644 --- a/netbox/templates/core/htmx/plugins.html +++ b/netbox/templates/core/htmx/plugins.html @@ -2,41 +2,8 @@ {% load helpers %} {% load i18n %} - {% for plugin in plugins %} -
- -
-
-
{{ plugin.name }}
-

By {{ plugin.author }}

-
- {% if plugin.is_local %} - - {% endif %} - {% if plugin.is_certified %} - - {% endif %} - {% if plugin.is_community %} - - {% endif %} - {% if plugin.is_installed %} - - {% endif %} -
-
-
-
+
+
+ {% include 'htmx/table.html' %}
- {% endfor %} +
diff --git a/netbox/templates/core/plugin_list.html b/netbox/templates/core/plugin_list.html index a16da09ee..a8c29507d 100644 --- a/netbox/templates/core/plugin_list.html +++ b/netbox/templates/core/plugin_list.html @@ -31,51 +31,6 @@
-
- -
-
-
- {% trans "Status" %} - -
-
- -
-
- {% trans "Sort" %} - -
-
- -
- -
- {# System status #}