diff --git a/netbox/extras/tests/test_views.py b/netbox/extras/tests/test_views.py index fd3ce5453..ac3f5b23a 100644 --- a/netbox/extras/tests/test_views.py +++ b/netbox/extras/tests/test_views.py @@ -807,3 +807,21 @@ class NotificationTestCase( def test_list_objects_with_constrained_permission(self): return + + +class ScriptListViewTest(TestCase): + user_permissions = ['extras.view_script'] + + def test_script_list_embedded_parameter(self): + """Test that ScriptListView accepts embedded parameter without error""" + url = reverse('extras:script_list') + + # Test normal request + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'extras/script_list.html') + + # Test embedded request + response = self.client.get(url, {'embedded': 'true'}) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'extras/inc/script_list_content.html') diff --git a/netbox/extras/views.py b/netbox/extras/views.py index ea465a4a4..fae8eb63e 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1282,11 +1282,18 @@ class ScriptListView(ContentTypePermissionRequiredMixin, View): script_modules = ScriptModule.objects.restrict(request.user).prefetch_related( 'data_source', 'data_file', 'jobs' ) - - return render(request, 'extras/script_list.html', { + context = { 'model': ScriptModule, 'script_modules': script_modules, - }) + } + + # Use partial template for dashboard widgets + template_name = 'extras/script_list.html' + if request.GET.get('embedded'): + template_name = 'extras/inc/script_list_content.html' + context['embedded'] = True + + return render(request, template_name, context) class BaseScriptView(generic.ObjectView): diff --git a/netbox/templates/extras/inc/script_list_content.html b/netbox/templates/extras/inc/script_list_content.html new file mode 100644 index 000000000..4bdb1bf16 --- /dev/null +++ b/netbox/templates/extras/inc/script_list_content.html @@ -0,0 +1,139 @@ +{% load buttons %} +{% load helpers %} +{% load perms %} +{% load i18n %} + +{# Core script list content - used by both full page and embedded views #} +{% for module in script_modules %} + {% include 'inc/sync_warning.html' with object=module %} +
+ {% if not embedded %} +

+ {{ module }} +
+ {% if perms.extras.edit_scriptmodule %} + + {% trans "Edit" %} + + {% endif %} + {% if perms.extras.delete_scriptmodule %} + + {% trans "Delete" %} + + {% endif %} +
+

+ {% endif %} + {% with scripts=module.ordered_scripts %} + {% if scripts %} + + + + + + + + + + + + {% for script in scripts %} + {% with last_job=script.get_latest_jobs|first %} + + + + {% if last_job %} + + + {% else %} + + + {% endif %} + + + {% if last_job and not embedded %} + {% for test_name, data in last_job.data.tests.items %} + + + + + {% endfor %} + {% elif last_job and not last_job.data.log and not embedded %} + {# legacy #} + {% for method, stats in last_job.data.items %} + + + + + {% endfor %} + {% endif %} + {% endwith %} + {% endfor %} + +
{% trans "Name" %}{% trans "Description" %}{% trans "Last Run" %}{% trans "Status" %}
+ {% if script.is_executable %} + {{ script.python_class.name }} + {% else %} + {{ script.python_class.name }} + + + + {% endif %} + {{ script.python_class.description|markdown|placeholder }} + {{ last_job.created|isodatetime }} + + {% badge last_job.get_status_display last_job.get_status_color %} + {% trans "Never" %}{{ ''|placeholder }} + {% if request.user|can_run:script and script.is_executable %} +
+
+ {% if script.python_class.commit_default %} + + {% endif %} + {% csrf_token %} + +
+
+ {% endif %} +
+ {{ test_name }} + + {{ data.success }} + {{ data.info }} + {{ data.warning }} + {{ data.failure }} +
+ {{ method }} + + {{ stats.success }} + {{ stats.info }} + {{ stats.warning }} + {{ stats.failure }} +
+ {% else %} +
+ +
+ {% endif %} + {% endwith %} +
+{% empty %} + +{% endfor %} diff --git a/netbox/templates/extras/script_list.html b/netbox/templates/extras/script_list.html index 57269aa53..4f7652c1f 100644 --- a/netbox/templates/extras/script_list.html +++ b/netbox/templates/extras/script_list.html @@ -19,135 +19,5 @@ {% endblock controls %} {% block content %} - {% for module in script_modules %} - {% include 'inc/sync_warning.html' with object=module %} -
-

- {{ module }} -
- {% if perms.extras.edit_scriptmodule %} - - {% trans "Edit" %} - - {% endif %} - {% if perms.extras.delete_scriptmodule %} - - {% trans "Delete" %} - - {% endif %} -
-

- {% with scripts=module.ordered_scripts %} - {% if scripts %} - - - - - - - - - - - - {% for script in scripts %} - {% with last_job=script.get_latest_jobs|first %} - - - - {% if last_job %} - - - {% else %} - - - {% endif %} - - - {% if last_job %} - {% for test_name, data in last_job.data.tests.items %} - - - - - {% endfor %} - {% elif not last_job.data.log %} - {# legacy #} - {% for method, stats in last_job.data.items %} - - - - - {% endfor %} - {% endif %} - {% endwith %} - {% endfor %} - -
{% trans "Name" %}{% trans "Description" %}{% trans "Last Run" %}{% trans "Status" %}
- {% if script.is_executable %} - {{ script.python_class.name }} - {% else %} - {{ script.python_class.name }} - - - - {% endif %} - {{ script.python_class.description|markdown|placeholder }} - {{ last_job.created|isodatetime }} - - {% badge last_job.get_status_display last_job.get_status_color %} - {% trans "Never" %}{{ ''|placeholder }} - {% if request.user|can_run:script and script.is_executable %} -
-
- {% if script.python_class.commit_default %} - - {% endif %} - {% csrf_token %} - -
-
- {% endif %} -
- {{ test_name }} - - {{ data.success }} - {{ data.info }} - {{ data.warning }} - {{ data.failure }} -
- {{ method }} - - {{ stats.success }} - {{ stats.info }} - {{ stats.warning }} - {{ stats.failure }} -
- {% else %} -
- -
- {% endif %} - {% endwith %} -
- {% empty %} - - {% endfor %} + {% include 'extras/inc/script_list_content.html' with embedded=False %} {% endblock content %}