From ddb7ec3f46cae08e0abd0e95032b18838d1aa594 Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 22 Jan 2024 15:38:05 -0800 Subject: [PATCH] 14729 exec detail and common view --- netbox/core/tables/tasks.py | 4 - netbox/core/views.py | 75 ++++++++++++++---- netbox/templates/core/background_task.html | 9 ++- .../templates/core/background_task_list.html | 76 ++++++++++++++++++- netbox/templates/core/worker_list.html | 47 ++++++++++++ 5 files changed, 192 insertions(+), 19 deletions(-) create mode 100644 netbox/templates/core/worker_list.html diff --git a/netbox/core/tables/tasks.py b/netbox/core/tables/tasks.py index 61655b9b5..86562c48d 100644 --- a/netbox/core/tables/tasks.py +++ b/netbox/core/tables/tasks.py @@ -59,10 +59,6 @@ class BackgroundTaskTable(BaseTable): except Exception as e: return repr(e) - def __init__(self, queue_index, *args, **kwargs): - self.queue_index = queue_index - super().__init__(*args, **kwargs) - class WorkerTable(BaseTable): name = tables.Column(verbose_name=_("Name")) diff --git a/netbox/core/views.py b/netbox/core/views.py index a86237531..0f940d05c 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -14,6 +14,8 @@ from django.views.generic import View from netbox.config import get_config, PARAMS from netbox.views import generic from netbox.views.generic.base import BaseObjectView +from netbox.views.generic.mixins import ActionsMixin, TableMixin + from rq.exceptions import NoSuchJobError from rq.job import Job as RQ_Job from rq.registry import ( @@ -25,6 +27,7 @@ from rq.registry import ( ) from rq.worker import Worker from rq.worker_registration import clean_worker_registry +from utilities.htmx import is_embedded, is_htmx from utilities.utils import count_related from utilities.views import ContentTypePermissionRequiredMixin, register_model_view from . import filtersets, forms, tables @@ -256,6 +259,12 @@ class ConfigRevisionRestoreView(ContentTypePermissionRequiredMixin, View): # +class BaseTaskListView(UserPassesTestMixin, TableMixin, View): + + def test_func(self): + return self.request.user.is_staff + + class BackgroundQueueListView(UserPassesTestMixin, View): def test_func(self): @@ -269,15 +278,12 @@ class BackgroundQueueListView(UserPassesTestMixin, View): }) -class BackgroundTaskListView(UserPassesTestMixin, View): +class BackgroundTaskListView(BaseTaskListView): + table = tables.BackgroundTaskTable - def test_func(self): - return self.request.user.is_staff - - def get(self, request, queue_index, status): + def get_table_data(self, request, queue, status): registry = None jobs = [] - queue = get_queue_by_index(queue_index) if status == 'queued': if queue.count > 0: @@ -311,8 +317,27 @@ class BackgroundTaskListView(UserPassesTestMixin, View): for job in jobs: job.scheduled_at = registry.get_scheduled_time(job) - table = tables.BackgroundTaskTable(data=jobs, user=request.user, queue_index=queue_index) - table.configure(request) + return jobs + + def get(self, request, queue_index, status): + queue = get_queue_by_index(queue_index) + data = self.get_table_data(request, queue, status) + + table = self.get_table(data, request, False) + + # If this is an HTMX request, return only the rendered table HTML + if is_htmx(request): + if is_embedded(request): + table.embedded = True + # Hide selection checkboxes + if 'pk' in table.base_columns: + table.columns.hide('pk') + return render(request, 'htmx/table.html', { + 'table': table, + 'queue': queue, + 'status': status, + }) + return render(request, 'core/background_task_list.html', { 'table': table, 'queue': queue, @@ -320,19 +345,36 @@ class BackgroundTaskListView(UserPassesTestMixin, View): }) -class WorkerListView(UserPassesTestMixin, View): +class WorkerListView(BaseTaskListView): + table = tables.WorkerTable def test_func(self): return self.request.user.is_staff - def get(self, request, queue_index): - queue = get_queue_by_index(queue_index) + def get_table_data(self, request, queue): clean_worker_registry(queue) all_workers = Worker.all(queue.connection) workers = [worker for worker in all_workers if queue.name in worker.queue_names()] + return workers + + def get(self, request, queue_index): + queue = get_queue_by_index(queue_index) + data = self.get_table_data(request, queue) + + table = self.get_table(data, request, False) + + # If this is an HTMX request, return only the rendered table HTML + if is_htmx(request): + if is_embedded(request): + table.embedded = True + # Hide selection checkboxes + if 'pk' in table.base_columns: + table.columns.hide('pk') + return render(request, 'htmx/table.html', { + 'table': table, + 'queue': queue, + }) - table = tables.WorkerTable(data=workers, user=request.user) - table.configure(request) return render(request, 'core/worker_list.html', { 'table': table, 'queue': queue, @@ -361,11 +403,18 @@ class BackgroundTaskDetailView(UserPassesTestMixin, View): except Exception: data_is_valid = False + try: + exc_info = job._exc_info + except AttributeError: + exc_info = None + return render(request, 'core/background_task.html', { 'queue': queue, 'job': job, 'queue_index': queue_index, 'data_is_valid': data_is_valid, + 'dependency_id': job._dependency_id, + 'exc_info': exc_info, }) diff --git a/netbox/templates/core/background_task.html b/netbox/templates/core/background_task.html index 2d505c540..8c718ba68 100644 --- a/netbox/templates/core/background_task.html +++ b/netbox/templates/core/background_task.html @@ -5,7 +5,7 @@ {% block breadcrumbs %} - + {% endblock breadcrumbs %} {% block title %}{% trans "Job" %} {{ job.id }}{% endblock %} @@ -75,6 +75,13 @@ {% trans "Kwargs" %} {{ job.kwargs|placeholder }} + {% if exc_info %} + + {% trans "Exception:" %} +
{% if job.exc_info %}{{ job.exc_info|linebreaks }}{% endif %}
+ + {% endif %} + diff --git a/netbox/templates/core/background_task_list.html b/netbox/templates/core/background_task_list.html index 8ec18126f..0e8d7e35f 100644 --- a/netbox/templates/core/background_task_list.html +++ b/netbox/templates/core/background_task_list.html @@ -1,4 +1,5 @@ {% extends 'generic/_base.html' %} +{% load buttons %} {% load helpers %} {% load i18n %} {% load render_table from django_tables2 %} @@ -26,6 +27,7 @@ {% endblock tabs %} {% block content %} + {% comment %}
{# Table configuration button #} @@ -37,9 +39,81 @@
+ {# Objects table #}
- {% render_table table %} +
+ {% include 'htmx/table.html' %} +
+ {# /Objects table #} + {% endcomment %} + + + + {# Object list tab #} +
+ + {# Object table controls #} + {% include 'inc/table_controls_htmx.html' with table_modal="ObjectTable_config" %} + +
+ {% csrf_token %} + {# "Select all" form #} + {% if table.paginator.num_pages > 1 %} +
+
+
+
+ {% if 'bulk_edit' in actions %} + {% bulk_edit_button model query_params=request.GET %} + {% endif %} + {% if 'bulk_delete' in actions %} + {% bulk_delete_button model query_params=request.GET %} + {% endif %} +
+
+ + +
+
+
+
+ {% endif %} + +
+ {% csrf_token %} + + + {# Objects table #} +
+
+ {% include 'htmx/table.html' %} +
+
+ {# /Objects table #} + + {# Form buttons #} +
+ {% block bulk_buttons %} + {% if 'bulk_edit' in actions %} + {% bulk_edit_button model query_params=request.GET %} + {% endif %} + {% if 'bulk_delete' in actions %} + {% bulk_delete_button model query_params=request.GET %} + {% endif %} + {% endblock %} +
+ {# /Form buttons #} + +
+
+
+ {# /Object list tab #} + {% endblock content %} {% block modals %} diff --git a/netbox/templates/core/worker_list.html b/netbox/templates/core/worker_list.html new file mode 100644 index 000000000..35ad4792a --- /dev/null +++ b/netbox/templates/core/worker_list.html @@ -0,0 +1,47 @@ +{% extends 'generic/_base.html' %} +{% load helpers %} +{% load i18n %} +{% load render_table from django_tables2 %} + +{% block page-header %} +
+ {# Breadcrumbs #} + +
+ {{ block.super }} +{% endblock page-header %} + +{% block title %}{{ status|capfirst }} {% trans "Workers in " %}{{ queue.name }}{% endblock %} + +{% block tabs %} + +{% endblock tabs %} + +{% block content %} +
+
+ {# Table configuration button #} +
+ +
+
+
+ +
+ {% render_table table %} +
+{% endblock content %} + +{% block modals %} + {% table_config_form table table_name="ObjectTable" %} +{% endblock modals %}