diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py index 0e2edcd9f..ee806f094 100644 --- a/netbox/extras/choices.py +++ b/netbox/extras/choices.py @@ -141,7 +141,7 @@ class LogLevelChoices(ChoiceSet): class JobResultStatusChoices(ChoiceSet): STATUS_PENDING = 'pending' - STATUS_SCHEDULED = 'pending' + STATUS_SCHEDULED = 'scheduled' STATUS_RUNNING = 'running' STATUS_COMPLETED = 'completed' STATUS_ERRORED = 'errored' @@ -149,7 +149,7 @@ class JobResultStatusChoices(ChoiceSet): CHOICES = ( (STATUS_PENDING, 'Pending'), - (STATUS_SCHEDULED, 'Pending'), + (STATUS_SCHEDULED, 'Scheduled'), (STATUS_RUNNING, 'Running'), (STATUS_COMPLETED, 'Completed'), (STATUS_ERRORED, 'Errored'), diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index aed8d4bb3..f7927a454 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -87,6 +87,7 @@ class CustomFieldFilterSet(BaseFilterSet): Q(description__icontains=value) ) + class CustomLinkFilterSet(BaseFilterSet): q = django_filters.CharFilter( method='search', @@ -434,8 +435,8 @@ class JobResultFilterSet(BaseFilterSet): method='search', label='Search', ) - created = django_filters.DateTimeFilter() - completed = django_filters.DateTimeFilter() + created = django_filters.DateTimeFromToRangeFilter() + completed = django_filters.DateTimeFromToRangeFilter() status = django_filters.MultipleChoiceFilter( choices=JobResultStatusChoices, null_value=None diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py index 2e715d9a7..c40d0ce94 100644 --- a/netbox/extras/forms/filtersets.py +++ b/netbox/extras/forms/filtersets.py @@ -69,7 +69,43 @@ class CustomFieldFilterForm(FilterForm): class JobResultFilterForm(FilterForm): fieldsets = ( (None, ('q',)), - #('Attributes', ('type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility')), + ('Attributes', ('obj_type', 'status')), + ('Creation', ('created_before', 'created_after', 'completed_before', 'completed_after', 'user')), + ) + + obj_type = ContentTypeChoiceField( + label=_('Object Type'), + queryset=ContentType.objects.all(), + limit_choices_to=FeatureQuery('job_results'), # TODO: This doesn't actually work + required=False, + ) + status = MultipleChoiceField( + choices=JobResultStatusChoices, + required=False + ) + created_after = forms.DateTimeField( + required=False, + widget=DateTimePicker() + ) + created_before = forms.DateTimeField( + required=False, + widget=DateTimePicker() + ) + completed_after = forms.DateTimeField( + required=False, + widget=DateTimePicker() + ) + completed_before = forms.DateTimeField( + required=False, + widget=DateTimePicker() + ) + user = DynamicModelMultipleChoiceField( + queryset=User.objects.all(), + required=False, + label=_('User'), + widget=APISelectMultiple( + api_url='/api/users/users/', + ) ) diff --git a/netbox/extras/forms/reports.py b/netbox/extras/forms/reports.py index 658796bb5..aa4f6223b 100644 --- a/netbox/extras/forms/reports.py +++ b/netbox/extras/forms/reports.py @@ -13,4 +13,4 @@ class ReportForm(BootstrapMixin, forms.Form): widget=DateTimePicker(), label="Schedule at", help_text="Schedule execution of report to a set time", - ) \ No newline at end of file + ) diff --git a/netbox/extras/management/commands/housekeeping.py b/netbox/extras/management/commands/housekeeping.py index 51d50d7e1..d2f2b1776 100644 --- a/netbox/extras/management/commands/housekeeping.py +++ b/netbox/extras/management/commands/housekeeping.py @@ -81,7 +81,7 @@ class Command(BaseCommand): ending="" ) self.stdout.flush() - JobResult.objects.filter(created__lt=cutoff)._raw_delete(using=DEFAULT_DB_ALIAS) + JobResult.objects.filter(created__lt=cutoff).delete(using=DEFAULT_DB_ALIAS) if options['verbosity']: self.stdout.write("Done.", self.style.SUCCESS) elif options['verbosity']: diff --git a/netbox/extras/migrations/0079_change_jobresult_order.py b/netbox/extras/migrations/0079_change_jobresult_order.py new file mode 100644 index 000000000..12e35bf67 --- /dev/null +++ b/netbox/extras/migrations/0079_change_jobresult_order.py @@ -0,0 +1,17 @@ +# Generated by Django 4.1.1 on 2022-10-09 18:37 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0078_unique_constraints'), + ] + + operations = [ + migrations.AlterModelOptions( + name='jobresult', + options={'ordering': ['-created']}, + ), + ] diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 03796f17d..2d3df5ca2 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -528,13 +528,22 @@ class JobResult(models.Model): objects = RestrictedQuerySet.as_manager() class Meta: - ordering = ['obj_type', 'name', '-created'] + ordering = ['-created'] def __str__(self): return str(self.job_id) + def delete(self, *args, **kwargs): + queue = django_rq.get_queue("default") + job = queue.fetch_job(str(self.job_id)) + + if job: + job.cancel() + + return super().delete(*args, **kwargs) + def get_absolute_url(self): - return reverse('extras:jobresult', args=[self.pk]) + return reverse(f'extras:{self.obj_type.name}_result', args=[self.pk]) @property def duration(self): @@ -579,7 +588,7 @@ class JobResult(models.Model): if schedule_at := kwargs.pop("schedule_at", None): job_result.status = JobResultStatusChoices.STATUS_SCHEDULED job_result.save() - + queue.enqueue_at(schedule_at, func, job_id=str(job_result.job_id), job_result=job_result, **kwargs) else: queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs) diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index 39f186ed6..6ddc26c3d 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -56,9 +56,9 @@ class JobResultTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = JobResult fields = ( - 'pk', 'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status', 'job_id', + 'pk', 'id', 'name', 'obj_type', 'job_id', 'created', 'completed', 'user', 'status', ) - default_columns = ('pk', 'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status', 'job_id') + default_columns = ('pk', 'id', 'name', 'obj_type', 'status', 'created', 'completed', 'user',) # diff --git a/netbox/extras/urls.py b/netbox/extras/urls.py index dfea1a4ef..0640904f2 100644 --- a/netbox/extras/urls.py +++ b/netbox/extras/urls.py @@ -76,7 +76,6 @@ urlpatterns = [ # Job results path('job-results/', views.JobResultListView.as_view(), name='jobresult_list'), - path('job-results//', views.JobResultView.as_view(), name='jobresult'), path('job-results/delete/', views.JobResultBulkDeleteView.as_view(), name='jobresult_bulk_delete'), path('job-results//delete/', views.JobResultDeleteView.as_view(), name='jobresult_delete'), diff --git a/netbox/extras/views.py b/netbox/extras/views.py index c242e36f4..29855a82b 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -815,6 +815,7 @@ class JobResultListView(generic.ObjectListView): table = tables.JobResultTable actions = ('delete', 'bulk_delete', ) + class JobResultDeleteView(generic.ObjectDeleteView): queryset = JobResult.objects.all() @@ -822,4 +823,4 @@ class JobResultDeleteView(generic.ObjectDeleteView): class JobResultBulkDeleteView(generic.BulkDeleteView): queryset = JobResult.objects.all() filterset = filtersets.JobResultFilterSet - table = tables.JobResultTable \ No newline at end of file + table = tables.JobResultTable diff --git a/netbox/project-static/dist/netbox-external.css b/netbox/project-static/dist/netbox-external.css index f8bd6e21c..8504316d4 100644 Binary files a/netbox/project-static/dist/netbox-external.css and b/netbox/project-static/dist/netbox-external.css differ diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index fe7a7e569..1534cee9b 100644 Binary files a/netbox/project-static/dist/netbox.js and b/netbox/project-static/dist/netbox.js differ diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index ff7b5a41d..bf25f3919 100644 Binary files a/netbox/project-static/dist/netbox.js.map and b/netbox/project-static/dist/netbox.js.map differ diff --git a/netbox/templates/extras/jobresult.html b/netbox/templates/extras/jobresult.html deleted file mode 100644 index 5f46dd6ac..000000000 --- a/netbox/templates/extras/jobresult.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends 'generic/object.html' %} -{% load helpers %} -{% load plugins %} - -{% block title %}{{ object.name }} ({{object.job_id}}){% endblock %} - -{# JobResult does not support add/edit controls #} -{% block controls %}{% endblock %} -{% block subtitle %}{% endblock %} - -{% block content %} -
-
-
-
- Tag -
-
- - - - - - - - - - - - - -
Name - {{ object.name }} -
Created - {{ object.created|annotated_date }} -
Completed - {{ object.completed|annotated_date }} -
-
-
-
-
-
-
- TODO -
-
- - TODO -
-
-
-
-
-
-
- {% plugin_full_width_page object %} -
-
-{% endblock %}