From 4fc5205ace2b9840fa05ef2f07a2157b896ba5c8 Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 08:18:21 +0100 Subject: [PATCH 01/10] fix sample load time formatting --- response_operations_ui/views/collection_exercise.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index 29aa83039..5529956e3 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -109,6 +109,7 @@ def _build_collection_instruments_details(collection_exercise_id: str, survey_id def view_collection_exercise(short_name, period): collection_exercise, survey = get_collection_exercise_and_survey_details(short_name, period) sample = get_sample_summary(collection_exercise["id"]) + sample = _format_sample_summary(sample) events = convert_events_to_new_format( collection_exercise_controllers.get_collection_exercise_events_by_id(collection_exercise["id"]) ) @@ -117,9 +118,6 @@ def view_collection_exercise(short_name, period): if sample_controllers.sample_summary_state_check_required(collection_exercise["state"], sample): try: sample_load_status = sample_controllers.check_if_all_sample_units_present_for_sample_summary(sample["id"]) - if sample_load_status["areAllSampleUnitsLoaded"]: - sample = _format_sample_summary(sample) - except ApiError: flash("Sample summary check failed. Refresh page to try again", category="error") From 08dfac532c623e292d2025256a5f5ddb83858eba Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 10:01:03 +0100 Subject: [PATCH 02/10] slight refactor --- response_operations_ui/views/collection_exercise.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index 5529956e3..c62edaccc 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -82,6 +82,7 @@ def get_sample_summary(collection_exercise_id): summary_id = collection_exercise_controllers.get_linked_sample_summary_id(collection_exercise_id) sample_summary = sample_controllers.get_sample_summary(summary_id) if summary_id else None + sample_summary = _format_sample_summary(sample_summary) return sample_summary @@ -109,7 +110,6 @@ def _build_collection_instruments_details(collection_exercise_id: str, survey_id def view_collection_exercise(short_name, period): collection_exercise, survey = get_collection_exercise_and_survey_details(short_name, period) sample = get_sample_summary(collection_exercise["id"]) - sample = _format_sample_summary(sample) events = convert_events_to_new_format( collection_exercise_controllers.get_collection_exercise_events_by_id(collection_exercise["id"]) ) @@ -118,6 +118,8 @@ def view_collection_exercise(short_name, period): if sample_controllers.sample_summary_state_check_required(collection_exercise["state"], sample): try: sample_load_status = sample_controllers.check_if_all_sample_units_present_for_sample_summary(sample["id"]) + if sample_load_status["areAllSampleUnitsLoaded"]: + sample = _format_sample_summary(sample) except ApiError: flash("Sample summary check failed. Refresh page to try again", category="error") From 56535899f97ddc987f7ae4a222a1ec9a745b04da Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 10:05:37 +0100 Subject: [PATCH 03/10] improve naming --- response_operations_ui/views/collection_exercise.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index c62edaccc..134a38866 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -82,8 +82,8 @@ def get_sample_summary(collection_exercise_id): summary_id = collection_exercise_controllers.get_linked_sample_summary_id(collection_exercise_id) sample_summary = sample_controllers.get_sample_summary(summary_id) if summary_id else None - sample_summary = _format_sample_summary(sample_summary) - return sample_summary + formatted_sample_summary = _format_sample_summary(sample_summary) + return formatted_sample_summary def get_collection_exercise_and_survey_details(short_name, period): From f08a7f9b316274be27ba60446ff3831e915dd2c1 Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 10:32:16 +0100 Subject: [PATCH 04/10] refactor test --- response_operations_ui/__init__.py | 2 +- response_operations_ui/views/collection_exercise.py | 6 ++---- tests/views/test_collection_exercise.py | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/response_operations_ui/__init__.py b/response_operations_ui/__init__.py index 289b3f56b..b267c8c41 100644 --- a/response_operations_ui/__init__.py +++ b/response_operations_ui/__init__.py @@ -5,13 +5,13 @@ import redis from flask import Flask, flash, redirect, session, url_for from flask_login import LoginManager -from flask_session import Session from flask_talisman import Talisman from flask_wtf.csrf import CSRFError, CSRFProtect from jinja2 import ChainableUndefined from structlog import wrap_logger from config import Config +from flask_session import Session from response_operations_ui.common.jinja_filters import filter_blueprint from response_operations_ui.controllers.uaa_controller import user_has_permission from response_operations_ui.logger_config import logger_initial_config diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index 134a38866..ae45667f0 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -82,8 +82,8 @@ def get_sample_summary(collection_exercise_id): summary_id = collection_exercise_controllers.get_linked_sample_summary_id(collection_exercise_id) sample_summary = sample_controllers.get_sample_summary(summary_id) if summary_id else None - formatted_sample_summary = _format_sample_summary(sample_summary) - return formatted_sample_summary + sample_summary = _format_sample_summary(sample_summary) + return sample_summary def get_collection_exercise_and_survey_details(short_name, period): @@ -118,8 +118,6 @@ def view_collection_exercise(short_name, period): if sample_controllers.sample_summary_state_check_required(collection_exercise["state"], sample): try: sample_load_status = sample_controllers.check_if_all_sample_units_present_for_sample_summary(sample["id"]) - if sample_load_status["areAllSampleUnitsLoaded"]: - sample = _format_sample_summary(sample) except ApiError: flash("Sample summary check failed. Refresh page to try again", category="error") diff --git a/tests/views/test_collection_exercise.py b/tests/views/test_collection_exercise.py index a7e5b4f11..6fab4fa91 100644 --- a/tests/views/test_collection_exercise.py +++ b/tests/views/test_collection_exercise.py @@ -489,12 +489,12 @@ def test_collection_exercise_sample_check_count( "expectedTotal": 10, "currentTotal": 10, } - + response = self.client.get(f"/surveys/{short_name}/{period}", follow_redirects=True) self.assertEqual(response.status_code, 200) self.assertIn("Ready for live".encode(), response.data) - self.assertIn("14 March 2018".encode(), response.data) + self.assertIn("Sample loaded: ".encode(), response.data) @mock_decorator(CE_INIT, EQ_SURVEY, EQ_CI, SAMPLE_SUMMARY_INIT, CE_EVENTS) @patch("response_operations_ui.controllers.sample_controllers.sample_summary_state_check_required") From d0fdfad667a79a2091471d90bdde890224512069 Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 10:37:51 +0100 Subject: [PATCH 05/10] linter --- response_operations_ui/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/response_operations_ui/__init__.py b/response_operations_ui/__init__.py index b267c8c41..289b3f56b 100644 --- a/response_operations_ui/__init__.py +++ b/response_operations_ui/__init__.py @@ -5,13 +5,13 @@ import redis from flask import Flask, flash, redirect, session, url_for from flask_login import LoginManager +from flask_session import Session from flask_talisman import Talisman from flask_wtf.csrf import CSRFError, CSRFProtect from jinja2 import ChainableUndefined from structlog import wrap_logger from config import Config -from flask_session import Session from response_operations_ui.common.jinja_filters import filter_blueprint from response_operations_ui.controllers.uaa_controller import user_has_permission from response_operations_ui.logger_config import logger_initial_config From 6dc1959ec862b3a87d864ab82c7c839f2d5f67fd Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 10:40:13 +0100 Subject: [PATCH 06/10] Linter! --- tests/views/test_collection_exercise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/views/test_collection_exercise.py b/tests/views/test_collection_exercise.py index 6fab4fa91..96c5aef06 100644 --- a/tests/views/test_collection_exercise.py +++ b/tests/views/test_collection_exercise.py @@ -489,7 +489,7 @@ def test_collection_exercise_sample_check_count( "expectedTotal": 10, "currentTotal": 10, } - + response = self.client.get(f"/surveys/{short_name}/{period}", follow_redirects=True) self.assertEqual(response.status_code, 200) From 891ff4d279feac3a0c52525eabb65d582ef370ad Mon Sep 17 00:00:00 2001 From: ras-rm-pr-bot Date: Fri, 17 Oct 2025 09:50:52 +0000 Subject: [PATCH 07/10] auto patch increment --- _infra/helm/response-operations-ui/Chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_infra/helm/response-operations-ui/Chart.yaml b/_infra/helm/response-operations-ui/Chart.yaml index 1add9305b..a86b0adf8 100644 --- a/_infra/helm/response-operations-ui/Chart.yaml +++ b/_infra/helm/response-operations-ui/Chart.yaml @@ -14,8 +14,8 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version -version: 3.1.144 +version: 3.1.145 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. -appVersion: 3.1.144 +appVersion: 3.1.145 From 9a30a7c529d13d7466f429a5ccbaa1f80dbdc19b Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 14:35:11 +0100 Subject: [PATCH 08/10] different approach --- .../ce-sample-section.html | 2 +- .../views/collection_exercise.py | 19 ++++++++++++++----- tests/views/test_collection_exercise.py | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/response_operations_ui/templates/collection_exercise/ce-sample-section.html b/response_operations_ui/templates/collection_exercise/ce-sample-section.html index dd6ff2761..91f161bd9 100644 --- a/response_operations_ui/templates/collection_exercise/ce-sample-section.html +++ b/response_operations_ui/templates/collection_exercise/ce-sample-section.html @@ -47,7 +47,7 @@

Sample file *

{ "tds": [ { - "value": "Sample loaded: " + '' + sample.ingestDateTime[:-7] + '' + sample.ingestDateTime[-7:] + "value": "Sample loaded: " + '' + formatted_sample.ingestDateTime[:-7] + '' + formatted_sample.ingestDateTime[-7:] }, { "value": addSampleLink, diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index ae45667f0..f25ed6dd3 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -82,7 +82,6 @@ def get_sample_summary(collection_exercise_id): summary_id = collection_exercise_controllers.get_linked_sample_summary_id(collection_exercise_id) sample_summary = sample_controllers.get_sample_summary(summary_id) if summary_id else None - sample_summary = _format_sample_summary(sample_summary) return sample_summary @@ -110,6 +109,7 @@ def _build_collection_instruments_details(collection_exercise_id: str, survey_id def view_collection_exercise(short_name, period): collection_exercise, survey = get_collection_exercise_and_survey_details(short_name, period) sample = get_sample_summary(collection_exercise["id"]) + formatted_sample = _format_sample_summary(sample) events = convert_events_to_new_format( collection_exercise_controllers.get_collection_exercise_events_by_id(collection_exercise["id"]) ) @@ -118,6 +118,8 @@ def view_collection_exercise(short_name, period): if sample_controllers.sample_summary_state_check_required(collection_exercise["state"], sample): try: sample_load_status = sample_controllers.check_if_all_sample_units_present_for_sample_summary(sample["id"]) + if sample_load_status["areAllSampleUnitsLoaded"]: + formatted_sample = _format_sample_summary(sample) except ApiError: flash("Sample summary check failed. Refresh page to try again", category="error") @@ -161,6 +163,7 @@ def view_collection_exercise(short_name, period): processing=processing, sample_load_status=sample_load_status, sample=sample, + formatted_sample=formatted_sample, show_set_live_button=show_set_live_button, survey=survey, success_panel=success_panel, @@ -465,10 +468,16 @@ def _validate_sample() -> bool: def _format_sample_summary(sample): if sample and sample.get("ingestDateTime"): - submission_datetime = localise_datetime(iso8601.parse_date(sample["ingestDateTime"])) - submission_time = submission_datetime.strftime("%d %B %Y %I:%M%p") - sample["ingestDateTime"] = submission_time - + submission_value = sample["ingestDateTime"] + if isinstance(submission_value, str): + try: + submission_datetime = localise_datetime(iso8601.parse_date(submission_value)) + submission_time = submission_datetime.strftime("%d %B %Y %I:%M%p") + sample["ingestDateTime"] = submission_time + except ValueError: + sample["ingestDateTime"] = submission_value + else: + sample["ingestDateTime"] = submission_value return sample diff --git a/tests/views/test_collection_exercise.py b/tests/views/test_collection_exercise.py index 96c5aef06..a7e5b4f11 100644 --- a/tests/views/test_collection_exercise.py +++ b/tests/views/test_collection_exercise.py @@ -494,7 +494,7 @@ def test_collection_exercise_sample_check_count( self.assertEqual(response.status_code, 200) self.assertIn("Ready for live".encode(), response.data) - self.assertIn("Sample loaded: ".encode(), response.data) + self.assertIn("14 March 2018".encode(), response.data) @mock_decorator(CE_INIT, EQ_SURVEY, EQ_CI, SAMPLE_SUMMARY_INIT, CE_EVENTS) @patch("response_operations_ui.controllers.sample_controllers.sample_summary_state_check_required") From 0a10150778b28292be281f8aba353424a5b473f3 Mon Sep 17 00:00:00 2001 From: matthew-robinson-ons Date: Fri, 17 Oct 2025 14:50:05 +0100 Subject: [PATCH 09/10] better varibale names --- response_operations_ui/views/collection_exercise.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index f25ed6dd3..3ab133fda 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -468,16 +468,16 @@ def _validate_sample() -> bool: def _format_sample_summary(sample): if sample and sample.get("ingestDateTime"): - submission_value = sample["ingestDateTime"] - if isinstance(submission_value, str): + submission_datetime = sample["ingestDateTime"] + if isinstance(submission_datetime, str): try: - submission_datetime = localise_datetime(iso8601.parse_date(submission_value)) - submission_time = submission_datetime.strftime("%d %B %Y %I:%M%p") + localised_submission_datetime = localise_datetime(iso8601.parse_date(submission_datetime)) + submission_time = localised_submission_datetime.strftime("%d %B %Y %I:%M%p") sample["ingestDateTime"] = submission_time except ValueError: - sample["ingestDateTime"] = submission_value + sample["ingestDateTime"] = submission_datetime else: - sample["ingestDateTime"] = submission_value + sample["ingestDateTime"] = submission_datetime return sample From ec842ca65201edc19554ad18e9be3d91eb8a2b4a Mon Sep 17 00:00:00 2001 From: LJBabbage Date: Fri, 17 Oct 2025 17:06:13 +0100 Subject: [PATCH 10/10] Tidy up sample section --- .../ce-sample-section.html | 2 +- .../views/collection_exercise.py | 42 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/response_operations_ui/templates/collection_exercise/ce-sample-section.html b/response_operations_ui/templates/collection_exercise/ce-sample-section.html index 91f161bd9..d5b8b2fc9 100644 --- a/response_operations_ui/templates/collection_exercise/ce-sample-section.html +++ b/response_operations_ui/templates/collection_exercise/ce-sample-section.html @@ -47,7 +47,7 @@

Sample file *

{ "tds": [ { - "value": "Sample loaded: " + '' + formatted_sample.ingestDateTime[:-7] + '' + formatted_sample.ingestDateTime[-7:] + "value": "Sample loaded: " + '' + sample_ingest_date_time[:-7] + '' + sample_ingest_date_time[-7:] }, { "value": addSampleLink, diff --git a/response_operations_ui/views/collection_exercise.py b/response_operations_ui/views/collection_exercise.py index 3ab133fda..95aa3a8aa 100644 --- a/response_operations_ui/views/collection_exercise.py +++ b/response_operations_ui/views/collection_exercise.py @@ -107,21 +107,23 @@ def _build_collection_instruments_details(collection_exercise_id: str, survey_id @collection_exercise_bp.route("//", methods=["GET"]) @login_required def view_collection_exercise(short_name, period): + sample_load_status = None + sample_ingest_date_time =None collection_exercise, survey = get_collection_exercise_and_survey_details(short_name, period) sample = get_sample_summary(collection_exercise["id"]) - formatted_sample = _format_sample_summary(sample) events = convert_events_to_new_format( collection_exercise_controllers.get_collection_exercise_events_by_id(collection_exercise["id"]) ) collection_instruments = _build_collection_instruments_details(collection_exercise["id"], survey["id"]) - sample_load_status = None - if sample_controllers.sample_summary_state_check_required(collection_exercise["state"], sample): - try: - sample_load_status = sample_controllers.check_if_all_sample_units_present_for_sample_summary(sample["id"]) - if sample_load_status["areAllSampleUnitsLoaded"]: - formatted_sample = _format_sample_summary(sample) - except ApiError: - flash("Sample summary check failed. Refresh page to try again", category="error") + + if sample: + if sample_controllers.sample_summary_state_check_required(collection_exercise["state"], sample): + try: + sample_load_status = sample_controllers.check_if_all_sample_units_present_for_sample_summary(sample["id"]) + except ApiError: + flash("Sample summary check failed. Refresh page to try again", category="error") + if sample["state"] in ["ACTIVE", "COMPLETE"]: + sample_ingest_date_time = _format_ingestion_date(sample.get("ingestDateTime")) ce_state = collection_exercise["state"] survey_mode = survey["surveyMode"] @@ -163,7 +165,7 @@ def view_collection_exercise(short_name, period): processing=processing, sample_load_status=sample_load_status, sample=sample, - formatted_sample=formatted_sample, + sample_ingest_date_time=sample_ingest_date_time, show_set_live_button=show_set_live_button, survey=survey, success_panel=success_panel, @@ -466,20 +468,12 @@ def _validate_sample() -> bool: return True -def _format_sample_summary(sample): - if sample and sample.get("ingestDateTime"): - submission_datetime = sample["ingestDateTime"] - if isinstance(submission_datetime, str): - try: - localised_submission_datetime = localise_datetime(iso8601.parse_date(submission_datetime)) - submission_time = localised_submission_datetime.strftime("%d %B %Y %I:%M%p") - sample["ingestDateTime"] = submission_time - except ValueError: - sample["ingestDateTime"] = submission_datetime - else: - sample["ingestDateTime"] = submission_datetime - return sample - +def _format_ingestion_date(date_time): + try: + localised_submission_datetime = localise_datetime(iso8601.parse_date(date_time)) + return localised_submission_datetime.strftime("%d %B %Y %I:%M%p") + except ValueError: + return date_time def _format_ci_file_name(collection_instruments, survey_details): for ci in collection_instruments: