diff --git a/netbox/core/tables/plugins.py b/netbox/core/tables/plugins.py index 7ca3c5415..04f7e6219 100644 --- a/netbox/core/tables/plugins.py +++ b/netbox/core/tables/plugins.py @@ -5,44 +5,11 @@ from django.utils.translation import gettext_lazy as _ from netbox.tables import BaseTable __all__ = ( - 'CertifiedPluginTable', - 'InstalledPluginTable', + 'CatalogPluginTable', 'PluginVersionTable', ) -class InstalledPluginTable(BaseTable): - name = tables.Column( - accessor=tables.A('verbose_name'), - verbose_name=_('Name') - ) - version = tables.Column( - verbose_name=_('Version') - ) - package = tables.Column( - accessor=tables.A('name'), - verbose_name=_('Package') - ) - author = tables.Column( - verbose_name=_('Author') - ) - author_email = tables.Column( - verbose_name=_('Author Email') - ) - description = tables.Column( - verbose_name=_('Description') - ) - - class Meta(BaseTable.Meta): - empty_text = _('No plugins found') - fields = ( - 'name', 'version', 'package', 'author', 'author_email', 'description', - ) - default_columns = ( - 'name', 'version', 'package', 'description', - ) - - class PluginVersionTable(BaseTable): version = tables.Column( verbose_name=_('Version') @@ -71,10 +38,10 @@ class PluginVersionTable(BaseTable): orderable = False def render_last_updated(self, value, record): - return naturalday(datetime.fromisoformat(value)) + return naturalday(value) -class CertifiedPluginTable(BaseTable): +class CatalogPluginTable(BaseTable): name = tables.Column( linkify=('core:plugin', [tables.A('slug')]), verbose_name=_('Name') diff --git a/netbox/core/views.py b/netbox/core/views.py index a0dde87a9..88bdb199b 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -1,9 +1,11 @@ +import datetime import importlib import importlib.util import json import platform import requests +from dataclasses import dataclass, field from django import __version__ as DJANGO_VERSION from django.apps import apps from django.conf import settings @@ -41,7 +43,7 @@ from utilities.query import count_related from utilities.views import ContentTypePermissionRequiredMixin, GetRelatedModelsMixin, register_model_view from . import filtersets, forms, tables from .models import * -from .tables import CertifiedPluginTable, PluginVersionTable +from .tables import CatalogPluginTable, PluginVersionTable # @@ -648,12 +650,8 @@ class SystemView(UserPassesTestMixin, View): response['Content-Disposition'] = 'attachment; filename="netbox.json"' return response - plugins_table = tables.InstalledPluginTable(plugins, orderable=False) - plugins_table.configure(request) - return render(request, 'core/system.html', { 'stats': stats, - 'plugins_table': plugins_table, 'config': config, }) @@ -662,6 +660,36 @@ class SystemView(UserPassesTestMixin, View): # Plugins # +@dataclass +class PluginVersion: + date: datetime.datetime = None + version: str = '' + netbox_min_version: str = '' + netbox_max_version: str = '' + has_model: bool = False + is_certified: bool = False + is_feature: bool = False + is_integration: bool = False + is_netboxlabs_supported: bool = False + + +@dataclass +class Plugin: + slug: str = '' + config_name: str = '' + name: str = '' + tag_line: str = '' + description_short: str = '' + author: str = '' + created: datetime.datetime = None + updated: datetime.datetime = None + is_local: bool = False + is_installed: bool = False + is_certified: bool = False + is_community: bool = False + versions: list[PluginVersion] = field(default_factory=list) + + def get_local_plugins(plugins): for plugin_name in settings.PLUGINS: plugin = importlib.import_module(plugin_name) @@ -692,7 +720,8 @@ def get_catalog_plugins(plugins): session = requests.Session() def get_pages(): - payload = {'page': '1', 'per_page': '25'} + # TODO: pagintation is curently broken in API + payload = {'page': '1', 'per_page': '50'} first_page = session.get(url, params=payload).json() yield first_page num_pages = first_page['metadata']['pagination']['last_page'] @@ -706,7 +735,6 @@ def get_catalog_plugins(plugins): for data in page['data']: versions = [] - versions.append(data['release_latest']) versions.extend(data['release_recent_history']) if data['slug'] in plugins: plugins[data['slug']]['is_local'] = False @@ -748,7 +776,7 @@ def get_plugins(): class PluginListView(UserPassesTestMixin, View): def test_func(self): - return self.request.user.is_staff + return self.request.user.is_superuser def get(self, request): q = request.GET.get('q', None) @@ -757,9 +785,9 @@ class PluginListView(UserPassesTestMixin, View): if q: plugins = [v for k, v in plugins.items() if q.casefold() in v['name'].casefold()] else: - plugins = [v for k, v in plugins.items()] + plugins = plugins.values() - table = CertifiedPluginTable(plugins, user=request.user) + table = CatalogPluginTable(plugins, user=request.user) table.configure(request) # If this is an HTMX request, return only the rendered table HTML diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py index 6ff6aaa35..3ba5b7078 100644 --- a/netbox/netbox/navigation/menu.py +++ b/netbox/netbox/navigation/menu.py @@ -431,13 +431,13 @@ ADMIN_MENU = Menu( label=_('System'), items=( MenuItem( - link='core:plugin_list', - link_text=_('Plugins'), + link='core:system', + link_text=_('System'), auth_required=True ), MenuItem( - link='core:system', - link_text=_('System'), + link='core:plugin_list', + link_text=_('Plugins'), auth_required=True ), MenuItem( diff --git a/netbox/templates/core/plugin.html b/netbox/templates/core/plugin.html index 4841ea196..de7060394 100644 --- a/netbox/templates/core/plugin.html +++ b/netbox/templates/core/plugin.html @@ -50,7 +50,6 @@ From {% block content %} - {# Component creation form #}
{{ plugin.description_short }}
diff --git a/netbox/templates/core/system.html b/netbox/templates/core/system.html index 6f88643a0..5a7088e96 100644 --- a/netbox/templates/core/system.html +++ b/netbox/templates/core/system.html @@ -78,16 +78,6 @@ - {# Plugins #} -
-
-
-
{% trans "Plugins" %}
- {% render_table plugins_table %} -
-
-
- {# Configuration #}