diff --git a/atdb/taskdatabase/models.py b/atdb/taskdatabase/models.py index 3ce0ad358b08d69abe562510bc74881deb51d8a7..ff5f71499986dfb2766c2e78995f973f6799a5a2 100644 --- a/atdb/taskdatabase/models.py +++ b/atdb/taskdatabase/models.py @@ -1,7 +1,6 @@ from django.db import models from django.urls import reverse from django.utils.timezone import datetime -from django.db.models import Sum # constants datetime_format_string = '%Y-%m-%dT%H:%M:%SZ' @@ -18,6 +17,43 @@ class Workflow(models.Model): return str(self.id) +def convert_quality_to_dict_for_template(task): + d = {} + + try: + d['QA uv-coverage'] = str(task.quality['uv-coverage']) + d['QA sensitivity'] = str(task.quality['sensitivity']) + d['QA observing-conditions'] = str(task.quality['observing-conditions']) + d['QA diagnostic plots'] = "(link)" + d['Workflow summary parset'] = "(link)" + d['Summary logs'] = "(link)" + d['QA summary.hf5'] = "(link)" + + except Exception as err: + pass + + return d + + +# convert the quality information from the JSONfield into a easy parsable list for the template +def convert_quality_to_list_for_template(task): + list = [] + + try: + list.append(str(task.quality['uv-coverage'])) + list.append(str(task.quality['sensitivity'])) + list.append(str(task.quality['observing-conditions'])) + list.append("(link)") + list.append("(link)") + list.append("(link)") + list.append("(link)") + + except Exception as err: + pass + + return list + + class Task(models.Model): # Task control properties @@ -73,10 +109,26 @@ class Task(models.Model): def has_quality(self): # todo: check if there is a 'quality' structure in the 'task.outputs' try: + quality = self.outputs[0]['quality'] return True except: return False + @property + def quality(self): + # todo: check if there is a 'quality' structure in the 'task.outputs' + try: + return self.outputs[0]['quality'] + except: + return None + + @property + def quality_as_list(self): + try: + q = convert_quality_to_list_for_template(self) + return q + except: + return None class LogEntry(models.Model): cpu_cycles = models.IntegerField(null=True,blank=True) diff --git a/atdb/taskdatabase/services/algorithms.py b/atdb/taskdatabase/services/algorithms.py index 44a41a76aacf14e6b052077d327cde6e0b965701..953dcc0bd12fdccda8d47508c7454fec29e97a6d 100644 --- a/atdb/taskdatabase/services/algorithms.py +++ b/atdb/taskdatabase/services/algorithms.py @@ -110,21 +110,16 @@ def convert_quality_to_html(task): results = "" try: - outputs = task.outputs - print(outputs[0]) - quality = task.outputs[0]['quality'] - print(quality) results = "" - results += "<tr><td><b>SAS_ID</b></td><td>" + str(task.sas_id) + "</td></tr>" results += "<tr><td><b>Project</b></td><td>" + str(task.project) + "</td></tr>" results += "<tr><td><b>ATDB Filter</b></td><td>" + str(task.filter) + "</td></tr>" results += "<tr><td><b>Input Type</b></td><td>" + "???" + "</td></tr>" results += "<tr><td><b>NrJobs (MSs)</b></td><td>" + "???" + "</td></tr>" - results += "<tr><td><b>QA uv-coverage</b></td><td>" + str(quality['uv-coverage']) + "</td></tr>" - results += "<tr><td><b>QA sensitivity</b></td><td>" + str(quality['sensitivity']) + "</td></tr>" - results += "<tr><td><b>QA observing-conditions</b></td><td>" + str(quality['observing-conditions']) + "</td></tr>" + results += "<tr><td><b>QA uv-coverage</b></td><td>" + str(task.quality['uv-coverage']) + "</td></tr>" + results += "<tr><td><b>QA sensitivity</b></td><td>" + str(task.quality['sensitivity']) + "</td></tr>" + results += "<tr><td><b>QA observing-conditions</b></td><td>" + str(task.quality['observing-conditions']) + "</td></tr>" results += "<tr><td><b>QA diagnostic plots</b></td><td>" + "(link)" + "</td></tr>" results += "<tr><td><b>Workflow summary parset</b></td><td>" + "(link)" + "</td></tr>" results += "<tr><td><b>Summary logs</b></td><td>" + "(link)" + "</td></tr>" diff --git a/atdb/taskdatabase/templates/taskdatabase/base.html b/atdb/taskdatabase/templates/taskdatabase/base.html index 2bc5bbf8a08591a8204a4179f788eae83bf3005e..e4604399994c17e0fd570780c567c1c0634c1d55 100644 --- a/atdb/taskdatabase/templates/taskdatabase/base.html +++ b/atdb/taskdatabase/templates/taskdatabase/base.html @@ -42,10 +42,14 @@ ATDB</a> </li> - <li><a class="nav-link" href="{% url 'index' %}">Regular Tasks</a></li> + <li><a class="nav-link" href="{% url 'index' %}">Tasks</a></li> +{% comment %} <li><a class="nav-link" href="{% url 'postprocessing-tasks' %}">PostProcessing</a></li> +{% endcomment %} + {% if user.is_authenticated %} <li><a class="nav-link" href="{% url 'task-details'%}">Task Details</a></li> + <li><a class="nav-link" href="{% url 'quality-tasks' %}">Quality</a></li> {% endif %} <li><a class="nav-link" href="{% url 'dashboard' 'active_nores' %}">Dashboard</a></li> diff --git a/atdb/taskdatabase/templates/taskdatabase/index.html b/atdb/taskdatabase/templates/taskdatabase/index.html index 276050d311900953d1aa60ba736094572b4ce31a..835c572b2e38c1dc4e16e3ea7221ee27265b5ceb 100644 --- a/atdb/taskdatabase/templates/taskdatabase/index.html +++ b/atdb/taskdatabase/templates/taskdatabase/index.html @@ -19,53 +19,7 @@ <table class="table table-striped table-bordered table-sm"> <thead> - <tr> - <th> - <a href="{% url 'sort-tasks' '-pk' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - ID - <a href="{% url 'sort-tasks' 'id' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - <th>Details</th> - <th> - <a href="{% url 'sort-tasks' '-workflow' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - Workflow - <a href="{% url 'sort-tasks' 'workflow' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - <th> - <a href="{% url 'sort-tasks' '-priority' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - Priority - <a href="{% url 'sort-tasks' 'priority' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - - <th> - <a href="{% url 'sort-tasks' '-status' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - Status - <a href="{% url 'sort-tasks' 'status' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - <th> - <a href="{% url 'sort-tasks' '-project' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - Project - <a href="{% url 'sort-tasks' 'project' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - <th> - <a href="{% url 'sort-tasks' '-sas_id' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - SAS_ID - <a href="{% url 'sort-tasks' 'sas_id' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - <th> - <a href="{% url 'sort-tasks' '-creationTime' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - CreationTime - <a href="{% url 'sort-tasks' 'creationTime' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - - <th> - <a href="{% url 'sort-tasks' '-size_to_process' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> - Size - <a href="{% url 'sort-tasks' 'size_to_process' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> - </th> - - <th>Actions</th> - </tr> + {% include 'taskdatabase/tasks_headers.html' %} </thead> <tbody> {% include 'taskdatabase/tasks.html' %} @@ -80,7 +34,7 @@ {% include 'taskdatabase/pagination.html' %} </div> </div> - <p class="footer"> Version 1.0.0 (3 feb 2021 - 8:00) + <p class="footer"> Version 1.0.0 (4 feb 2021 - 15:00) </div> diff --git a/atdb/taskdatabase/templates/taskdatabase/monitoring.html b/atdb/taskdatabase/templates/taskdatabase/monitoring.html index 95fc5c138573e3b7b2cf63ff8a335c0d505c21e7..1080b5846b0cd1c02333cb8dd8473f39c6d8f314 100644 --- a/atdb/taskdatabase/templates/taskdatabase/monitoring.html +++ b/atdb/taskdatabase/templates/taskdatabase/monitoring.html @@ -4,6 +4,14 @@ {% block myBlock %} <div class="hiking-container container-fluid"> + <div class="card"> + <div class="card-body"> + <div class="row"> + <div class="col-8"> + <h4>Monitoring</h4> + </div> + </div> + <div class="col-sm-6 col-md-8 col-lg-12"> <div class="thumbnail"> diff --git a/atdb/taskdatabase/templates/taskdatabase/quality_page.html b/atdb/taskdatabase/templates/taskdatabase/quality_page.html new file mode 100644 index 0000000000000000000000000000000000000000..d8bf52ff04e2ac476f447a3581da0b33cc8dc32b --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/quality_page.html @@ -0,0 +1,48 @@ +{% extends 'taskdatabase/base.html' %} +{% load static %} + +{% block myBlock %} + +<div class="container-fluid details-container"> + <div class="card"> + <div class="card-body"> + <div class="row"> + <div class="col-8"> + <h4>Quality</h4> + </div> + </div> + <div class="row"> + <div class="col-sm-12 col-md-12 col-lg-12"> + {% include 'taskdatabase/pagination.html' %} + + {% if my_tasks %} + <div class="panel panel-success"> + + <div class="panel-body"> + + <table class="table table-striped table-bordered table-sm"> + <thead> + {% include 'taskdatabase/tasks_quality_headers.html' %} + </thead> + <tbody> + {% include 'taskdatabase/tasks_quality.html' %} + </tbody> + </table> + {% else %} + <p>No recent Tasks.</p> + {% endif %} + + </div> + </div> + {% include 'taskdatabase/pagination.html' %} + </div> + </div> + </div> + </div> +</div> + +{% include 'taskdatabase/localstorage_scripts.html' %} + + +{% endblock %} + diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks.html b/atdb/taskdatabase/templates/taskdatabase/tasks.html index b6675ada3f55bdbd082208034fec589fead93d3e..c7e32dc2ff2dbffa263b74101a44e28ad3dc3971 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks.html @@ -9,16 +9,19 @@ </td> <td> {% if user.is_authenticated %} - <a class="btn btn-primary btn-sm" - href="{% url 'task-details' task.id my_tasks.number %}" - data-popup-url="{% url 'task-details' task.id my_tasks.number %}" - ><i class="fas fa-list"></i> Details - </a> - <a class="btn btn-primary btn-sm" - href="{% url 'task-quality' task.id my_tasks.number %}" - data-popup-url="{% url 'task-quality' task.id my_tasks.number %}" - ><i class="fas fa-balance-scale-right"></i> Quality - </a> + <a class="btn btn-primary btn-sm" + href="{% url 'task-details' task.id my_tasks.number %}" + data-popup-url="{% url 'task-details' task.id my_tasks.number %}" + ><i class="fas fa-list"></i> Details + </a> + + {% if task.has_quality %} + <a class="btn btn-primary btn-sm" + href="{% url 'task-quality' task.id my_tasks.number %}" + data-popup-url="{% url 'task-quality' task.id my_tasks.number %}" + ><i class="fas fa-balance-scale-right"></i> Quality + </a> + {% endif %} {% endif %} </td> <td> diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html b/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html index 27297632234d1cee596e63af704a51a05626435a..abaab6708b567ee4c3757e122298ab2c9cb16b3e 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html @@ -45,6 +45,13 @@ data-popup-url="{% url 'show-metrics' task.id %}" target="_blank"><i class="fas fa-clock"></i> metrics </a> + {% if task.has_quality %} + <a class="open-modal btn btn-primary btn-sm" + href="{% url 'task-quality' task.id 1 %}" + data-popup-url="{% url 'task-quality' task.id 1 %}" + ><i class="fas fa-balance-scale-right"></i> Quality + </a> + {% endif %} </td> </tr> <tr><td><b>filter</b></td><td>{{ task.filter }}</td></tr> diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks/task_quality.html b/atdb/taskdatabase/templates/taskdatabase/tasks/task_quality.html index b54445d701a1112cb8318e074812748ab958eac4..36102a4fb86ce5b13ce448a3ec47b5a292c92b13 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks/task_quality.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks/task_quality.html @@ -1,4 +1,4 @@ -{% extends 'taskdatabase/base.html' %} + {% load static %} {% block myBlock %} diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html b/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html new file mode 100644 index 0000000000000000000000000000000000000000..156832363547b92123d5e85d64c4486b499d6147 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html @@ -0,0 +1,47 @@ +<tr> + <th> + <a href="{% url 'sort-tasks' '-pk' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + ID + <a href="{% url 'sort-tasks' 'id' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th>Details</th> + <th> + <a href="{% url 'sort-tasks' '-workflow' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Workflow + <a href="{% url 'sort-tasks' 'workflow' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th> + <a href="{% url 'sort-tasks' '-priority' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Priority + <a href="{% url 'sort-tasks' 'priority' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + + <th> + <a href="{% url 'sort-tasks' '-status' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Status + <a href="{% url 'sort-tasks' 'status' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th> + <a href="{% url 'sort-tasks' '-project' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Project + <a href="{% url 'sort-tasks' 'project' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th> + <a href="{% url 'sort-tasks' '-sas_id' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + SAS_ID + <a href="{% url 'sort-tasks' 'sas_id' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th> + <a href="{% url 'sort-tasks' '-creationTime' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + CreationTime + <a href="{% url 'sort-tasks' 'creationTime' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + + <th> + <a href="{% url 'sort-tasks' '-size_to_process' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Size + <a href="{% url 'sort-tasks' 'size_to_process' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + + <th>Actions</th> +</tr> \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks_quality.html b/atdb/taskdatabase/templates/taskdatabase/tasks_quality.html new file mode 100644 index 0000000000000000000000000000000000000000..75c461e2296df90e3092b03e3231195942ff4ff4 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/tasks_quality.html @@ -0,0 +1,49 @@ +{% load static %} +{% for task in my_tasks %} + + {% if task.status != "removed_invisible" %} + <div class="row"> + <tr class="{{ task.status }}"> + + <td> + <a href="{{ task.get_absolute_url }}" target="_blank">{{ task.id }} </a> + </td> + <td> + {% if user.is_authenticated %} + <a class="btn btn-primary btn-sm" + href="{% url 'task-details' task.id my_tasks.number %}" + data-popup-url="{% url 'task-details' task.id my_tasks.number %}" + ><i class="fas fa-list"></i> Details + </a> + {% endif %} + </td> + + {% if task.resume %} + <td class="bigger">{{ task.status }}</td> + {% endif %} + {% if not task.resume %} + <td class="bigger">{{ task.status }} (holding)</td> + {% endif %} + + <td>{{ task.project }}</td> + <td>{{ task.sas_id }}</td> + + <td>{{ task.filter }} </td> + + {% if task.has_quality %} + {% for value in task.quality_as_list %} + <td>{{value}}</td> + {% endfor %} + {% endif %} + + + <td> + + </tr> + </div> + {% endif %} + +{% endfor %} + +{% include "taskdatabase/modal/modal_script.html" %} +{% include "taskdatabase/modal/modal.html" %} \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks_quality_headers.html b/atdb/taskdatabase/templates/taskdatabase/tasks_quality_headers.html new file mode 100644 index 0000000000000000000000000000000000000000..cd699a598401ff3848aa79ade6099795e5574dc3 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/tasks_quality_headers.html @@ -0,0 +1,16 @@ +<tr> + <th>ID</th> + <th>Details</th> + + <th>Status</th> + <th>Project</th> + <th>SAS_ID</th> + <th>filter</th> + <th>uv-coverage</th> + <th>Sensitivity</th> + <th>Conditions</th> + <th>Diagnostic plots</th> + <th>Summary parset</th> + <th>Summary logs</th> + <th>Summary hf5</th> +</tr> \ No newline at end of file diff --git a/atdb/taskdatabase/urls.py b/atdb/taskdatabase/urls.py index 583c83874873f0e5a9cf6057e1e15c1cb2022f97..b3862f35ab86c6b3506bcdc9edb2bf8844190e87 100644 --- a/atdb/taskdatabase/urls.py +++ b/atdb/taskdatabase/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ # --- GUI --- path('', views.IndexView.as_view(), name='index'), path('postprocessing-tasks', views.PostProcessingTasksView.as_view(), name='postprocessing-tasks'), + path('quality-tasks', views.QualityTasksView.as_view(), name='quality-tasks'), path('task_details/<int:id>/<page>', views.TaskDetails, name='task-details'), path('task_details/', views.TaskDetails, name='task-details'), diff --git a/atdb/taskdatabase/views.py b/atdb/taskdatabase/views.py index 6e6cba77c201aa08a0c4fe6bdfe8fd278d62bf47..f68cd9c68a20a0d6ab6fbc3159792be5dc1b6df7 100644 --- a/atdb/taskdatabase/views.py +++ b/atdb/taskdatabase/views.py @@ -155,7 +155,8 @@ class MonitorFilter(filters.FilterSet): class QueryView(SingleTableMixin, FilterView): table_class = TaskTable model = Task - queryset = Task.objects.filter(task_type='regular') + # queryset = Task.objects.filter(task_type='regular') + queryset = Task.objects.all() template_name = "query/index.html" filterset_class = TaskFilterQueryPage @@ -221,7 +222,7 @@ class IndexView(ListView): tasks = get_searched_tasks(search_box, sort) # only return the 'regular' tasks, and not the 'postprocessing' tasks in the GUI - tasks = tasks.filter(task_type='regular') + # tasks = tasks.filter(task_type='regular') paginator = Paginator(tasks, config.TASKS_PER_PAGE) # Show 50 tasks per page page = self.request.GET.get('page') @@ -314,6 +315,67 @@ class PostProcessingTasksView(ListView): return tasks +class QualityTasksView(ListView): + """ + This is the main view of ATDB. It shows a pagination list of tasks, sorted by creationTime. + """ + template_name = 'taskdatabase/quality_page.html' + + # by default this returns the list in an object called object_list, so use 'object_list' in the html page. + # but if 'context_object_name' is defined, then this returned list is named and can be accessed that way in html. + context_object_name = 'my_tasks' + + def get_queryset(self): + status = self.request.GET.get('status') + search_box = self.request.GET.get('search_box', None) + + # get the sort variable from the session or use default + try: + sort = self.request.session['sort'] + except: + sort = '-creationTime' + + tasks = Task.objects.order_by(sort) + + # check if there is a 'task_filter' put on the session + try: + filter = self.request.session['task_filter'] + if filter != 'all': + tasks = get_searched_tasks(filter, sort) + except: + pass + + if (search_box is not None): + tasks = get_searched_tasks(search_box, sort) + + # exclude the tasks without quality information + tasks = tasks.exclude(outputs__isnull=True) + tasks = tasks.exclude(outputs__0__quality__isnull=True) + + + paginator = Paginator(tasks, config.TASKS_PER_PAGE) # Show 50 tasks per page + page = self.request.GET.get('page') + + try: + # check if there was a page on the session, if so, use it. + if page == None: + page = self.request.session['page'] + self.request.session['page'] = None + except: + pass + + try: + tasks = paginator.page(page) + except PageNotAnInteger: + # If page is not an integer, deliver first page. + tasks = paginator.page(1) + except EmptyPage: + # If page is out of range (e.g. 9999), deliver last page of results. + tasks = paginator.page(paginator.num_pages) + + return tasks + + def get_searched_tasks(search, sort): tasks = Task.objects.filter( Q(id__contains=search) |