From e2e0e419f15ba46497c68ae48ceefadeaf42cfdf Mon Sep 17 00:00:00 2001 From: Robbie Luijben <luijben@astron.nl> Date: Thu, 23 Mar 2023 15:23:20 +0000 Subject: [PATCH] LDVSpec usability improvements --- .gitlab-ci.yml | 6 ++++ integration/integration-test.robot | 32 +++++++++++++++++++ integration/resource/keywords.robot | 12 +++++-- integration/resource/variables.robot | 1 + ldvspec/lofardata/models.py | 5 ++- ldvspec/lofardata/static/update_workflow.js | 19 ++++++++--- .../lofardata/group/create_update.html | 10 ++++-- .../lofardata/templates/lofardata/index.html | 2 +- .../lofardata/partial_templates/badges.html | 14 +++++--- .../partial_templates/table_entry.html | 4 +-- .../partial_templates/table_header.html | 6 ++-- .../partial_templates/user_guide_link.html | 7 ++++ .../workspecification/create_update.html | 14 +++++--- .../lofardata/workspecification/detail.html | 2 +- ldvspec/lofardata/views/group/template.py | 4 ++- .../views/workspecification/template.py | 6 ++-- 16 files changed, 114 insertions(+), 30 deletions(-) create mode 100644 ldvspec/lofardata/templates/lofardata/partial_templates/user_guide_link.html diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5f304516..602832e2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -69,6 +69,12 @@ integration-test: - docker compose build - docker compose up -d atdb-backend ldv-specification-backend - docker compose run integration + artifacts: + paths: + - /workdir/output.xml + - /workdir/log.html + - /workdir/report.html + expire_in: 1 week allow_failure: false rules: - when: on_success diff --git a/integration/integration-test.robot b/integration/integration-test.robot index 50c44589..01a6c9cf 100644 --- a/integration/integration-test.robot +++ b/integration/integration-test.robot @@ -56,3 +56,35 @@ Test create a group with a few work specifications Add Group Beatles 1, 22, 13 3 Check if Group Exists Beatles +Test task submission status ready with files + [Tags] Workspecification + ${specification_id}= Add Work Specification 5 + ${submission_status}= Get Task Submission Status ${specification_id} + Should Be Equal As Strings ${submission_status} Ready + +Test task submission status ready without files + [Tags] Workspecification + ${specification_id}= Add Work Specification 9999 + ${submission_status}= Get Task Submission Status ${specification_id} + Should Be Equal As Strings ${submission_status} Ready* + +Test task submission status submitted + [Tags] Workspecification + ${specification_id}= Add Work Specification 5 + Submit Work Specification ${specification_id} + ${submission_status}= Get Task Submission Status ${specification_id} + Should Be Equal As Strings ${submission_status} Submitted + +# This test depends on one ATDB site added in the suite setup +Test automatically select first processing site dropdown in workspecification create form + [Tags] Workspecification + Go To ${LDVSPEC}specification/add/ + ${selected_value}= Get Selected List Value //*[@data-test-id="processing_site"] + Should Be Equal As Strings ${selected_value} ${ATDB_SITE_NAME} + +# This test depends on one ATDB site added in the suite setup +Test automatically select first processing site dropdown in group create form + [Tags] Workspecification + Go To ${LDVSPEC}group/add/ + ${selected_value}= Get Selected List Value //*[@data-test-id="processing_site"] + Should Be Equal As Strings ${selected_value} ${ATDB_SITE_NAME} \ No newline at end of file diff --git a/integration/resource/keywords.robot b/integration/resource/keywords.robot index 817d1545..8b4d6600 100644 --- a/integration/resource/keywords.robot +++ b/integration/resource/keywords.robot @@ -13,7 +13,7 @@ Add Group Input Text //*[@data-test-id="group_name"] ${name} - Select From List By Value //*[@data-test-id="processing_site"] atdb_site + Select From List By Value //*[@data-test-id="processing_site"] ${ATDB_SITE_NAME} Wait Until Element Contains //*[@data-test-id="workflow_tag"] environment timeout=5s Select From List By Value //*[@data-test-id="workflow_tag"] environment Wait Until Element Contains //*[@data-test-id="workflow"] https://example.com/workflow-1 timeout=5s @@ -42,7 +42,7 @@ Add Work Specification [Arguments] ${obs_id} Go To ${LDVSPEC}specification/add/ Click Element //*[@data-test-id="processing_site"] - Select From List By Value //*[@data-test-id="processing_site"] atdb_site + Select From List By Value //*[@data-test-id="processing_site"] ${ATDB_SITE_NAME} Wait Until Element Contains //*[@data-test-id="workflow_tag"] environment timeout=5s Select From List By Value //*[@data-test-id="workflow_tag"] environment Wait Until Element Contains //*[@data-test-id="workflow"] https://example.com/workflow-1 timeout=5s @@ -93,7 +93,7 @@ Add LDV Data Product Filter Add ATDB Processing Site [Arguments] ${token} Go To ${LDVSPEC}admin/lofardata/atdbprocessingsite/add/ - Input Text id_name atdb_site + Input Text id_name ${ATDB_SITE_NAME} Input Text id_url ${ATDB} Input Text id_access_token ${token} Click Button _save @@ -109,6 +109,12 @@ Logout from LDV Spec Go To ${LDVSPEC}accounts/logout/ Click Element //button[contains(text(), 'Log out')] +Get Task Submission Status + [Arguments] ${specification_id} + Go To ${LDVSPEC}specification/${specification_id} + ${submission_status}= Get Text //*[@data-test-id="submission-status"] + RETURN ${submission_status} + # ATDB Create Example Workflow in ATDB diff --git a/integration/resource/variables.robot b/integration/resource/variables.robot index 6ce6e6d4..94f9a075 100644 --- a/integration/resource/variables.robot +++ b/integration/resource/variables.robot @@ -3,3 +3,4 @@ ${BROWSER} headlessfirefox ${LDVSPEC} http://ldv-specification-backend:8000/ldvspec/ ${LDVSPEC_API} http://ldv-specification-backend:8000/ldvspec/api/ ${ATDB} http://atdb.backend:8000/atdb/ +${ATDB_SITE_NAME} atdb_site \ No newline at end of file diff --git a/ldvspec/lofardata/models.py b/ldvspec/lofardata/models.py index f36d9dd9..9884f266 100644 --- a/ldvspec/lofardata/models.py +++ b/ldvspec/lofardata/models.py @@ -124,6 +124,9 @@ class Group(models.Model): selected_workflow = models.CharField(max_length=500, blank=True, default='') selected_workflow_tag = models.CharField(max_length=500, blank=True, default='') + def ordered_workspecifications(self): + return self.workspecification_set.order_by('id') + class WorkSpecification(models.Model): """Work Specification""" @@ -139,7 +142,7 @@ class WorkSpecification(models.Model): # ATDB Workflow URL selected_workflow = models.CharField(max_length=500, null=True) - selected_workflow_tag = models.CharField(max_length=500, null=True, default="Unknown") + selected_workflow_tag = models.CharField(max_length=500, null=True) # Task ID's that were created in ATDB atdb_task_ids = ArrayField(models.IntegerField(), null=True, blank=True) diff --git a/ldvspec/lofardata/static/update_workflow.js b/ldvspec/lofardata/static/update_workflow.js index 03cb8f88..bb85ac8c 100644 --- a/ldvspec/lofardata/static/update_workflow.js +++ b/ldvspec/lofardata/static/update_workflow.js @@ -14,7 +14,7 @@ processingSites ); - self.selectedProcessingSite = ko.observable(existingProcessingSite); + self.selectedProcessingSite = ko.observable(initialProcessingSite); self.selectedProcessingSite.subscribe((context) => { self.loadWorkflows(); @@ -26,9 +26,12 @@ self.selectedGroup = ko.observable(existingGroup); + self.groupHasBeenSelectedAtLeastOnce = false; + self.selectedGroup.subscribe((context) => { const group = self.groups() && self.groups().filter(group => group.id === self.selectedGroup())[0]; if (group) { + self.groupHasBeenSelectedAtLeastOnce = true; self.selectedProcessingSite(group.processing_site); self.selectedTag(group.selected_workflow_tag); self.selectedWorkflow(group.selected_workflow); @@ -36,7 +39,10 @@ // setting the processing site to null will cause the loadWorkflows // function to trigger, which in turn will clear the previously selected // filled in workflow and tag - if (!self.pk) { // only do this for new work specifications (not existing ones) + if (!self.pk && self.groupHasBeenSelectedAtLeastOnce) { + // only do this for new work specifications (not existing ones) + // additionally, only do this when a group has already been selected once + // this is to avoid clearing the auto selected first processing site option self.selectedProcessingSite(null); } } @@ -62,8 +68,13 @@ self.selectedTag(group.selected_workflow_tag); self.selectedWorkflow(group.selected_workflow); } else { - self.selectedTag(self.existing_workflow_tag); - self.selectedWorkflow(self.existing_workflow); + // auto select first tag if there is only 1, and there is no tag saved on the work specification yet + const autoSelectedSingleTag = self.tags().length === 1 ? self.tags()[0] : null; + self.selectedTag(self.existing_workflow_tag || autoSelectedSingleTag); + + // auto select first workflow if there is only 1, and there is no workflow saved on the work specification yet + const autoSelectedWorkflow = self.workflowsByTag().length === 1 ? self.workflowsByTag()[0].workflow_uri : null; + self.selectedWorkflow(self.existing_workflow || autoSelectedWorkflow); } }).finally(() => { self.isLoading(false); diff --git a/ldvspec/lofardata/templates/lofardata/group/create_update.html b/ldvspec/lofardata/templates/lofardata/group/create_update.html index 573686c5..9902e36f 100644 --- a/ldvspec/lofardata/templates/lofardata/group/create_update.html +++ b/ldvspec/lofardata/templates/lofardata/group/create_update.html @@ -12,10 +12,14 @@ <a class="icon icon--times button--close" href="{% url 'index' %}"></a> <header class="flex-wrapper flex-wrapper--centered flex-wrapper--column"> {% if object.pk %} - <h2 class="title text text--primary">Edit {{ object.name }}</h2> + <h2 class="title text">Edit {{ object.name }} + {% include 'lofardata/partial_templates/user_guide_link.html' with link="group/editing" %} + </h2> <form method="post" action="{% url 'group-update' object.pk %}"> {% else %} - <h2 class="title text text--primary">New Group </h2> + <h2 class="title text">New Group + {% include 'lofardata/partial_templates/user_guide_link.html' with link="group/creating" %} + </h2> <form method="post" action="{% url 'group-create' %}"> {% endif %} @@ -173,7 +177,7 @@ const existingWorkflow = '{{ object.selected_workflow|default_if_none:"null" }}'; const existingWorkflowTag = '{{ object.selected_workflow_tag|default_if_none:"null" }}'; const processingSites = {{ processing_sites | json }}; - const existingProcessingSite = '{{ object.processing_site.name }}'; + const initialProcessingSite = '{{ object.processing_site.name|default:single_processing_site }}'; const groups = null; const existingGroup = null; const pk = {{ object.pk|default_if_none:0 }}; diff --git a/ldvspec/lofardata/templates/lofardata/index.html b/ldvspec/lofardata/templates/lofardata/index.html index 88896013..e37aa980 100644 --- a/ldvspec/lofardata/templates/lofardata/index.html +++ b/ldvspec/lofardata/templates/lofardata/index.html @@ -48,7 +48,7 @@ <div class="table"> {% include 'lofardata/partial_templates/table_header.html' with id=group.name %} <div class="table__content table__content--scroll table__content--scroll-small"> - {% for specification in group.workspecification_set.all %} + {% for specification in group.ordered_workspecifications %} {% include 'lofardata/partial_templates/table_entry.html' with specification=specification id=group.name %} {% endfor %} </div> diff --git a/ldvspec/lofardata/templates/lofardata/partial_templates/badges.html b/ldvspec/lofardata/templates/lofardata/partial_templates/badges.html index dc2f5a21..97fb33d1 100644 --- a/ldvspec/lofardata/templates/lofardata/partial_templates/badges.html +++ b/ldvspec/lofardata/templates/lofardata/partial_templates/badges.html @@ -4,16 +4,22 @@ {% define "The work specification is now retrieving the necessary information." as badgeTitle %} {% elif status == "D" %} {% define "secondary" as badgecolor %} - {% define "The work specification is now being send to ATDB." as badgeTitle %} + {% define "The work specification is now being sent to ATDB." as badgeTitle %} {% elif status == "S" %} {% define "green" as badgecolor %} {% define "The work specification has been succcesfully processed in ATDB." as badgeTitle %} {% elif status == "E" %} {% define "red" as badgecolor %} {% define "Retrieving the files to process or submitting the task to ATDB resulted in an error. Please reports this to the support helpdesk or try again." as badgeTitle %} -{% else %} - {% define "primary" as badgecolor %} - {% define "The work specification has been created but has not yet been send to ATDB for processing." as badgeTitle %} +{% elif status == "R" %} + {% if number_of_files == 0 %} + {% define "orange" as badgecolor %} + {% define label|add:"*" as label %} + {% define "The work specification has been created, but does not contain any files. Please inspect the specified filters." as badgeTitle %} + {% elif number_of_files > 0 %} + {% define "primary" as badgecolor %} + {% define "The work specification has been created, but has not yet been sent to ATDB for processing." as badgeTitle %} + {% endif %} {% endif %} <div class="badge badge--{{ badgecolor }} margin-top text text--capitalized" data-test-id="submission-status" diff --git a/ldvspec/lofardata/templates/lofardata/partial_templates/table_entry.html b/ldvspec/lofardata/templates/lofardata/partial_templates/table_entry.html index 15cda1ed..c8973a19 100644 --- a/ldvspec/lofardata/templates/lofardata/partial_templates/table_entry.html +++ b/ldvspec/lofardata/templates/lofardata/partial_templates/table_entry.html @@ -3,7 +3,7 @@ {% load workspecification %} <div class="table__row table__row--dark table__row--padding" - data-spec-id="specification.id"> + data-test-id="specification-{{ specification.id }}"> <div class="table__cell table__cell--mini"> <div class="flex-container flex-container--checkboxes"> @@ -37,7 +37,7 @@ <div class="table__cell table__cell--truncate table__cell--horizontal-center">{{ specification.created_by }}</div> <div class="table__cell table__cell--truncate table__cell--horizontal-center"> - {% include 'lofardata/partial_templates/badges.html' with status=specification.submission_status label=specification.get_submission_status_display %} + {% include 'lofardata/partial_templates/badges.html' with status=specification.submission_status label=specification.get_submission_status_display number_of_files=specification.inputs.surls|length %} </div> diff --git a/ldvspec/lofardata/templates/lofardata/partial_templates/table_header.html b/ldvspec/lofardata/templates/lofardata/partial_templates/table_header.html index 9baa9d94..4ef61360 100644 --- a/ldvspec/lofardata/templates/lofardata/partial_templates/table_header.html +++ b/ldvspec/lofardata/templates/lofardata/partial_templates/table_header.html @@ -57,14 +57,14 @@ <div class="table__cell">Splitted <a class="tooltip-dias tooltip-dias-bottom" - data-tooltip="Wether or not the work specification has been splitted in multiple ATDB tasks and if that is recommended or not.">m</a> + data-tooltip="Whether or not the work specification has been splitted in multiple ATDB tasks and if that is recommended or not.">m</a> </div> - <div class="table__cell">S + <div class="table__cell">Suc <a class="tooltip-dias tooltip-dias-bottom" data-tooltip="The successors of a work specification (i.e. the children of another work specification)">m</a> </div> - <div class="table__cell">P + <div class="table__cell">Pre <a class="tooltip-dias tooltip-dias-bottom" data-tooltip="The predecessor of a work specification (i.e. the parent of a work specification)">m</a> </div> diff --git a/ldvspec/lofardata/templates/lofardata/partial_templates/user_guide_link.html b/ldvspec/lofardata/templates/lofardata/partial_templates/user_guide_link.html new file mode 100644 index 00000000..1983e55c --- /dev/null +++ b/ldvspec/lofardata/templates/lofardata/partial_templates/user_guide_link.html @@ -0,0 +1,7 @@ +{% load static %} + +<a class="" title="User Guide" href="{% static 'documentation/docs/user-guide/'|add:link %}"> + <span class="icon icon--primary icon--user"> + <span class="icon icon--secondary icon--stacked icon--background--main icon--info-circle"></span> + </span> +</a> \ No newline at end of file diff --git a/ldvspec/lofardata/templates/lofardata/workspecification/create_update.html b/ldvspec/lofardata/templates/lofardata/workspecification/create_update.html index a6f689b9..70b77d9b 100644 --- a/ldvspec/lofardata/templates/lofardata/workspecification/create_update.html +++ b/ldvspec/lofardata/templates/lofardata/workspecification/create_update.html @@ -12,10 +12,14 @@ <a class="icon icon--times button--close" href="{% url 'index' %}"></a> <header class="flex-wrapper flex-wrapper--centered flex-wrapper--column"> {% if object.pk %} - <h2 class="title text text--primary">Edit Work Specification {{ object.pk }}</h2> + <h2 class="title text">Edit Work Specification {{ object.pk }} + {% include 'lofardata/partial_templates/user_guide_link.html' with link="work-specification/editing" %} + </h2> <form method="post" action="{% url 'specification-update' object.pk %}"> {% else %} - <h2 class="title text text--primary">New Work Specification </h2> + <h2 class="title text text">New Work Specification + {% include 'lofardata/partial_templates/user_guide_link.html' with link="work-specification/creating" %} + </h2> <form method="post" action="{% url 'specification-create' %}"> {% endif %} @@ -249,10 +253,10 @@ <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-min.js'></script> <script type="text/javascript"> const processingSite = "{% url 'processingsite-detail' 'replace' %}"; - const existingWorkflow = '{{ object.selected_workflow|default_if_none:"null" }}'; - const existingWorkflowTag = '{{ object.selected_workflow_tag|default_if_none:"null" }}'; + const existingWorkflow = '{{ object.selected_workflow|default_if_none:"" }}'; + const existingWorkflowTag = '{{ object.selected_workflow_tag|default_if_none:"" }}'; const processingSites = {{ processing_sites | json }}; - const existingProcessingSite = '{{ object.processing_site.name }}'; + const initialProcessingSite = '{{ object.processing_site.name|default:single_processing_site }}'; const groups = {{ groups | json }}; const existingGroup = '{{ object.group.id|default_if_none:"null" }}'; const pk = {{ object.pk|default_if_none:0 }}; diff --git a/ldvspec/lofardata/templates/lofardata/workspecification/detail.html b/ldvspec/lofardata/templates/lofardata/workspecification/detail.html index b940d4d9..dbd74825 100644 --- a/ldvspec/lofardata/templates/lofardata/workspecification/detail.html +++ b/ldvspec/lofardata/templates/lofardata/workspecification/detail.html @@ -175,7 +175,7 @@ <div class="table__row table__row--dark table__row--padding"> <div class="table__cell table__cell--title">Submission status</div> <div class="table__cell"> - {% include '../partial_templates/badges.html' with status=object.submission_status label=object.get_submission_status_display %} + {% include '../partial_templates/badges.html' with status=object.submission_status label=object.get_submission_status_display number_of_files=object.inputs.surls|length %} </div> </div> diff --git a/ldvspec/lofardata/views/group/template.py b/ldvspec/lofardata/views/group/template.py index 09953ed2..b0f9360f 100644 --- a/ldvspec/lofardata/views/group/template.py +++ b/ldvspec/lofardata/views/group/template.py @@ -22,7 +22,9 @@ class GroupCreateUpdateView(LoginRequiredMixin, UpdateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context["processing_sites"] = list(ATDBProcessingSite.objects.values("name", "url")) + processing_sites = list(ATDBProcessingSite.objects.values("name", "url")) + context["processing_sites"] = processing_sites + context["single_processing_site"] = processing_sites[0]['name'] if len(processing_sites) == 1 else None return context def form_valid(self, form): diff --git a/ldvspec/lofardata/views/workspecification/template.py b/ldvspec/lofardata/views/workspecification/template.py index c1ca46c5..e3c27b2d 100644 --- a/ldvspec/lofardata/views/workspecification/template.py +++ b/ldvspec/lofardata/views/workspecification/template.py @@ -41,7 +41,9 @@ class WorkSpecificationCreateUpdateView(LoginRequiredMixin, CanEditWorkSpecifica except ObjectDoesNotExist: specification = None context["filters"] = filters_preprocessor.preprocess(specification) - context["processing_sites"] = list(ATDBProcessingSite.objects.values("name", "url")) + processing_sites = list(ATDBProcessingSite.objects.values("name", "url")) + context["processing_sites"] = processing_sites + context["single_processing_site"] = processing_sites[0]['name'] if len(processing_sites) == 1 else None context["groups"] = list(Group.objects.values("name", "id", "processing_site", "selected_workflow", "selected_workflow_tag")) return context @@ -143,5 +145,5 @@ class Overview(ListView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context["ungrouped_work_specifications"] = WorkSpecification.objects.filter(group=None) + context["ungrouped_work_specifications"] = WorkSpecification.objects.filter(group=None).order_by('id') return context -- GitLab