Skip to content
Snippets Groups Projects
Commit ecf16b12 authored by Nico Vermaas's avatar Nico Vermaas
Browse files

add task details page

parent d5a912cf
No related branches found
No related tags found
3 merge requests!73Master,!54Master,!48add task details page
Showing with 192 additions and 82 deletions
...@@ -92,7 +92,7 @@ class TaskReadSerializer(serializers.ModelSerializer): ...@@ -92,7 +92,7 @@ class TaskReadSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Task model = Task
fields = ('id','task_type','filter','predecessor','successors', fields = ('id','task_type','creationTime','filter','predecessor','successors',
'project','sas_id','priority','purge_policy','resume', 'project','sas_id','priority','purge_policy','resume',
'workflow', 'workflow',
'stage_request_id', 'stage_request_id',
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
ATDB-LDV Dashboard</a> ATDB-LDV Dashboard</a>
</li> </li>
<li><a class="nav-link" href="{% url 'homepage' %}">Tasks</a></li> <li><a class="nav-link" href="{% url 'homepage' %}">Tasks</a></li>
<li><a class="nav-link" href="{% url 'task-details' 0 0 %}">Details</a></li> <li><a class="nav-link" href="{% url 'task-details'%}">Details</a></li>
<li><a class="nav-link" href="{% url 'tables2' %}">Query</a></li> <li><a class="nav-link" href="{% url 'tables2' %}">Query</a></li>
<li><a class="nav-link" href="{% url 'diagram' %}">State Diagram</a></li> <li><a class="nav-link" href="{% url 'diagram' %}">State Diagram</a></li>
{% if user.is_staff %} {% if user.is_staff %}
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
<table> <table>
<tr><td>Click to Filter</td></tr> <tr><td>Click to Filter</td></tr>
<tr> <tr>
<td> <td>
<a href="{% url 'task-set-filter' 'all' %}" class="btn btn-success btn-sm" role="button">ALL</a> <a href="{% url 'task-set-filter' 'all' %}" class="btn btn-success btn-sm" role="button">ALL</a>
<a href="{% url 'task-set-filter' 'defined' %}" class="btn btn-primary btn-sm" role="button">defined</a> <a href="{% url 'task-set-filter' 'defined' %}" class="btn btn-primary btn-sm" role="button">defined</a>
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
{% include 'taskdatabase/pagination.html' %} {% include 'taskdatabase/pagination.html' %}
</div> </div>
</div> </div>
<p class="footer"> Version 1.0.0 (5 mar 2021 - 12:00) <p class="footer"> Version 1.0.0 (5 mar 2021 - 15:00)
</div> </div>
......
<div class="card">
<div class="card-body">
<h4>Task: {{ task.id }}</h4>
<table class="table table-striped">
<tbody>
<tr><td><b>id</b></td><td><a href="{% url 'task-detail-view-api' task.pk %}" target="_blank">{{ task.id }} </a></td></tr>
<tr><td><b>priority</b></td><td>{{ task.priority }}</td></tr>
<tr class="{{ task.status }}"><td><b>status</b></td><td>{{ task.status }}</td></tr>
<tr><td><b>workflow</b></td><td>
<a class="open-modal btn btn-primary btn-sm"
href="{% url 'workflow-details' task.workflow %}"
data-popup-url="{% url 'workflow-details' task.workflow %}"
target="_blank"> {{ task.workflow }}
</a></td>
<tr>
<td colspan="2">
<a class="open-modal btn btn-primary btn-sm"
href="{% url 'show-inputs' task.id %}"
data-popup-url="{% url 'show-inputs' task.id %}"
target="_blank"><i class="fas fa-angle-double-down"></i>&nbsp;inputs
</a>&nbsp;
<a class="open-modal btn btn-primary btn-sm"
href="{% url 'show-outputs' task.id %}"
data-popup-url="{% url 'show-outputs' task.id %}"
target="_blank"><i class="fas fa-angle-double-up"></i>&nbsp;outputs
</a>&nbsp;
<a class="open-modal btn btn-primary btn-sm"
href="{% url 'show-metrics' task.id %}"
data-popup-url="{% url 'show-metrics' task.id %}"
target="_blank"><i class="fas fa-clock"></i>&nbsp;metrics
</a>
</td>
</tr>
<tr><td><b>project</b></td><td>{{ task.project }}</td></tr>
<tr><td><b>sas_id</b></td><td>{{ task.sas_id }}</td></tr>
<tr><td><b>creationTime</b></td><td>{{ task.creationTime }}</td></tr>
<tr><td><b>purge_policy</b></td><td>{{ task.purge_policy }}</td></tr>
<tr><td><b>resume</b></td><td>{{ task.resume }}</td></tr>
<tr><td><b>stage_request_id</b></td><td>{{ task.stage_request_id }}</td></tr>
<tr><td><b>size_to_process</b></td><td>{{ task.size_to_process|filesizeformat }}</td></tr>
<tr><td><b>size_processed</b></td><td>{{ task.size_processed|filesizeformat }}</td></tr>
<tr><td><b>total_processing_time</b></td><td>{{ task.total_processing_time }}</td></tr>
</tbody>
</table>
</div>
</div>
\ No newline at end of file
<div class="card">
<div class="card-body">
<h4>Log Entries</h4>
<table class="table table-striped">
{{ logentries | safe }}
</table>
</div>
</div>
\ No newline at end of file
<div class="row">
<div class="col-sm">
<div class="card">
<div class="card-body">
{% if user.is_staff %}
<p>Click to change Status</p>
<table>
<tr>
{% if task.status != "defining" %}
<a href="{% url 'task-details-setstatus' task.pk 'defining' %}" class="btn btn-warning btn-sm" role="button"><i class="fas fa-undo"></i> Reset</a>&nbsp;
{% endif %}
{% if task.status == "defining" %}
<a href="{% url 'task-details-setstatus' task.pk 'defined' %}" class="btn btn-success btn-sm" role="button"><i class="fas fa-sync-alt"></i> Stage</a>&nbsp;
{% endif %}
<a href="{% url 'task-details-setstatus' task.pk 'staged' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-sync-alt"></i> staged</a>&nbsp;
<a href="{% url 'task-details-setstatus' task.pk 'processed' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-sync-alt"></i> processed</a></td>&nbsp;
<a href="{% url 'task-details-setstatus' task.pk 'validated' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-sync-alt"></i> validated</a>&nbsp;
<a href="{% url 'task-details-setstatus' task.pk 'scrubbed' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-sync-alt"></i> scrubbed</a>&nbsp;
<a href="{% url 'task-details-setstatus' task.pk 'archived' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-sync-alt"></i> archived</a>&nbsp;
<a href="{% url 'task-details-setstatus' task.pk 'finished' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-sync-alt"></i> finished</a>&nbsp;
</tr>
</table>
{% endif %}
</div>
</div>
</div>
</div>
...@@ -3,40 +3,22 @@ ...@@ -3,40 +3,22 @@
{% block myBlock %} {% block myBlock %}
<div class="container"> <div class="container">
{% include "taskdatabase/task/status_panel.html" %}
<div class="row"> <div class="row">
<div class="col-sm">
<div class="card">
<div class="card-body">
<h3>Task: {{ task.id }}</h3>
<table class="table table-striped">
<tbody>
<tr><td><b>id</b></td><td><a href="{% url 'task-detail-view-api' task.pk %}" target="_blank">{{ task.id }} </a></td></tr>
<tr><td><b>status</b></td><td>{{ task.status }}</td></tr>
<td><b>tasks list</b></td><td><a href="{% url 'tasks-api' %}" class="btn btn-secondary btn-sm" role="button" target="_blank">REST API</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-sm"> <div class="col-sm">
<div class="card"> {% include "taskdatabase/task/details_card.html" %}
<div class="card-body">
<h3>Logentries: {{ task.id }}</h3>
<table class="table table-striped">
<tbody>
<tr><td><b>id</b></td><td><a href="{% url 'task-detail-view-api' task.pk %}" target="_blank">{{ task.id }} </a></td></tr>
<tr><td><b>status</b></td><td>{{ task.status }}</td></tr>
<td><b>tasks list</b></td><td><a href="{% url 'tasks-api' %}" class="btn btn-secondary btn-sm" role="button" target="_blank">REST API</a></td>
</tr>
</tbody>
</table>
</div>
</div> </div>
<div class="col-sm">
{% include "taskdatabase/task/logentries_card.html" %}
</div> </div>
</div> </div>
</div> </div>
{% include "taskdatabase/modal/modal_script.html" %}
{% include "taskdatabase/modal/modal.html" %}
{% endblock %} {% endblock %}
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<a class="btn btn-primary btn-sm" <a class="btn btn-primary btn-sm"
href="{% url 'task-details' task.id my_tasks.number %}" href="{% url 'task-details' task.id my_tasks.number %}"
data-popup-url="{% url 'task-details' task.id my_tasks.number %}" data-popup-url="{% url 'task-details' task.id my_tasks.number %}"
> Task > Details
</a> </a>
<a class="open-modal btn btn-primary btn-sm" <a class="open-modal btn btn-primary btn-sm"
...@@ -85,12 +85,6 @@ ...@@ -85,12 +85,6 @@
{% if task.status == "defining" %} {% if task.status == "defining" %}
<a href="{% url 'task-setstatus-view' task.pk 'defined' my_tasks.number %}" class="btn btn-success btn-sm" role="button">Stage</a> <a href="{% url 'task-setstatus-view' task.pk 'defined' my_tasks.number %}" class="btn btn-success btn-sm" role="button">Stage</a>
{% endif %} {% endif %}
<a href="{% url 'task-setstatus-view' task.pk 'staged' my_tasks.number %}" class="btn btn-secondary btn-sm" role="button"></i> staged</a>
<a href="{% url 'task-setstatus-view' task.pk 'processed' my_tasks.number %}" class="btn btn-secondary btn-sm" role="button">processed</a>
<a href="{% url 'task-setstatus-view' task.pk 'validated' my_tasks.number %}" class="btn btn-secondary btn-sm" role="button">validated</a>
<a href="{% url 'task-setstatus-view' task.pk 'scrubbed' my_tasks.number %}" class="btn btn-secondary btn-sm" role="button">scrubbed</a>
<a href="{% url 'task-setstatus-view' task.pk 'archived' my_tasks.number %}" class="btn btn-secondary btn-sm" role="button">archived</a>
<a href="{% url 'task-setstatus-view' task.pk 'finished' my_tasks.number %}" class="btn btn-secondary btn-sm" role="button">finished</a>
{% endif %} {% endif %}
{% if task.status == "processed" %} {% if task.status == "processed" %}
......
...@@ -6,7 +6,9 @@ urlpatterns = [ ...@@ -6,7 +6,9 @@ urlpatterns = [
# --- GUI --- # --- GUI ---
path('', views.IndexView.as_view(), name='homepage'), path('', views.IndexView.as_view(), name='homepage'),
path('/<page>', views.IndexView.as_view(), name='homepage_page'), path('/<page>', views.IndexView.as_view(), name='homepage_page'),
path('task_details/<int:id>/<page>', views.TaskDetails, name='task-details'), path('task_details/<int:id>/<page>', views.TaskDetails, name='task-details'),
path('task_details', views.TaskDetails, name='task-details'),
path('show-inputs/<int:id>/', views.ShowInputs, name='show-inputs'), path('show-inputs/<int:id>/', views.ShowInputs, name='show-inputs'),
path('show-outputs/<int:id>/', views.ShowOutputs, name='show-outputs'), path('show-outputs/<int:id>/', views.ShowOutputs, name='show-outputs'),
...@@ -42,6 +44,8 @@ urlpatterns = [ ...@@ -42,6 +44,8 @@ urlpatterns = [
# --- controller resources --- # --- controller resources ---
path('tasks/<int:pk>/setstatus/<new_status>/<page>', views.TaskSetStatus, name='task-setstatus-view'), path('tasks/<int:pk>/setstatus/<new_status>/<page>', views.TaskSetStatus, name='task-setstatus-view'),
path('tasks/<int:pk>/setstatus/<new_status>', views.TaskSetStatus, name='task-details-setstatus'),
path('tasks/<int:pk>/change_priority/<priority_change>/<page>', views.TaskChangePriority, name='task-change-priority'), path('tasks/<int:pk>/change_priority/<priority_change>/<page>', views.TaskChangePriority, name='task-change-priority'),
path('tasks/set_filter/<filter>', views.TaskSetFilter, name='task-set-filter'), path('tasks/set_filter/<filter>', views.TaskSetFilter, name='task-set-filter'),
......
...@@ -81,7 +81,9 @@ class LogEntryFilter(filters.FilterSet): ...@@ -81,7 +81,9 @@ class LogEntryFilter(filters.FilterSet):
model = LogEntry model = LogEntry
fields = { fields = {
'task__id': ['exact'],
'step_name': ['exact', 'icontains', 'in', 'startswith'], 'step_name': ['exact', 'icontains', 'in', 'startswith'],
'status': ['exact','in'],
} }
class ConfigurationFilter(filters.FilterSet): class ConfigurationFilter(filters.FilterSet):
...@@ -191,45 +193,34 @@ class TaskTables2View(SingleTableView): ...@@ -191,45 +193,34 @@ class TaskTables2View(SingleTableView):
table_class = TaskTable table_class = TaskTable
template_name = 'tables2/tables2.html' template_name = 'tables2/tables2.html'
# ---------- REST API views -----------
# example: /atdb/tasks/
class TaskListViewAPI(generics.ListCreateAPIView):
"""
A pagination list of tasks, unsorted.
"""
model = Task
queryset = Task.objects.all()
#serializer_class = TaskSerializer
# using the Django Filter Backend - https://django-filter.readthedocs.io/en/latest/index.html def convert_logentries_to_html(log_entries):
filter_backends = (filters.DjangoFilterBackend,) results = ""
filter_class = TaskFilter
def get_serializer_class(self): try:
if self.request.method in ['GET']: results += "<th>step</th><th>status</th><th>timestamp</th><th>cpu_cycles</th><th>wall_clock_time</th><th>logfile</th>"
return TaskReadSerializer results += "<tbody>"
for log in log_entries:
line = "<tr><td><b>" + log.step_name + '</b></td>'
line +='<td class="' + log.status + '" >' + log.status + "</td>"
line += "<td>" + str(log.timestamp) + "</td>"
line += "<td>" + str(log.cpu_cycles) + "</td>"
line += "<td>" + str(log.wall_clock_time) + "</td>"
if log.url_to_log_file!=None:
link = "<a href=" + '"' + str(log.url_to_log_file) + '">' + "logfile" + "</a>"
else: else:
return TaskWriteSerializer link = "-"
line += "<td>" + link + "</td>"
results += line
# example: /atdb/tasks/5/ results += "</tbody>"
# calling this view serializes a task in the REST API except:
class TaskDetailsViewAPI(generics.RetrieveUpdateDestroyAPIView): results = "<tr><td>no data</td></tr>"
"""
Detailed view of a task.
"""
model = Task
queryset = Task.objects.all()
# serializer_class = TaskSerializer
def get_serializer_class(self): return results
if self.request.method in ['GET']:
return TaskReadSerializer
else:
return TaskWriteSerializer
def TaskDetails(request, id, page): def TaskDetails(request, id=0, page=0):
try: try:
task = Task.objects.get(id=id) task = Task.objects.get(id=id)
...@@ -249,7 +240,11 @@ def TaskDetails(request, id, page): ...@@ -249,7 +240,11 @@ def TaskDetails(request, id, page):
# store the current page on the session # store the current page on the session
request.session['page'] = page request.session['page'] = page
return render(request, "taskdatabase/task/task_details.html", {'task': task })
log_entries = LogEntry.objects.filter(task=task)
logentries_html = convert_logentries_to_html(log_entries)
return render(request, "taskdatabase/task/task_details.html", {'task': task, 'logentries': logentries_html })
def convert_list_of_dicts_to_html(my_list): def convert_list_of_dicts_to_html(my_list):
...@@ -296,6 +291,49 @@ def ShowMetrics(request, id): ...@@ -296,6 +291,49 @@ def ShowMetrics(request, id):
return render(request, "taskdatabase/details/metrics.html", {'results': results}) return render(request, "taskdatabase/details/metrics.html", {'results': results})
def WorkflowDetails(request, id):
workflow = Workflow.objects.get(id=id)
return render(request, "taskdatabase/workflow/workflow_details.html", {'workflow': workflow})
# ---------- REST API views -----------
# example: /atdb/tasks/
class TaskListViewAPI(generics.ListCreateAPIView):
"""
A pagination list of tasks, unsorted.
"""
model = Task
queryset = Task.objects.all()
#serializer_class = TaskSerializer
# using the Django Filter Backend - https://django-filter.readthedocs.io/en/latest/index.html
filter_backends = (filters.DjangoFilterBackend,)
filter_class = TaskFilter
def get_serializer_class(self):
if self.request.method in ['GET']:
return TaskReadSerializer
else:
return TaskWriteSerializer
# example: /atdb/tasks/5/
# calling this view serializes a task in the REST API
class TaskDetailsViewAPI(generics.RetrieveUpdateDestroyAPIView):
"""
Detailed view of a task.
"""
model = Task
queryset = Task.objects.all()
# serializer_class = TaskSerializer
def get_serializer_class(self):
if self.request.method in ['GET']:
return TaskReadSerializer
else:
return TaskWriteSerializer
# example: /atdb/workflows/ # example: /atdb/workflows/
class WorkflowListViewAPI(generics.ListCreateAPIView): class WorkflowListViewAPI(generics.ListCreateAPIView):
model = Workflow model = Workflow
...@@ -312,11 +350,6 @@ class WorkflowDetailsViewAPI(generics.RetrieveUpdateDestroyAPIView): ...@@ -312,11 +350,6 @@ class WorkflowDetailsViewAPI(generics.RetrieveUpdateDestroyAPIView):
serializer_class = WorkflowSerializer serializer_class = WorkflowSerializer
def WorkflowDetails(request, id):
workflow = Workflow.objects.get(id=id)
return render(request, "taskdatabase/workflow/workflow_details.html", {'workflow': workflow})
# example: /atdb/logentries/ # example: /atdb/logentries/
class LogEntryListViewAPI(generics.ListCreateAPIView): class LogEntryListViewAPI(generics.ListCreateAPIView):
model = LogEntry model = LogEntry
...@@ -382,11 +415,17 @@ def Hold(request,pk,hold_it,page): ...@@ -382,11 +415,17 @@ def Hold(request,pk,hold_it,page):
return redirect('/atdb/?page='+page) return redirect('/atdb/?page='+page)
def TaskSetStatus(request,pk,new_status,page): def TaskSetStatus(request,pk,new_status,page=0):
model = Task model = Task
task = Task.objects.get(pk=pk) task = Task.objects.get(pk=pk)
task.new_status = new_status task.new_status = new_status
task.save() task.save()
if page==0:
# redirect to details screen
return redirect('/atdb/task_details/0/0')
else:
# redirect to tasks list
return redirect('/atdb/?page='+page) return redirect('/atdb/?page='+page)
...@@ -411,6 +450,7 @@ def TaskSetStatusTables2(request,pk,new_status,page): ...@@ -411,6 +450,7 @@ def TaskSetStatusTables2(request,pk,new_status,page):
task.save() task.save()
return redirect('/atdb/tables2/?page='+page) return redirect('/atdb/tables2/?page='+page)
# /atdb/get_size?status__in=defined,staged # /atdb/get_size?status__in=defined,staged
class GetSizeView(generics.ListAPIView): class GetSizeView(generics.ListAPIView):
queryset = Task.objects.all() queryset = Task.objects.all()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment