diff --git a/.copilot/phases/pre_build.sh b/.copilot/phases/pre_build.sh deleted file mode 100644 index f2a503f87b..0000000000 --- a/.copilot/phases/pre_build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -sed -i '15 s/build_exporter/build_exporter_dbt/' package.json -sed -i '15 s/build_caseworker/build_caseworker_dbt/' package.json diff --git a/caseworker/advice/constants.py b/caseworker/advice/constants.py index 37a4bd2f1f..4b536f3f4c 100644 --- a/caseworker/advice/constants.py +++ b/caseworker/advice/constants.py @@ -16,11 +16,14 @@ DESNZ_NUCLEAR_COUNTERSIGNING = "91213b45-f69f-492d-9d61-84e3a27cceb3" # /PS-IGNORE DESNZ_CHEMICAL_CASES_TO_REVIEW = "58e79b78-8817-40d0-afb3-fda57978a502" # /PS-IGNORE DESNZ_RUSSIA_SANCTIONS = "3ac48607-8102-49d9-bf49-55ef7b3cecef" # /PS-IGNORE +ENFORCEMENT_UNIT_CASES_TO_REVIEW = "50543c0d-bf2a-4f68-b33f-2ab89759db11" # /PS-IGNORE FCDO_CASES_TO_REVIEW_QUEUE = "f458094c-1fed-4222-ac70-ff5fa20ff649" # /PS-IGNORE FCDO_COUNTERSIGNING_QUEUE = "5e772575-9ae4-4a16-b55b-7e1476d810c4" # /PS-IGNORE FCDO_CPACC_CASES_TO_REVIEW_QUEUE = "a7ac8131-8eac-4dab-9eb1-aa2e9d0c0d42" # /PS-IGNORE -LU_POST_CIRC_FINALISE_QUEUE = "f0e7c2fa-100f-42ad-b740-bb072393e664" # /PS-IGNORE +LICENSING_RECEPTION_SIEL_APPLICATIONS = "1061b26e-b0f5-48dd-a6da-9717196b245c" # /PS-IGNORE LU_LICENSING_MANAGER_QUEUE = "9f5a2a93-03ed-4416-a8f8-8b728e5ea9d0" # /PS-IGNORE +LU_POST_CIRC_FINALISE_QUEUE = "f0e7c2fa-100f-42ad-b740-bb072393e664" # /PS-IGNORE +LU_PRE_CIRC = "4dfc0d0b-c0c0-4f59-897b-b7d596bed930" # /PS-IGNORE LU_SR_LICENSING_MANAGER_QUEUE = "7b643901-565a-4ec8-8a7a-de34bc541a0e" # /PS-IGNORE MOD_CAPPROT_CASES_TO_REVIEW = "93d1bc19-979d-4ba3-a57c-b0ce253c6237" # /PS-IGNORE MOD_DI_DIRECT_CASES_TO_REVIEW = "c93f1e56-c577-4910-a01c-434e47ac6c9c" # /PS-IGNORE @@ -29,6 +32,7 @@ MOD_DSTL_CASES_TO_REVIEW = "1a5f47ee-ef5e-456b-914c-4fa629b4559c" # /PS-IGNORE MOD_ECJU_REVIEW_AND_COMBINE = "432a8587-fc0e-4d34-9b50-92ad6d45bb16" # /PS-IGNORE NCSC_CASES_TO_REVIEW = "bbfc426b-a1af-4a4c-a97b-ae1557de4210" # /PS-IGNORE +TECHNICAL_ASSESSMENT_UNIT_SIELS_TO_REVIEW = "2876addb-1860-4226-b1f3-0bd0c1e21f9c" # /PS-IGNORE BULK_APPROVE_ALLOWED_QUEUES = ( @@ -45,9 +49,12 @@ DESNZ_NUCLEAR_COUNTERSIGNING, DESNZ_CHEMICAL_CASES_TO_REVIEW, DESNZ_RUSSIA_SANCTIONS, + ENFORCEMENT_UNIT_CASES_TO_REVIEW, FCDO_CASES_TO_REVIEW_QUEUE, FCDO_COUNTERSIGNING_QUEUE, FCDO_CPACC_CASES_TO_REVIEW_QUEUE, + LICENSING_RECEPTION_SIEL_APPLICATIONS, + LU_PRE_CIRC, LU_POST_CIRC_FINALISE_QUEUE, LU_LICENSING_MANAGER_QUEUE, LU_SR_LICENSING_MANAGER_QUEUE, @@ -58,6 +65,7 @@ MOD_DSTL_CASES_TO_REVIEW, MOD_ECJU_REVIEW_AND_COMBINE, NCSC_CASES_TO_REVIEW, + TECHNICAL_ASSESSMENT_UNIT_SIELS_TO_REVIEW, ] DECISION_TYPE_VERB_MAPPING = { diff --git a/caseworker/queues/views/cases.py b/caseworker/queues/views/cases.py index a995757cc6..48e5162a01 100644 --- a/caseworker/queues/views/cases.py +++ b/caseworker/queues/views/cases.py @@ -136,6 +136,19 @@ def get_params(self): if params.get("return_to"): del params["return_to"] + if not params.get("sort_by"): + # There is a default sort on the API side but we're overriding this + # here so that we control the sorting on the frontend + session_sort_by = self.request.session.get("case_search_sort_by") + if session_sort_by: + params["sort_by"] = session_sort_by + elif self.queue_pk == ALL_CASES_QUEUE_ID: + params["sort_by"] = "submitted_at" + else: + params["sort_by"] = "-submitted_at" + + self.request.session["case_search_sort_by"] = params["sort_by"] + return params def _set_is_hidden(self, tab_name, is_hidden_by_form): diff --git a/caseworker/queues/views/forms.py b/caseworker/queues/views/forms.py index 33b837f7a2..1428bfc7bd 100644 --- a/caseworker/queues/views/forms.py +++ b/caseworker/queues/views/forms.py @@ -141,15 +141,15 @@ def __init__(self, queue, filters_data, all_flags, all_cles, all_regimes, countr assigned_queues_choices = [(queue["id"], f"{queue['team']['name']}: {queue['name']}") for queue in queues] sort_options = [ - ("-submitted_at", "Submitted (newest to oldest)"), ("submitted_at", "Submitted (oldest to newest)"), + ("-submitted_at", "Submitted (newest to oldest)"), ] if queue["id"] in CASE_PROGRESSION_QUEUES: sort_options.extend( [ - ("-time_on_queue", "Time on queue (newest to oldest)"), ("time_on_queue", "Time on queue (oldest to newest)"), + ("-time_on_queue", "Time on queue (newest to oldest)"), ] ) diff --git a/conf/base.py b/conf/base.py index c4ab307d6d..8a62d42c5f 100644 --- a/conf/base.py +++ b/conf/base.py @@ -3,7 +3,6 @@ from environ import Env import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration -from django_log_formatter_ecs import ECSFormatter from django_log_formatter_asim import ASIMFormatter from dbt_copilot_python.utility import is_copilot @@ -165,10 +164,7 @@ LOGIN_URL = reverse_lazy("auth:login") -if IS_ENV_DBT_PLATFORM: - DATA_DIR = BASE_DIR -else: - DATA_DIR = os.path.dirname(BASE_DIR) +DATA_DIR = BASE_DIR STATICFILES_FINDERS = ( "django.contrib.staticfiles.finders.FileSystemFinder", @@ -228,11 +224,6 @@ LOGGING.update({"formatters": {"asim_formatter": {"()": ASIMFormatter}}}) LOGGING.update({"handlers": {"asim": {"class": "logging.StreamHandler", "formatter": "asim_formatter"}}}) LOGGING.update({"root": {"handlers": ["asim"], "level": LOG_LEVEL}}) -elif IS_ENV_GOV_PAAS: - REDIS_URL = VCAP_SERVICES["redis"][0]["credentials"]["uri"] - LOGGING.update({"formatters": {"ecs_formatter": {"()": ECSFormatter}}}) - LOGGING.update({"handlers": {"ecs": {"class": "logging.StreamHandler", "formatter": "ecs_formatter"}}}) - LOGGING.update({"root": {"handlers": ["ecs"], "level": LOG_LEVEL}}) else: # Local configurations and CircleCI REDIS_URL = env.str("REDIS_URL", "") diff --git a/package.json b/package.json index 9feddce8ed..6b05a645af 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,8 @@ "description": "Combined repo for LITE exporter and caseworker frontends", "private": true, "scripts": { - "build_exporter": "parcel build ./exporter/assets/javascripts/main.js ./exporter/assets/javascripts/cookie-policy-form.js --dist-dir exporter/assets/built --public-url /assets/", - "build_caseworker": "parcel build ./caseworker/assets/javascripts/{main,head,bookmarks,cookie-policy-form,desnz,tau,tau-edit,tau-multiple-assessment-edit,case-filters,refusal-review-consolidate,search-products}.js --dist-dir caseworker/assets/built --public-url /assets/", - "build_exporter_dbt": "NODE_OPTIONS='' parcel build ./exporter/assets/javascripts/main.js ./exporter/assets/javascripts/cookie-policy-form.js --dist-dir exporter/assets/built --public-url /assets/", - "build_caseworker_dbt": "NODE_OPTIONS='' parcel build ./caseworker/assets/javascripts/{main,head,bookmarks,cookie-policy-form,desnz,tau,tau-edit,tau-multiple-assessment-edit,case-filters,refusal-review-consolidate,search-products}.js --dist-dir caseworker/assets/built --public-url /assets/", + "build_exporter": "NODE_OPTIONS='' parcel build ./exporter/assets/javascripts/main.js ./exporter/assets/javascripts/cookie-policy-form.js --dist-dir exporter/assets/built --public-url /assets/", + "build_caseworker": "NODE_OPTIONS='' parcel build ./caseworker/assets/javascripts/{main,head,bookmarks,cookie-policy-form,desnz,tau,tau-edit,tau-multiple-assessment-edit,case-filters,refusal-review-consolidate,search-products}.js --dist-dir caseworker/assets/built --public-url /assets/", "watch_exporter": "PARCEL_WORKERS=0 parcel watch --port 8400 ./exporter/assets/javascripts/{main,head}.js ./exporter/assets/javascripts/cookie-policy-form.js --dist-dir exporter/assets/built --public-url /assets/", "watch_caseworker": "PARCEL_WORKERS=0 parcel watch --port 8401 ./caseworker/assets/javascripts/{main,head,bookmarks,cookie-policy-form,search-cases,desnz,tau,tau-edit,tau-multiple-assessment-edit,case-filters,refusal-review-consolidate,search-products}.js --dist-dir caseworker/assets/built --public-url /assets/", "watch": "rm -rf .parcel-cache && npm run build_exporter && npm run build_caseworker && concurrently 'npm run watch_exporter' 'npm run watch_caseworker'", diff --git a/ui_tests/caseworker/conftest.py b/ui_tests/caseworker/conftest.py index 20dcdd35a4..079da07868 100644 --- a/ui_tests/caseworker/conftest.py +++ b/ui_tests/caseworker/conftest.py @@ -429,6 +429,12 @@ def get_my_case_list(driver): # noqa """ driver.find_element(by=By.ID, value="link-menu").click() driver.find_element(by=By.LINK_TEXT, value="Cases").click() + current_sort_by = driver.find_element(by=By.ID, value="id_sort_by").get_attribute("value") + if current_sort_by != "-submitted_at": + case_list_page = CaseListPage(driver) + functions.open_case_filters(driver) + case_list_page.set_sort_by("-submitted_at") + functions.click_apply_filters(driver) @when(parsers.parse('I click on the "{queue_name}" queue in dropdown')) # noqa diff --git a/ui_tests/caseworker/pages/case_list_page.py b/ui_tests/caseworker/pages/case_list_page.py index 5d4d9ae747..dcc22c569b 100644 --- a/ui_tests/caseworker/pages/case_list_page.py +++ b/ui_tests/caseworker/pages/case_list_page.py @@ -59,6 +59,7 @@ class CaseListPage(BasePage): PARTY_ADDRESS_ID = "party_address" GOODS_RELATED_DESCRIPTION_ID = "goods_related_description" CONTROL_LIST_ENTRY_ID = "control_list_entry" + SORT_BY_ID = "id_sort_by" ADVANCED_FILTERS = [ CASE_REFERENCE_ID, @@ -220,3 +221,6 @@ def click_export_enforcement_xml(self): WebDriverWait(self.driver, 30 * settings.E2E_WAIT_MULTIPLIER).until( expected_conditions.presence_of_element_located((By.ID, self.EXPORT_ENFORCEMENT_XML_BUTTON_ID)) ).click() + + def set_sort_by(self, value): + Select(self.driver.find_element(by=By.ID, value=self.SORT_BY_ID)).select_by_value(value) diff --git a/unit_tests/caseworker/cases/views/test_case_filters.py b/unit_tests/caseworker/cases/views/test_case_filters.py index 455be558cc..bf48b76055 100644 --- a/unit_tests/caseworker/cases/views/test_case_filters.py +++ b/unit_tests/caseworker/cases/views/test_case_filters.py @@ -1,11 +1,14 @@ import pytest + from bs4 import BeautifulSoup from pytest_django.asserts import assertTemplateUsed from urllib import parse from django.urls import reverse +from caseworker.advice.constants import CASE_PROGRESSION_QUEUES from caseworker.queues.views.forms import CasesFiltersForm +from core import client @pytest.fixture(autouse=True) @@ -122,3 +125,73 @@ def test_case_filters_licence( "cancelled", "draft", ] + + +ALL_CASES_QUEUE = "00000000-0000-0000-0000-000000000001" +all_cases_sort_options = [ + ("submitted_at", "Submitted (oldest to newest)"), + ("-submitted_at", "Submitted (newest to oldest)"), +] + +ogd_queue_sort_options = [ + ("submitted_at", "Submitted (oldest to newest)"), + ("-submitted_at", "Submitted (newest to oldest)"), + ("time_on_queue", "Time on queue (oldest to newest)"), + ("-time_on_queue", "Time on queue (newest to oldest)"), +] + + +@pytest.mark.parametrize( + "queue_id, expected_sort_options", + [ + (ALL_CASES_QUEUE, all_cases_sort_options), + ] + + [(item, ogd_queue_sort_options) for item in CASE_PROGRESSION_QUEUES], +) +def test_time_on_queue_availability_on_queues( + authorized_client_factory, + mock_queues_list, + mock_cases, + mock_cases_head, + mock_no_bookmarks, + mock_notifications, + mock_new_mentions_count, + mock_gov_user, + gov_uk_user_id, + requests_mock, + queue_id, + expected_sort_options, +): + requests_mock.get(client._build_absolute_uri(f"/queues/{queue_id}"), json={"id": queue_id, "is_system_queue": True}) + requests_mock.get( + client._build_absolute_uri(f"/cases/?queue_id={queue_id}&page=1&selected_tab=all_cases&hidden=True"), + json={"results": {"queues": [], "cases": [], "filters": {"gov_users": []}}}, + ) + requests_mock.head( + client._build_absolute_uri(f"/cases/?queue_id={queue_id}&page=1&selected_tab=all_cases&hidden=True"), + headers={"Resource-Count": ""}, + ) + requests_mock.head( + client._build_absolute_uri(f"/cases/?queue_id={queue_id}&page=1&selected_tab=my_cases&hidden=True"), + headers={"Resource-Count": ""}, + ) + requests_mock.head( + client._build_absolute_uri(f"/cases/?queue_id={queue_id}&page=1&selected_tab=open_queries&hidden=True"), + headers={"Resource-Count": ""}, + ) + + user = { + "id": gov_uk_user_id, + "email": "govuser@example.com", + "first_name": "Foo", + "last_name": "Bar", + "status": "Active", + "default_queue": {"id": queue_id, "name": "All cases"}, + } + + authorized_client = authorized_client_factory(user) + + response = authorized_client.get(reverse("core:index")) + assertTemplateUsed(response, "queues/cases.html") + assert isinstance(response.context["form"], CasesFiltersForm) + assert response.context["form"].fields["sort_by"].choices == expected_sort_options diff --git a/unit_tests/caseworker/queues/views/test_cases.py b/unit_tests/caseworker/queues/views/test_cases.py index 2897ecfa50..518d657e6f 100644 --- a/unit_tests/caseworker/queues/views/test_cases.py +++ b/unit_tests/caseworker/queues/views/test_cases.py @@ -19,6 +19,7 @@ "queue_id": ["00000000-0000-0000-0000-000000000001"], "selected_tab": ["all_cases"], "hidden": ["true"], + "sort_by": ["submitted_at"], } @@ -312,6 +313,7 @@ def test_cases_queue_page_assigned_queues(authorized_client, mock_cases_search_t "queue_id": [queue_pk], "selected_tab": ["all_cases"], "hidden": ["false"], + "sort_by": ["-submitted_at"], } @@ -618,6 +620,7 @@ def test_tabs_with_all_cases_default(authorized_client, mock_cases_search, mock_ "page": ["1"], "queue_id": ["00000000-0000-0000-0000-000000000001"], "selected_tab": [tab], + "sort_by": ["submitted_at"], } in head_request_history @@ -652,6 +655,7 @@ def test_tabs_on_all_cases_queue(authorized_client, mock_cases_search, tab_name, "page": ["1"], "queue_id": ["00000000-0000-0000-0000-000000000001"], "selected_tab": [tab_name], + "sort_by": ["submitted_at"], } @@ -680,6 +684,7 @@ def test_tabs_on_team_queue( "page": ["1"], "queue_id": [queue_pk], "selected_tab": [tab_name], + "sort_by": ["-submitted_at"], } head_request_history = [x.qs for x in mock_cases_search_head.request_history] assert { @@ -687,6 +692,7 @@ def test_tabs_on_team_queue( "page": ["1"], "queue_id": [queue_pk], "selected_tab": ["all_cases"], + "sort_by": ["-submitted_at"], } in head_request_history tabs_with_hidden_param = ("my_cases", "open_queries") @@ -696,6 +702,7 @@ def test_tabs_on_team_queue( "page": ["1"], "queue_id": [queue_pk], "selected_tab": [tab], + "sort_by": ["-submitted_at"], } in head_request_history @@ -710,6 +717,7 @@ def test_tabs_on_team_queue_with_hidden_param( "page": ["1"], "queue_id": [queue_pk], "selected_tab": ["all_cases"], + "sort_by": ["-submitted_at"], } head_request_history = [x.qs for x in mock_cases_search_head.request_history] tabs_with_hidden_param = ("all_cases", "my_cases", "open_queries") @@ -719,6 +727,7 @@ def test_tabs_on_team_queue_with_hidden_param( "page": ["1"], "queue_id": [queue_pk], "selected_tab": [tab], + "sort_by": ["-submitted_at"], } in head_request_history @@ -1142,3 +1151,13 @@ def test_product_search_is_visible_to_specific_users_only( soup = BeautifulSoup(response.content, "html.parser") is_product_search_visible = "Search for products" in str(soup.find(id="link-product-search")) assert is_product_search_visible == expected + + +def test_queue_view_sort_params_persist(authorized_client): + response = authorized_client.get(reverse("core:index")) + assert response.status_code == 200 + assert authorized_client.session["case_search_sort_by"] == "submitted_at" + + authorized_client.get(reverse("core:index") + "?sort_by=-submitted_at") + assert response.status_code == 200 + assert authorized_client.session["case_search_sort_by"] == "-submitted_at"