diff --git a/atdb/docs/ATDB-LDV Workflow Diagram.png b/atdb/docs/ATDB-LDV Workflow Diagram.png index 44e15fb397f50ec8fc4108cda3ddb94b7a37f6ed..34af713c20c18676d574bd938c27970096819900 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/taskdatabase/models.py b/atdb/taskdatabase/models.py index ddf22e8bedb2d4a0bf06b45ebe40b2a6edada853..687f5137fc6c79adf14dcaef3ced7139973a3fa2 100644 --- a/atdb/taskdatabase/models.py +++ b/atdb/taskdatabase/models.py @@ -7,33 +7,34 @@ from django.db.models import Sum datetime_format_string = '%Y-%m-%dT%H:%M:%SZ' class Workflow(models.Model): - workflow_uri = models.CharField(max_length=30, blank=True, null=True) + workflow_uri = models.CharField(unique=True, max_length=30, blank=True, null=True) repository = models.CharField(max_length=100, blank=True, null=True) - commit_id = models.CharField(max_length=30, blank=True, null=True) + commit_id = models.CharField(max_length=15, blank=True, null=True) path = models.CharField(max_length=100, blank=True, null=True) def __str__(self): - return str(self.id)+' - '+str(self.workflow_uri) + return str(self.workflow_uri) class Task(models.Model): taskID = models.CharField(db_index=True, max_length=30, blank=True, null=True) task_type = models.CharField(max_length=20, default="task") + filter = models.CharField(max_length=30, blank=True, null=True) + # note: the apparent naming reversal is intentional. Predecessors are somebody elses successors. # todo: change to Integer... but then the specification service has to be changed to using a dict - # to properly translate a python 'None' string to a Null value. - - new_predecessor_id = models.CharField(max_length=12, blank=True, null=True) - predecessor = models.ForeignKey('self', related_name='task_successors', on_delete=models.SET_NULL, null=True,blank=True) + # to properly translate a python 'None' string to a Null value. + predecessor = models.ForeignKey('self', related_name='successors', on_delete=models.SET_NULL, null=True,blank=True) + new_workflow_id = models.CharField(max_length=15, blank=True, null=True) + new_workflow_uri = models.CharField(max_length=100, blank=True, null=True) workflow = models.ForeignKey(Workflow, related_name='tasks', on_delete=models.SET_NULL, null=True, blank=True) + project = models.CharField(max_length=100, blank=True, null=True, default="unknown") - sas_id = models.CharField(max_length=30, blank=True, null=True) - priority = models.IntegerField(default=0) + sas_id = models.CharField(max_length=15, blank=True, null=True) + priority = models.IntegerField() purge_policy = models.CharField(max_length=5, default="no", blank=True, null=True) - new_workflow_id = models.CharField(max_length=12, blank=True, null=True) - new_workflow_uri = models.CharField(max_length=100, blank=True, null=True) stage_request_id = models.IntegerField(default=0) inputs = models.JSONField(null=True, blank=True) @@ -46,7 +47,7 @@ class Task(models.Model): status = models.CharField(db_index=True, default="unknown", max_length=50,blank=True, null=True) def __str__(self): - return str(self.id) + ' - ' + str(self.taskID) + ' - ' + str(self.sas_id) + return str(self.id) + ' - ' + str(self.sas_id) # this translates a view-name (from urls.py) back to a url, to avoid hardcoded url's in the html templates # bad : <td><a href="/atdb/taaks/{{ task.id }}/" target="_blank">{{ task.taskID }} </a> </td> @@ -66,7 +67,7 @@ class LogEntry(models.Model): status = models.CharField(max_length=50,default="defined", blank=True, null=True) def __str__(self): - return str(self.id)+' - ('+str(self.task)+')' + return str(self.id)+ ' - '+ str(self.task)+' - '+self.status class Status(models.Model): @@ -74,14 +75,6 @@ class Status(models.Model): timestamp = models.DateTimeField(default=datetime.utcnow, blank=True) task = models.ForeignKey(Task, related_name='status_history', on_delete=models.CASCADE, null=False) - @property - def property_taskID(self): - return self.task.taskID - - @property - def property_task_type(self): - return self.task.task_type - # the representation of the value in the REST API def __str__(self): formatedDate = self.timestamp.strftime(datetime_format_string) diff --git a/atdb/taskdatabase/serializers.py b/atdb/taskdatabase/serializers.py index 5a2ffc66b4bd0833fab58b89b620e86f817016eb..f9bbb37674a13a7ba6bf46e478c8a4887bda776f 100644 --- a/atdb/taskdatabase/serializers.py +++ b/atdb/taskdatabase/serializers.py @@ -36,11 +36,14 @@ class TaskSerializer(serializers.ModelSerializer): required=False ) + successors = serializers.StringRelatedField( + many=True, + required=False, + ) class Meta: model = Task - fields = ('id','task_type','taskID', - 'new_predecessor_id','predecessor', + fields = ('id','task_type','taskID','filter','predecessor','successors', 'project','sas_id','priority','purge_policy','skip', 'new_workflow_id','new_workflow_uri','workflow', 'stage_request_id', diff --git a/atdb/taskdatabase/services/signals.py b/atdb/taskdatabase/services/signals.py index d6a7590c295902340dbc7be6a67f96da7377f2f5..5edb49aaeeaa5fef0d6372023a56d22829207001 100644 --- a/atdb/taskdatabase/services/signals.py +++ b/atdb/taskdatabase/services/signals.py @@ -46,17 +46,20 @@ def add_workflow(myTaskObject): if (new_workflow == None): # then try workflow_uri - new_workflow = Workflow.objects.get(workflow_uri=new_workflow_uri) + try: + new_workflow = Workflow.objects.get(workflow_uri=new_workflow_uri) + except: + pass # first check if works needs to be done at all if (myTaskObject.workflow != new_workflow): - # set the new status + # set the new workflow myTaskObject.workflow = new_workflow return myTaskObject -def add_predecessor(myTaskObject): +def add_predecessor_obsolete(myTaskObject): # connect the task to a workflow after posting a (flat) task through the REST API try: @@ -100,10 +103,6 @@ def handle_pre_save(sender, **kwargs): myStatus = Status(name=new_status, task=myTaskObject) myStatus.save() - # connect the task to a workflow after posting a (flat) task through the REST API - myTaskObject = add_workflow(myTaskObject) - myTaskObject = add_predecessor(myTaskObject) - # temporarily disconnect the post_save handler to save the dataproduct (again) and avoiding recursion. # I don't use pre_save, because then the 'created' key is not available, which is the most handy way to @@ -143,6 +142,10 @@ def handle_post_save(sender, **kwargs): myStatus = Status(name=myTaskObject.new_status, task=myTaskObject) myStatus.save() + # connect the task to a workflow after posting a (flat) task through the REST API + myTaskObject = add_workflow(myTaskObject) + #myTaskObject = add_predecessor(myTaskObject) + # temporarily disconnect the post_save handler to save the dataproduct (again) and avoiding recursion. # I don't use pre_save, because then the 'created' key is not available, which is the most handy way to # determine if this dataproduct already exists. (I could also check the database, but this is easier). diff --git a/atdb/taskdatabase/static/taskdatabase/style.css b/atdb/taskdatabase/static/taskdatabase/style.css index 7704fca858dc2266047f9e933d2bcaf57c66c7b0..ea6d7cf84d1936e109d95580206c05cc2381cb8b 100644 --- a/atdb/taskdatabase/static/taskdatabase/style.css +++ b/atdb/taskdatabase/static/taskdatabase/style.css @@ -3,7 +3,7 @@ TD { font-size: 12pt; } -.defined, .completed, .complete, { +.defined, .staged, { background-color: lemonchiffon; color: blue; } diff --git a/atdb/taskdatabase/templates/taskdatabase/index.html b/atdb/taskdatabase/templates/taskdatabase/index.html index 9e4e353c01d51806981ca8f8df974c07883e73be..1a567eb5583052303c4887204193f6d0b3016798 100644 --- a/atdb/taskdatabase/templates/taskdatabase/index.html +++ b/atdb/taskdatabase/templates/taskdatabase/index.html @@ -17,13 +17,11 @@ <table class="table table-striped table-bordered table-sm"> <thead> <tr> - <th width="5%">TaskID</th> - <th>Status</th> - <th width="3%">task_type</th> + <th width="5%">ID</th> + <th>Status</th> <th>Project</th> <th width="15%">Workflow</th> - <th>Created</th> <th>Size</th> @@ -46,7 +44,7 @@ </div> {% include 'taskdatabase/pagination.html' %} </div> - <p class="footer"> Version 1.0.0 (21 jan 2021 - 11:00) + <p class="footer"> Version 1.0.0 (22 jan 2021 - 9:00) <script type="text/javascript"> (function(seconds) { var refresh, diff --git a/atdb/taskdatabase/templates/taskdatabase/tasks.html b/atdb/taskdatabase/templates/taskdatabase/tasks.html index 89ac9f351ab01571d0d1fddcae02aff03a08a26e..4780bd5c088fdb6fd1edf1b49336e485598f10a6 100644 --- a/atdb/taskdatabase/templates/taskdatabase/tasks.html +++ b/atdb/taskdatabase/templates/taskdatabase/tasks.html @@ -6,10 +6,9 @@ <td> - <a href="{{ task.get_absolute_url }}" target="_blank">{{ task.taskID }} </a> + <a href="{{ task.get_absolute_url }}" target="_blank">{{ task.id }} </a> </td> - <td>{{ task.status }}</td> - <td>{{ task.task_type }}</td> + <td>{{ task.status }}</td> <td>{{ task.project }}</td> <td>{{ task.workflow }} @@ -19,12 +18,15 @@ </td> <td> + {% if task.status == "defining" %} + <a href="{% url 'task-setstatus-view' task.pk 'defined' my_tasks.number %}" class="btn btn-primary btn-sm" role="button">To Defined</a> + {% endif %} {% if task.status == "defined" %} <a href="{% url 'task-setstatus-view' task.pk 'defining' my_tasks.number %}" class="btn btn-primary btn-sm" role="button">To Defining</a> {% endif %} - {% if task.status == "submitted" %} + {% if task.status == "submitted" or task.status == "submitting" %} <a href="{% url 'task-setstatus-view' task.pk 'defined' my_tasks.number %}" class="btn btn-primary btn-sm" role="button">To Defined</a> {% endif %} diff --git a/atdb/taskdatabase/views.py b/atdb/taskdatabase/views.py index 4d6eadca20ea9d0c0d0ad2b7ca9c99409d2b1089..e35e6679a4f82a9017e881dd6c83b1eda26a00c6 100644 --- a/atdb/taskdatabase/views.py +++ b/atdb/taskdatabase/views.py @@ -28,6 +28,8 @@ class TaskFilter(filters.FilterSet): model = Task fields = { + 'task_type': ['exact', 'icontains'], + 'filter': ['exact', 'icontains'], 'project': ['exact', 'icontains'], 'sas_id': ['exact', 'icontains'], 'status': ['exact', 'icontains', 'in', 'startswith'],