diff --git a/atdb/atdb/static/taskdatabase/ATDB-LDV Workflow Diagram.png b/atdb/atdb/static/taskdatabase/ATDB-LDV Workflow Diagram.png index 32eb9a99e93f9fc7f7310005c55f7f21e14c4540..ec891fc069c43f3dd26510872329bf10775db1ac 100644 Binary files a/atdb/atdb/static/taskdatabase/ATDB-LDV Workflow Diagram.png and b/atdb/atdb/static/taskdatabase/ATDB-LDV Workflow Diagram.png differ diff --git a/atdb/atdb/static/taskdatabase/style.css b/atdb/atdb/static/taskdatabase/style.css index b927c9663aa7ee0883ebf3c4f2c97636a3cc0850..e3b90a877ba6478a82cf72635f7f15d96d85d61b 100644 --- a/atdb/atdb/static/taskdatabase/style.css +++ b/atdb/atdb/static/taskdatabase/style.css @@ -49,7 +49,7 @@ TD { font-weight: bold; } -.scrubbed, { +.scrubbed { color: darkgray; font-style: italic; } @@ -141,4 +141,11 @@ p.title { .poor { color: red; font-weight: bold; -} \ No newline at end of file +} + +#search_box +{ + color: darkblue; + display: inline-block; + vertical-align: middle; +} diff --git a/atdb/docs/ATDB-LDV Data Model.png b/atdb/docs/ATDB-LDV Data Model.png index 63080e2b4a8ee77fde265f7c52d8c3d0402d8da7..2cb5d5ba14cc4cb74d94a9bb26ee581ee8a90e3b 100644 Binary files a/atdb/docs/ATDB-LDV Data Model.png and b/atdb/docs/ATDB-LDV Data Model.png differ diff --git a/atdb/docs/ATDB-LDV GUI.png b/atdb/docs/ATDB-LDV GUI.png index 0b9c98a9d0a8fc781eca59ee7918d39a957a2044..fdeaf2e5ff4a6bb0856e4016ace4de329e89ff8f 100644 Binary files a/atdb/docs/ATDB-LDV GUI.png and b/atdb/docs/ATDB-LDV GUI.png differ diff --git a/atdb/docs/ATDB-LDV Workflow Diagram.png b/atdb/docs/ATDB-LDV Workflow Diagram.png index 2ef5b467bffbb3b10197899e0bcbbf8ffa66c6dc..98aff9e99489be16e269b65a204bcf2d15754e73 100644 Binary files a/atdb/docs/ATDB-LDV Workflow Diagram.png and b/atdb/docs/ATDB-LDV Workflow Diagram.png differ diff --git a/atdb/logs/atdb.log b/atdb/logs/atdb.log index 06ea631700c580a41acd0b847a83c52ebef045a9..c47e73e3ebb4a84d419fdd911fc3fa88fe26c51e 100644 --- a/atdb/logs/atdb.log +++ b/atdb/logs/atdb.log @@ -54,3 +54,19 @@ logging[14/Apr/2023 14:17:24,827] unsupported operand type(s) for +=: 'NoneType' [04/May/2023 14:35:52,193] task 25378 - (regular) - 116876 has no plots, skipped. [04/May/2023 14:35:52,294] 'NoneType' object is not subscriptable [04/May/2023 14:35:52,294] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:20,610] 'NoneType' object is not subscriptable +[09/May/2023 08:47:20,610] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:20,725] 'NoneType' object is not subscriptable +[09/May/2023 08:47:20,725] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:20,822] 'NoneType' object is not subscriptable +[09/May/2023 08:47:20,823] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:20,932] 'NoneType' object is not subscriptable +[09/May/2023 08:47:20,933] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:32,444] 'NoneType' object is not subscriptable +[09/May/2023 08:47:32,445] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:33,063] 'NoneType' object is not subscriptable +[09/May/2023 08:47:33,064] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:33,649] 'NoneType' object is not subscriptable +[09/May/2023 08:47:33,650] task 25378 - (regular) - 116876 has no plots, skipped. +[09/May/2023 08:47:34,165] 'NoneType' object is not subscriptable +[09/May/2023 08:47:34,165] task 25378 - (regular) - 116876 has no plots, skipped. diff --git a/atdb/taskdatabase/forms.py b/atdb/taskdatabase/forms.py index c6c3ec4eda3308820bb9627564f16b492443bef8..79d1160c3f085f8a78f15ef04b76d1af9bc0a430 100644 --- a/atdb/taskdatabase/forms.py +++ b/atdb/taskdatabase/forms.py @@ -1,9 +1,11 @@ from django import forms class QualityAnnotationForm(forms.Form): - annotation = forms.CharField(label='', - widget=forms.Textarea( - attrs={'rows': 12,'cols': 85} - ), - max_length=1000) + annotation = forms.CharField(label='', widget=forms.Textarea(attrs={'rows': 12,'cols': 85}),required=False,max_length=1000) return_to_page = forms.IntegerField(widget=forms.HiddenInput) + + +class DiscardAnnotationForm(forms.Form): + annotation = forms.CharField(label='', widget=forms.Textarea(attrs={'rows': 3, 'cols': 85}), required=False, + max_length=250) + return_to_page = forms.IntegerField(widget=forms.HiddenInput) diff --git a/atdb/taskdatabase/migrations/0023_task_cleanup_policy.py b/atdb/taskdatabase/migrations/0023_task_cleanup_policy.py new file mode 100644 index 0000000000000000000000000000000000000000..36b2db5366cd26a89c07c6747a3bf1e05d91223f --- /dev/null +++ b/atdb/taskdatabase/migrations/0023_task_cleanup_policy.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.4 on 2023-05-04 09:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('taskdatabase', '0022_workflow_tag'), + ] + + operations = [ + migrations.AddField( + model_name='task', + name='cleanup_policy', + field=models.CharField(blank=True, max_length=30, null=True), + ), + ] diff --git a/atdb/taskdatabase/migrations/0024_auto_20230509_1612.py b/atdb/taskdatabase/migrations/0024_auto_20230509_1612.py new file mode 100644 index 0000000000000000000000000000000000000000..31b8ee24282a885820b542717a9428e4247695f2 --- /dev/null +++ b/atdb/taskdatabase/migrations/0024_auto_20230509_1612.py @@ -0,0 +1,20 @@ +# Generated by Django 3.1.4 on 2023-05-09 14:12 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('taskdatabase', '0023_task_cleanup_policy'), + ] + + operations = [ + migrations.AlterField( + model_name='task', + name='workflow', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='taskdatabase.workflow'), + preserve_default=False, + ), + ] diff --git a/atdb/taskdatabase/migrations/0025_auto_20230509_1631.py b/atdb/taskdatabase/migrations/0025_auto_20230509_1631.py new file mode 100644 index 0000000000000000000000000000000000000000..b3ae0c53ad0f1a2b1a9a9c5206999ceff9cfb5fe --- /dev/null +++ b/atdb/taskdatabase/migrations/0025_auto_20230509_1631.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.4 on 2023-05-09 14:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('taskdatabase', '0024_auto_20230509_1612'), + ] + + operations = [ + migrations.AlterField( + model_name='task', + name='workflow', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='taskdatabase.workflow'), + ), + ] diff --git a/atdb/taskdatabase/models.py b/atdb/taskdatabase/models.py index 4c0661303500578aa38c996a77412d872e097ee4..4fac9471f1cc1360d2dd967d33c5c79c8157156e 100644 --- a/atdb/taskdatabase/models.py +++ b/atdb/taskdatabase/models.py @@ -25,7 +25,7 @@ class Workflow(models.Model): prefetch = models.BooleanField(null=True, default=True) def __str__(self): - return str(self.id) + return str(self.id) + ' - ' + str(self.workflow_uri) # convert the quality information from the JSONfield into a easy parsable list for the template @@ -73,7 +73,6 @@ class Task(models.Model): # Task control properties task_type = models.CharField(max_length=20, default="regular") filter = models.CharField(max_length=30, blank=True, null=True) - #environment = models.JSONField(null=True, blank=True) environment = models.CharField(max_length=255, blank=True, null=True) new_status = models.CharField(max_length=50, default="defining", null=True) status = models.CharField(db_index=True, default="unknown", max_length=50,blank=True, null=True) @@ -84,6 +83,7 @@ class Task(models.Model): priority = models.IntegerField(default=100, null=True) purge_policy = models.CharField(max_length=5, default="no", blank=True, null=True) + cleanup_policy = models.CharField(max_length=30, blank=True, null=True) stage_request_id = models.IntegerField(null=True) # LOFAR properties @@ -101,7 +101,7 @@ class Task(models.Model): total_processing_time = models.IntegerField(default=0, null=True, blank=True) # relationships - workflow = models.ForeignKey(Workflow, related_name='tasks', on_delete=models.SET_NULL, null=True, blank=True) + workflow = models.ForeignKey(Workflow, related_name='tasks', on_delete=models.CASCADE, null=True, blank=True) predecessor = models.ForeignKey('self', related_name='successors', on_delete=models.SET_NULL, null=True, blank=True) def __str__(self): @@ -241,12 +241,23 @@ class Task(models.Model): @property def sasid_is_verified(self): - for task in Task.objects.filter(sas_id=self.sas_id): if task.status not in verified_statusses: return False return True + # NV: this shows the latest status change, but because it is a derived property it cannot be sorted. + # This functionality was not requested, and to avoid additional requests about 'sort' functionalty + # it is currently commented out. Could be of use later though, so I leave it in for now. + # @property + # def latest_change(self): + # qs = Status.objects.filter(task__id=self.id).order_by('-timestamp') + # if len(qs) > 0: + # status = qs[0] + # timestamp = status.timestamp + # + # return timestamp + class LogEntry(models.Model): cpu_cycles = models.IntegerField(null=True,blank=True) diff --git a/atdb/taskdatabase/serializers.py b/atdb/taskdatabase/serializers.py index d12f0229bcae30c6e944cab4c853980b7fe6aef3..b7aec35769c4465710e5d6033646e403c861a0dd 100644 --- a/atdb/taskdatabase/serializers.py +++ b/atdb/taskdatabase/serializers.py @@ -1,7 +1,6 @@ from rest_framework import serializers from .models import Status, Task, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor, LatestMonitor - class WorkflowSerializer(serializers.ModelSerializer): class Meta: @@ -39,7 +38,7 @@ class TaskWriteSerializer(serializers.ModelSerializer): class Meta: model = Task fields = ('id','task_type','filter','predecessor','successors', - 'project','sas_id','priority','purge_policy','resume', + 'project','sas_id','priority','purge_policy','cleanup_policy','resume', 'new_workflow_id','new_workflow_uri','workflow', 'stage_request_id', 'status','new_status','quality', @@ -59,7 +58,6 @@ class TaskWriteSerializer(serializers.ModelSerializer): workflow_uri = self.initial_data['new_workflow_uri'] if workflow_uri: - #workflow_uri = validated_data['new_workflow_uri'] workflow = Workflow.objects.get(workflow_uri=workflow_uri) task.workflow = workflow task.save() @@ -94,7 +92,7 @@ class TaskReadSerializer(serializers.ModelSerializer): model = Task fields = ['id','task_type','creationTime','filter', 'predecessor','predecessor_status','successors', - 'project','sas_id','priority','purge_policy','resume', + 'project','sas_id','priority','purge_policy','cleanup_policy','resume', 'workflow', 'stage_request_id', 'status','new_status','quality', @@ -125,13 +123,12 @@ class TaskReadSerializerFast(serializers.ModelSerializer): class Meta: model = Task fields = ['id','task_type','creationTime','filter','predecessor','predecessor_status', - 'project','sas_id','priority','purge_policy','resume', + 'project','sas_id','priority','purge_policy','cleanup_policy','resume', 'workflow', 'stage_request_id', 'status','new_status','quality', 'inputs','outputs','metrics','archive', 'size_to_process', 'size_processed', 'total_processing_time', - ] read_only_fields = fields diff --git a/atdb/taskdatabase/services/algorithms.py b/atdb/taskdatabase/services/algorithms.py index 61c31d77251d5d4b16ba236c6405b6770e7782cb..428662350e76a3896c5e69e9bce65db729f88a6b 100644 --- a/atdb/taskdatabase/services/algorithms.py +++ b/atdb/taskdatabase/services/algorithms.py @@ -829,7 +829,7 @@ def construct_summary(task): line += '<tr><td colspan="3">' for filename in added: line += '<tr><td colspan="3">' + filename + '<td></tr>' - except: + except Exception as error: pass try: @@ -838,14 +838,13 @@ def construct_summary(task): line += '<th>Deleted</th>' for filename in deleted: line += '<tr><td colspan="3">' +filename + '<td></tr>' - - except: + except Exception as error: pass results += line - except: - pass + except Exception as error: + logger.error(error) totals += '<th>Totals</th><th></th><th></th>' totals += '<tr><td colspan="2"><b>Input size</b></td><td>' + str(total_size_input) + '</td></tr>' diff --git a/atdb/taskdatabase/static/taskdatabase/ATDB-LDV Workflow Diagram.png b/atdb/taskdatabase/static/taskdatabase/ATDB-LDV Workflow Diagram.png index 32eb9a99e93f9fc7f7310005c55f7f21e14c4540..ec891fc069c43f3dd26510872329bf10775db1ac 100644 Binary files a/atdb/taskdatabase/static/taskdatabase/ATDB-LDV Workflow Diagram.png and b/atdb/taskdatabase/static/taskdatabase/ATDB-LDV Workflow Diagram.png differ diff --git a/atdb/taskdatabase/static/taskdatabase/style.css b/atdb/taskdatabase/static/taskdatabase/style.css index b927c9663aa7ee0883ebf3c4f2c97636a3cc0850..6ca2e94521d94a8ec94f9977d1fc8facfd3efcb7 100644 --- a/atdb/taskdatabase/static/taskdatabase/style.css +++ b/atdb/taskdatabase/static/taskdatabase/style.css @@ -49,7 +49,7 @@ TD { font-weight: bold; } -.scrubbed, { +.scrubbed { color: darkgray; font-style: italic; } @@ -141,4 +141,16 @@ p.title { .poor { color: red; font-weight: bold; +} + +#search_box +{ + color: darkblue; + display: inline-block; + vertical-align: middle; +} + +.img { + color: white; + font-family: "Courier New"; } \ No newline at end of file diff --git a/atdb/taskdatabase/tables.py b/atdb/taskdatabase/tables.py index 8390b260a02d5baff6b78907f9dea31b13a2d212..b8ad9471f10a72409740e54a11b7d114e864e97d 100644 --- a/atdb/taskdatabase/tables.py +++ b/atdb/taskdatabase/tables.py @@ -25,7 +25,7 @@ class TaskTable(tables.Table): class Meta: model = Task template_name = "django_tables2/bootstrap4.html" - fields = ("id", "workflow","filter","priority","status","quality","project","sas_id","resume","actions","buttons") + fields = ("id", "workflow.id","filter","priority","status","quality","project","sas_id","resume","actions","buttons") # columns that need specific rendering status = StatusColumn() diff --git a/atdb/taskdatabase/templates/astronauth/navbar.html b/atdb/taskdatabase/templates/astronauth/navbar.html index 8b9121f1ed80811702f20c57ddffabcbd4bf9f28..02b3cf1f2168d17136d4b62e9fa2dd921b43735a 100644 --- a/atdb/taskdatabase/templates/astronauth/navbar.html +++ b/atdb/taskdatabase/templates/astronauth/navbar.html @@ -28,6 +28,7 @@ <li><a class="nav-link" href="{% url 'quality' %}">Quality</a></li> <li><a class="nav-link" href="{% url 'validation' %}">Validation</a></li> <li><a class="nav-link" href="{% url 'failures' %}">Failures</a></li> + <li><a class="nav-link" href="{% url 'discarded' %}">Discarded</a></li> <li><a class="nav-link" href="{% url 'finished' %}">Finished</a></li> <li><a class="nav-link" href="{% url 'monitoring' %}">Monitoring</a></li> <li><a class="nav-link" href="{% url 'diagram' %}">Diagram</a></li> diff --git a/atdb/taskdatabase/templates/taskdatabase/archived/tasks.html b/atdb/taskdatabase/templates/taskdatabase/archived/tasks.html index 40d040726da1185196d61a31c4020442b38cc3d8..4725101ecd71a85212d8a6a84c7ab6265ba57186 100644 --- a/atdb/taskdatabase/templates/taskdatabase/archived/tasks.html +++ b/atdb/taskdatabase/templates/taskdatabase/archived/tasks.html @@ -26,9 +26,9 @@ </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"><i class="fas fa-project-diagram"></i> {{ task.workflow }} + href="{% url 'workflow-details' task.workflow.id %}" + data-popup-url="{% url 'workflow-details' task.workflow.id %}" + target="_blank"><i class="fas fa-project-diagram"></i> {{ task.workflow.id }} </a></td> </td> {% if task.resume %} diff --git a/atdb/taskdatabase/templates/taskdatabase/discarded/clear_filter_button.html b/atdb/taskdatabase/templates/taskdatabase/discarded/clear_filter_button.html new file mode 100644 index 0000000000000000000000000000000000000000..9e843a842e62f6d79bc04615a0fae156856baaef --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/discarded/clear_filter_button.html @@ -0,0 +1 @@ +<a href="{% url 'clear-filter' 'discarded' %}" class="btn btn-success btn-sm" role="button"><i class="fas fa-window-close"></i> Clear Filter</a> diff --git a/atdb/taskdatabase/templates/taskdatabase/discarded/headers.html b/atdb/taskdatabase/templates/taskdatabase/discarded/headers.html new file mode 100644 index 0000000000000000000000000000000000000000..6a08ee853f618b2662896c47c2b5512ce210dc97 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/discarded/headers.html @@ -0,0 +1,30 @@ +<tr> + <th width="5%"> + <a href="{% url 'sort-tasks' '-pk' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + ID + <a href="{% url 'sort-tasks' 'id' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th>Details</th> + <th width="8%"> + <a href="{% url 'sort-tasks' '-status' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Status + <a href="{% url 'sort-tasks' 'status' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th width="8%"> + <a href="{% url 'sort-tasks' '-project' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Project + <a href="{% url 'sort-tasks' 'project' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th width="8%"> + <a href="{% url 'sort-tasks' '-sas_id' 'discarded' %}" 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' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th> + <a href="{% url 'sort-tasks' '-filter' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> + Filter + <a href="{% url 'sort-tasks' 'filter' 'discarded' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> + </th> + <th>Cleanup Policy</th> + <th>Reason</th> +</tr> \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/discarded/page.html b/atdb/taskdatabase/templates/taskdatabase/discarded/page.html new file mode 100644 index 0000000000000000000000000000000000000000..66a827c72a00d134adceac4362d6677d54cc2b88 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/discarded/page.html @@ -0,0 +1,57 @@ +{% 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"> + <h3>Discarded</h3> + These the discarded tasks, invisible in the rest of ATDB. + <hr> + <table> + <tr> + <td>{% include "taskdatabase/discarded/clear_filter_button.html" %}</td> + <td>{% include 'taskdatabase/filter/search.html' %}</td> + </tr> + </table> + <hr> + </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/discarded/headers.html' %} + </thead> + <tbody> + {% include 'taskdatabase/discarded/tasks.html' %} + </tbody> + </table> + {% else %} + <p>No recent Tasks.</p> + {% endif %} + + </div> + </div> + {% include 'taskdatabase/pagination.html' %} + </div> + </div> + </div> + </div> +</div> + +{% include 'taskdatabase/no_refresh.html' %} + + +{% endblock %} + diff --git a/atdb/taskdatabase/templates/taskdatabase/discarded/tasks.html b/atdb/taskdatabase/templates/taskdatabase/discarded/tasks.html new file mode 100644 index 0000000000000000000000000000000000000000..ab93845beb36597730d7519419715bf5da19c47c --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/discarded/tasks.html @@ -0,0 +1,48 @@ +{% load static %} +{% for task in my_tasks %} + + {% if task.status != "removed_invisible" %} + <div class="row"> + <tr> + + <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 %} + {% if task.has_quality %} + <a class="open-modal 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"></i> Quality + </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> + <td>{{ task.cleanup_policy }} </td> + <td>{{ task.remarks.discard_reason }} </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/failures/confirm_discard.html b/atdb/taskdatabase/templates/taskdatabase/failures/confirm_discard.html new file mode 100644 index 0000000000000000000000000000000000000000..8f30325f106e5f2e562216e76671b01a54527ce2 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/failures/confirm_discard.html @@ -0,0 +1,29 @@ +{% extends 'taskdatabase/base.html' %} + +{% block myBlock %} +<div class="container-fluid details-container"> + + + <div class="card"> + <div class="card-body"> + + <form action="./{{ page }}" method="POST">{% csrf_token %} + <div class="text-center"> + <h5>Are you sure you want to discard task {{ task.id }}?</h5> + Enter a reason for discarding (optional) + {% csrf_token %} + + <div> + {{ my_form }} + </div> + <p> + <button class="btn btn-success btn-sm" type="submit"><i class="fas fa-check"></i> OK</button> + <a href="{% url 'failures' %}" class="btn btn-warning btn-sm" role="button"><i class="fas fa-times-circle"></i> Cancel</a>  + </p> + </div> + </form> + + </div> + </div> +</div> +{% endblock %} \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/failures/tasks.html b/atdb/taskdatabase/templates/taskdatabase/failures/tasks.html index 51bd7cabba1fc72a5ae5fea04e123f93f51f29f8..09c33c875749551bcac92051cfc7a0365828a451 100644 --- a/atdb/taskdatabase/templates/taskdatabase/failures/tasks.html +++ b/atdb/taskdatabase/templates/taskdatabase/failures/tasks.html @@ -20,7 +20,7 @@ <a class="open-modal 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 + ><i class="fas fa-balance-scale"></i> Quality </a> {% endif %} </td> @@ -38,7 +38,10 @@ <td>{{ task.filter }} </td> - <td>{% include "taskdatabase/failures/retry_buttons.html" %}</td> + <td> + {% include "taskdatabase/failures/retry_buttons.html" %} + <a href="{% url 'task-discard-view' task.pk 'discarded' my_tasks.number %}" class="btn btn-danger btn-sm" role="button"><i class="fas fa-trash-alt"></i> Discard</a> + </td> </tr> </div> diff --git a/atdb/taskdatabase/templates/taskdatabase/index.html b/atdb/taskdatabase/templates/taskdatabase/index.html index b07f8df8b389f31f9c84c1889a8dfa92dad48149..38abbccf3af932c550035ecc10009419b79ce094 100644 --- a/atdb/taskdatabase/templates/taskdatabase/index.html +++ b/atdb/taskdatabase/templates/taskdatabase/index.html @@ -8,35 +8,30 @@ {% include 'taskdatabase/filter/filter_buttons.html' %} <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_headers.html' %} - </thead> - <tbody> - {% include 'taskdatabase/tasks.html' %} - </tbody> - </table> - {% else %} - <p>No recent Tasks.</p> - {% endif %} - + <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_headers.html' %} + </thead> + <tbody> + {% include 'taskdatabase/tasks.html' %} + </tbody> + </table> + {% else %} + <p>No recent Tasks.</p> + {% endif %} + </div> </div> + {% include 'taskdatabase/pagination.html' %} </div> - {% include 'taskdatabase/pagination.html' %} - </div> </div> - - <p class="footer"> Version 2 May 2023 - + <p class="footer"> Version 9 May 2023 </div> {% include 'taskdatabase/refresh.html' %} diff --git a/atdb/taskdatabase/templates/taskdatabase/quality/filter_buttons.html b/atdb/taskdatabase/templates/taskdatabase/quality/filter_buttons.html index 31c387bda9fa043195290a2280476d9b03b9a1bd..106a504477671503cb8bb9a4851a8b6faea696f7 100644 --- a/atdb/taskdatabase/templates/taskdatabase/quality/filter_buttons.html +++ b/atdb/taskdatabase/templates/taskdatabase/quality/filter_buttons.html @@ -16,19 +16,19 @@ <tr> <td> {% include "taskdatabase/quality/clear_filter_button.html" %} - <a href="{% url 'task-set-filter' 'failed' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-layer-group"></i> Failed</a> - <a href="{% url 'task-set-onhold-filter' True 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-layer-group"></i> On Hold</a> - - <a href="{% url 'task-set-filter' 'processed' 'quality' %}" class="btn btn-secondary btn-sm" role="button">processed</a> - <a href="{% url 'task-set-filter' 'storing' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i>storing</i></a> - <a href="{% url 'task-set-filter' 'stored' 'quality' %}" class="btn btn-secondary btn-sm" role="button">stored</a> - <a href="{% url 'task-set-filter' 'validated' 'quality' %}" class="btn btn-secondary btn-sm" role="button">validated</a> - <a href="{% url 'task-set-filter' 'scrubbing' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i>scrubbing</i></a> - <a href="{% url 'task-set-filter' 'scrubbed' 'quality' %}" class="btn btn-secondary btn-sm" role="button">scrubbed</a> - <a href="{% url 'task-set-filter' 'archiving' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i>archiving</i></a> - <a href="{% url 'task-set-filter' 'archived' 'quality' %}" class="btn btn-secondary btn-sm" role="button">archived</a> - <a href="{% url 'task-set-filter' 'finished' 'quality' %}" class="btn btn-secondary btn-sm" role="button">finished</a> - <a href="{% url 'task-set-filter' 'suspended' 'quality' %}" class="btn btn-secondary btn-sm" role="button">suspended</a> + <a href="{% url 'task-set-filter' 'failed' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-layer-group"></i> Failed</a> + <a href="{% url 'task-set-onhold-filter' True 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-layer-group"></i> On Hold</a> + + <a href="{% url 'task-set-filter' 'processed' 'quality' %}" class="btn btn-secondary btn-sm" role="button">processed</a> + <a href="{% url 'task-set-filter' 'storing' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i>storing</i></a> + <a href="{% url 'task-set-filter' 'stored' 'quality' %}" class="btn btn-secondary btn-sm" role="button">stored</a> + <a href="{% url 'task-set-filter' 'validated' 'quality' %}" class="btn btn-secondary btn-sm" role="button">validated</a> + <a href="{% url 'task-set-filter' 'scrubbing' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i>scrubbing</i></a> + <a href="{% url 'task-set-filter' 'scrubbed' 'quality' %}" class="btn btn-secondary btn-sm" role="button">scrubbed</a> + <a href="{% url 'task-set-filter' 'archiving' 'quality' %}" class="btn btn-secondary btn-sm" role="button"><i>archiving</i></a> + <a href="{% url 'task-set-filter' 'archived' 'quality' %}" class="btn btn-secondary btn-sm" role="button">archived</a> + <a href="{% url 'task-set-filter' 'finished' 'quality' %}" class="btn btn-secondary btn-sm" role="button">finished</a> + <a href="{% url 'task-set-filter' 'suspended' 'quality' %}" class="btn btn-secondary btn-sm" role="button">suspended</a> </td> <td> diff --git a/atdb/taskdatabase/templates/taskdatabase/query/confirm_discard.html b/atdb/taskdatabase/templates/taskdatabase/query/confirm_discard.html new file mode 100644 index 0000000000000000000000000000000000000000..a0381cce143b58ddd665f00888356284cf816376 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/query/confirm_discard.html @@ -0,0 +1,31 @@ +{% extends 'taskdatabase/base.html' %} + +{% block myBlock %} +<div class="container-fluid details-container"> + + + <div class="card"> + <div class="card-body"> + + <form action="./{{ new_value }}" method="POST">{% csrf_token %} + <div class="text-center"> + + <h5> Are you sure you want to discard ({{ count }}) tasks ?</h5> + Enter a reason for discarding (optional) + {% csrf_token %} + + <div> + {{ my_form }} + </div> + + <p> + <button class="btn btn-success btn-sm" type="submit"><i class="fas fa-check"></i> OK</button> + <a href="{% url 'query' %}" class="btn btn-warning btn-sm" role="button"><i class="fas fa-times-circle"></i> Cancel</a>  + </p> + </div> + </form> + + </div> + </div> +</div> +{% endblock %} \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/query/set_multi_status_panel.html b/atdb/taskdatabase/templates/taskdatabase/query/set_multi_status_panel.html index c84b49815e541d29626ded47c809e9ad4aaad462..d0110b2fae03dbeac3120bea9c98e13cb3e43690 100644 --- a/atdb/taskdatabase/templates/taskdatabase/query/set_multi_status_panel.html +++ b/atdb/taskdatabase/templates/taskdatabase/query/set_multi_status_panel.html @@ -20,7 +20,7 @@ <a href="{% url 'task-multi-setstatus' 'archived' request.GET %}" class="btn btn-danger btn-sm" role="button"><i class="fas fa-sync-alt"></i> archived</a> <a href="{% url 'task-multi-setstatus' 'finished' request.GET %}" class="btn btn-danger btn-sm" role="button"><i class="fas fa-sync-alt"></i> finished</a> <a href="{% url 'task-multi-setstatus' 'suspended' request.GET %}" class="btn btn-danger btn-sm" role="button"><i class="fas fa-sync-alt"></i> suspended</a> - + <a href="{% url 'task-multi-setstatus' 'discarded' request.GET %}" class="btn btn-danger btn-sm" role="button"><i class="fas fa-trash-alt"></i> discard</a> </tr> </table> {% endif %} diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks.html b/atdb/taskdatabase/templates/taskdatabase/tasks.html index 6aacb705d5498377b213dfa4d2707d59e50be156..f3147466eee459c4be083a81c9eb7c08b574993b 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks.html @@ -1,6 +1,6 @@ {% load static %} {% for task in my_tasks %} - {% if task.status != "removed_invisible" %} + {% if task.status != "discarded" %} <div class="row"> <tr class="{{ task.status }}"> @@ -26,9 +26,9 @@ </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"><i class="fas fa-project-diagram"></i> {{ task.workflow }} + href="{% url 'workflow-details' task.workflow.id %}" + data-popup-url="{% url 'workflow-details' task.workflow.id %}" + target="_blank"><i class="fas fa-project-diagram"></i> {{ task.workflow.id }} </a></td> </td> <td> @@ -47,7 +47,7 @@ {% if not task.resume %} <td class="bigger">{{ task.status }} (holding)</td> {% endif %} - +<!-- <td>{{ task.latest_change|date:"Y-m-d H:i:s" }}</td>--> <td>{{ task.project }}</td> <td>{{ task.sas_id }}</td> <td>{{ task.filter }} </td> diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html b/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html index 54f6a7844161168f89d0b84ff507b8e6fda2da70..3daf2386b259fd302d334c819d55f0a894fa5e52 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks/details_card.html @@ -19,8 +19,8 @@ <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 %}" + href="{% url 'workflow-details' task.workflow.id %}" + data-popup-url="{% url 'workflow-details' task.workflow.id %}" target="_blank"><i class="fas fa-project-diagram"></i> {{ task.workflow }} </a> {% if user.is_staff %} @@ -63,12 +63,13 @@ <tr><td><b>creationTime</b></td><td>{{ task.creationTime|date:"Y-m-d H:i:s" }}</td></tr> <tr><td><b>purge_policy</b></td><td>{{ task.purge_policy }}</td></tr> + <tr><td><b>cleanup_policy</b></td><td>{{ task.cleanup_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> - + <tr><td><b>remarks</b></td><td>{{ task.remarks }}</td></tr> </tbody> </table> </div> diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html b/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html index 638e9c8f637421ae56f2f2705a24b33da98ec439..cb2ae6ecd7e4b79d4a9d0a8df29782f12e9bf1eb 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks_headers.html @@ -21,6 +21,7 @@ Status <a href="{% url 'sort-tasks' 'status' 'atdb' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-down"></i></a> </th> +<!-- <th>Latest Change</th>--> <th> <a href="{% url 'sort-tasks' '-project' 'atdb' %}" class="btn btn-light btn-sm" role="button"><i class="fas fa-sort-up"></i></a> Project diff --git a/atdb/taskdatabase/templates/taskdatabase/validation/confirm_discard.html b/atdb/taskdatabase/templates/taskdatabase/validation/confirm_discard.html new file mode 100644 index 0000000000000000000000000000000000000000..add183b0b428bdb6fd6e8fc139d66cdf4fd6ca99 --- /dev/null +++ b/atdb/taskdatabase/templates/taskdatabase/validation/confirm_discard.html @@ -0,0 +1,31 @@ +{% extends 'taskdatabase/base.html' %} + +{% block myBlock %} +<div class="container-fluid details-container"> + + + <div class="card"> + <div class="card-body"> + + <form action="./{{ page }}" method="POST">{% csrf_token %} + <div class="text-center"> + + <h5> Are you sure you want to discard all ({{ count }}) tasks with SAS_ID {{ sas_id }}?</h5> + Enter a reason for discarding (optional) + {% csrf_token %} + + <div> + {{ my_form }} + </div> + + <p> + <button class="btn btn-success btn-sm" type="submit"><i class="fas fa-check"></i> OK</button> + <a href="{% url 'validation' %}" class="btn btn-warning btn-sm" role="button"><i class="fas fa-times-circle"></i> Cancel</a>  + </p> + </div> + </form> + + </div> + </div> +</div> +{% endblock %} \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/validation/headers.html b/atdb/taskdatabase/templates/taskdatabase/validation/headers.html index 7eba892199d051f15e51caa196417972e2f589aa..9cd3a073b39d0ad794b25d34a6467e172c84f693 100644 --- a/atdb/taskdatabase/templates/taskdatabase/validation/headers.html +++ b/atdb/taskdatabase/templates/taskdatabase/validation/headers.html @@ -22,4 +22,5 @@ <th>Annotate</th> <th>Quality</th> <th>Validate (choose a Q)</th> + <th>Discard</th> </tr> \ No newline at end of file diff --git a/atdb/taskdatabase/templates/taskdatabase/validation/tasks.html b/atdb/taskdatabase/templates/taskdatabase/validation/tasks.html index d89f7fa7d330a4da131128cca864fcccabe19161..b4517b9fc7536c5547f577a7d5569e43284651f8 100644 --- a/atdb/taskdatabase/templates/taskdatabase/validation/tasks.html +++ b/atdb/taskdatabase/templates/taskdatabase/validation/tasks.html @@ -35,9 +35,9 @@ {% if task.has_summary %} <td> <a class="open-modal btn btn-primary btn-sm" - href="{% url 'summary' task.id my_tasks.number %}" data-popup-url="{% url 'summary' task.id my_tasks.number %}"> - <img src="{% static 'taskdatabase/ldvlogo_small.png' %}" height="20" alt="summary"> SUM + <img src="{% static 'taskdatabase/ldvlogo_small.png' %}" height="20" alt="summary"> + <font color="white"> SUM</font> </a> </td> {% else %} @@ -68,7 +68,7 @@ </td> <td class="{{ task.quality }}">{{ task.quality|default_if_none:"-" }}</td> <td>{% include "taskdatabase/validation/validation_buttons.html" %}</td> - + <td><a href="{% url 'task-discard-view-sasid' task.pk 'discarded' my_tasks.number %}" class="btn btn-danger btn-sm" role="button"><i class="fas fa-trash-alt"></i></a></td> </tr> </div> {% endif %} diff --git a/atdb/taskdatabase/urls.py b/atdb/taskdatabase/urls.py index 221d39ac911e24a19cd698493a7564de432c4c8a..faeda24a365005247690e5bf00e5e791ac14d2b7 100644 --- a/atdb/taskdatabase/urls.py +++ b/atdb/taskdatabase/urls.py @@ -18,6 +18,7 @@ urlpatterns = [ path('quality', views.ShowQualityPage.as_view(), name='quality'), path('validation', views.ShowValidationPage.as_view(), name='validation'), path('failures', views.ShowFailuresPage.as_view(), name='failures'), + path('discarded', views.ShowDiscardedPage.as_view(), name='discarded'), path('finished', views.ShowFinishedPage.as_view(), name='finished'), path('task_details/<int:id>/<page>', views.TaskDetails, name='task-details'), @@ -95,7 +96,9 @@ urlpatterns = [ path('tasks/<int:pk>/setstatus/<new_status>', views.TaskSetStatus, name='task-details-setstatus'), path('tasks/<int:pk>/validate/<quality>/<new_status>/<page>', views.TaskValidate, name='task-validate-view'), - path('tasks/<int:pk>/retry//<new_status>/<page>', views.TaskRetry, name='task-retry-view'), + path('tasks/<int:pk>/retry/<new_status>/<page>', views.TaskRetry, name='task-retry-view'), + path('tasks/<int:pk>/discard/<new_status>/<page>', views.TaskDiscard, name='task-discard-view'), + path('tasks/<int:pk>/discard_sasid/<new_status>/<page>', views.TaskDiscardSasId, name='task-discard-view-sasid'), path('tasks/<int:pk>/change_priority/<priority_change>/<page>', views.ChangePriority, name='task-change-priority'), path('tasks/<int:pk>/change_priority/<priority_change>', views.ChangePriority, name='task-change-priority'), @@ -112,8 +115,5 @@ urlpatterns = [ path('tasks/<int:pk>/hold/<hold_it>/<page>', views.Hold, name='task-hold-resume'), path('tasks/<int:pk>/hold/<hold_it>', views.Hold, name='task-hold-resume'), path('tasks/<int:pk>/query-hold/<hold_it>/<query_params>', views.HoldQuery, name='query-hold-resume'), - path('tasks/<int:pk>/hold/<hold_it>/<page>', views.Hold, name='service-hold-resume'), - - path('hello/', views.HelloView.as_view(), name='hello'), ] diff --git a/atdb/taskdatabase/views.py b/atdb/taskdatabase/views.py index a64eea07a5c490aebc7b722c507c45225de3e2dc..f732752c3c9e233ec80401fb66263f7ea9124041 100644 --- a/atdb/taskdatabase/views.py +++ b/atdb/taskdatabase/views.py @@ -24,7 +24,7 @@ from rest_framework.request import Request from django.conf import settings from .models import Task, Status, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor, LatestMonitor from .tables import TaskTable -from .forms import QualityAnnotationForm +from .forms import QualityAnnotationForm, DiscardAnnotationForm from django.db.models import Q from .serializers import \ @@ -62,6 +62,7 @@ class TaskFilter(filters.FilterSet): 'status': ['exact', 'icontains', 'in', 'startswith'], 'quality': ['exact', 'icontains', 'in', 'startswith'], 'purge_policy': ['exact'], + 'cleanup_policy': ['exact','icontains','in'], 'priority': ['exact', 'lte', 'gte'], 'resume': ['exact'], # http://localhost:8000/atdb/tasks/?predecessor__isnull=True @@ -404,6 +405,45 @@ class ShowFailuresPage(ListView): return tasks +class ShowDiscardedPage(ListView): + """ + This shows the tasks that are discarded + Note that the global filter is also applied + """ + template_name = 'taskdatabase/discarded/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): + + discarded_tasks = Task.objects.filter(status__icontains='discarded') + tasks = get_filtered_tasks(self.request, discarded_tasks) + + 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 + + class ShowFinishedPage(ListView): """ This shows the tasks that are archived @@ -446,9 +486,14 @@ class ShowFinishedPage(ListView): # this provides a broad range of filters for the search_box in the GUI def get_filtered_tasks(request, pre_filtered_tasks=None, distinct=None): - filtered_tasks_as_list = None + # there was an attempt to pre_filter tasks, but it has yielded no results. + # further filtering is then useless, return an empty queryset + if pre_filtered_tasks is not None: + if pre_filtered_tasks.count() == 0: + return pre_filtered_tasks + try: my_sort = request.session['sort'] except: @@ -1024,7 +1069,7 @@ def TaskSetStatus(request, pk, new_status, page=0): @login_required def TaskValidate(request, pk, quality, new_status, page=0): - model = Task + task = Task.objects.get(pk=pk) # find all tasks with the same SAS_ID, and set this quality to all of them @@ -1046,7 +1091,7 @@ def TaskValidate(request, pk, quality, new_status, page=0): @login_required def TaskRetry(request, pk, new_status, page=0): - model = Task + task = Task.objects.get(pk=pk) task.new_status = new_status task.save() @@ -1058,6 +1103,93 @@ def TaskRetry(request, pk, new_status, page=0): # redirect to tasks list return redirect_with_params('failures', '?page=' + page) +@login_required +def TaskDiscard(request, pk, new_status, page=0): + # TODO: when the cleanup service in place, + # make a change in this line in failures\tasks.html. Change 'discard' into 'discarded'. + # <a href="{% url 'task-discard-view' task.pk 'discarded' my_tasks.number %}" + + task = Task.objects.get(pk=pk) + + if request.method == "POST": + form = DiscardAnnotationForm(request.POST) + + if form.is_valid(): + try: + task.remarks['discard_reason'] = request.POST.get("annotation", "") + except: + task.remarks = {} + task.remarks['discard_reason'] = request.POST.get("annotation", "") + + # currently, the cleanup_policy is set to the old status. + # That will tell the cleanup service what to do with it. + task.cleanup_policy = task.status + + # set the status to discard and save it + task.new_status = new_status + task.save() + + # return to the failures page + return redirect_with_params('failures', '?page=' + page) + + else: + # a GET means that the form should be presented to be filled in + try: + discard_reason = task.remarks['discard_reason'] + except: + discard_reason = "" + + my_form = DiscardAnnotationForm(initial={'annotation': discard_reason, 'return_to_page': page}) + + # if not a POST, then render the confirmaton page, which will return to this function with a POST. + return render(request, "taskdatabase/failures/confirm_discard.html", + {'task': task, 'my_form': my_form, 'page': page}) + + + +def TaskDiscardSasId(request, pk, new_status, page=0): + # TODO: when the cleanup service in place, + # make a change in this line in failures\tasks.html. Change 'discard' into 'discarded'. + # <a href="{% url 'task-discard-view' task.pk 'discarded' my_tasks.number %}" + + task = Task.objects.get(pk=pk) + sas_id = task.sas_id + tasks = Task.objects.filter(sas_id=sas_id) + + if request.method == "POST": + form = DiscardAnnotationForm(request.POST) + + for task in tasks: + task.cleanup_policy = task.status + + if form.is_valid(): + try: + task.remarks['discard_reason'] = request.POST.get("annotation", "") + except: + task.remarks = {} + task.remarks['discard_reason'] = request.POST.get("annotation", "") + + task.new_status = new_status + task.save() + + # return to the validation page + return redirect_with_params('validation', '?page=' + page) + + else: + # a GET means that the form should be presented to be filled in + try: + discard_reason = task.remarks.get("discard_reason", "") + except: + discard_reason = "" + + count=tasks.count() + + my_form = DiscardAnnotationForm(initial={'annotation': discard_reason, 'return_to_page': page}) + + # if not a POST, then render the confirmaton page, which will return to this function with a POST. + return render(request, "taskdatabase/validation/confirm_discard.html", + {'task': task, 'my_form': my_form, 'page': page, 'sas_id': sas_id, 'count': count}) + # set a filter value in the session, used later by the 'get_searched_tasks' mechanism def TaskSetFilter(request, filter, redirect_to_page): @@ -1102,6 +1234,8 @@ def TaskClearFilter(request, redirect_to_page): return redirect('quality') if redirect_to_page == 'query': return redirect('query') + if redirect_to_page == 'discarded': + return redirect('discarded') return redirect_with_params('index', '?page=1') @@ -1154,7 +1288,6 @@ def convert_query_params_to_url(query_params): params = "" for key in d: params = params + "&" + key + "=" + d[key] - print(params) return params @@ -1178,21 +1311,40 @@ def TaskMultiStatus(request, new_status, query_params): count = len(filtered_tasks_as_list) if request.method == "POST": + form = DiscardAnnotationForm(request.POST) for id in filtered_tasks_as_list: task = Task.objects.get(id=id) + + # setting status to discard or discarded uses a different form + if 'discard' in new_status: + if form.is_valid(): + try: + task.remarks['discard_reason'] = request.POST.get("annotation", "") + except: + task.remarks = {} + task.remarks['discard_reason'] = request.POST.get("annotation", "") + + # currently, the cleanup_policy is set to the old status. + # That will tell the cleanup service what to do with it. + task.cleanup_policy = task.status task.new_status = new_status task.save() current_query_params = request.session['current_query_params'] return redirect_with_params('query', '?' + current_query_params) - # add the current query parameters to the session so that they survive - # the request/response to the confirmation page (which has other query parameters) - current_query_params = convert_query_params_to_url(query_params) - request.session['current_query_params'] = current_query_params - - return render(request, "taskdatabase/query/confirm_multi_change.html", {'new_value': new_status, 'count': count}) + else: + # add the current query parameters to the session so that they survive + # the request/response to the confirmation page (which has other query parameters) + current_query_params = convert_query_params_to_url(query_params) + request.session['current_query_params'] = current_query_params + + if 'discard' in new_status: + my_form = DiscardAnnotationForm(initial={'annotation': '', 'return_to_page': 0}) + return render(request, "taskdatabase/query/confirm_discard.html", {'my_form': my_form, 'new_value': new_status,'count': count}) + else: + return render(request, "taskdatabase/query/confirm_multi_change.html", {'new_value': new_status, 'count': count}) @login_required @@ -1301,13 +1453,3 @@ class GetUniqueValuesForKey(generics.ListAPIView): }) -# 4 mar 2022 -# this is a test class to test token authentication -# can be removed if it all also works in production -class HelloView(APIView): - permission_classes = (IsAuthenticated,) - queryset = Task.objects.all() - - def get(self, request): - content = {'message': 'Hello, World!'} - return Response(content)