From e2a4e871133b7a2f7e652f9343a23e1afdea1e50 Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Tue, 18 Jun 2024 08:15:34 +0800 Subject: [PATCH 1/3] Bugfix combined (Typesense) search views. --- .../templates/referral/prs_index_search.html | 2 +- .../referral/prs_index_search_combined.html | 22 +++--- prs2/referral/views.py | 79 +++++++++++++------ 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/prs2/referral/templates/referral/prs_index_search.html b/prs2/referral/templates/referral/prs_index_search.html index 501bd2a9..c3722d77 100644 --- a/prs2/referral/templates/referral/prs_index_search.html +++ b/prs2/referral/templates/referral/prs_index_search.html @@ -37,7 +37,7 @@

{{ page_heading }}

Search matches: diff --git a/prs2/referral/templates/referral/prs_index_search_combined.html b/prs2/referral/templates/referral/prs_index_search_combined.html index abd35806..f6cd1247 100644 --- a/prs2/referral/templates/referral/prs_index_search_combined.html +++ b/prs2/referral/templates/referral/prs_index_search_combined.html @@ -44,33 +44,31 @@

{{ page_heading }}

Search matches: diff --git a/prs2/referral/views.py b/prs2/referral/views.py index 74cc4160..fd7e1276 100644 --- a/prs2/referral/views.py +++ b/prs2/referral/views.py @@ -189,43 +189,56 @@ def get_context_data(self, **kwargs): paginator = Paginator(tuple(_ for _ in range(search_result["found"])), 20) context["page_obj"] = paginator.get_page(page) - # Replace underscores in search field names with spaces. - for hit in search_result["hits"]: - highlights = [] - for highlight in hit["highlights"]: - highlight["field"] = highlight["field"].replace("_", " ") - highlights.append(highlight) - hit["highlights"] = highlights - if collection == "referrals": for hit in search_result["hits"]: + highlights = [] + for key, value in hit["highlight"].items(): + # Replace underscores in search field names with spaces. + highlights.append((key.replace("_", " "), value["snippet"])) + hit["highlights"] = highlights context["search_result"].append({ "object": Referral.objects.get(pk=hit["document"]["id"]), - "highlights": hit["highlights"], + "highlights": highlights, }) elif collection == "records": for hit in search_result["hits"]: + highlights = [] + for key, value in hit["highlight"].items(): + highlights.append((key.replace("_", " "), value["snippet"])) + hit["highlights"] = highlights context["search_result"].append({ "object": Record.objects.get(pk=hit["document"]["id"]), - "highlights": hit["highlights"], + "highlights": highlights, }) elif collection == "notes": for hit in search_result["hits"]: + highlights = [] + for key, value in hit["highlight"].items(): + highlights.append((key.replace("_", " "), value["snippet"])) + hit["highlights"] = highlights context["search_result"].append({ "object": Note.objects.get(pk=hit["document"]["id"]), - "highlights": hit["highlights"], + "highlights": highlights, }) elif collection == "tasks": for hit in search_result["hits"]: + highlights = [] + for key, value in hit["highlight"].items(): + highlights.append((key.replace("_", " "), value["snippet"])) + hit["highlights"] = highlights context["search_result"].append({ "object": Task.objects.get(pk=hit["document"]["id"]), - "highlights": hit["highlights"], + "highlights": highlights, }) elif collection == "conditions": for hit in search_result["hits"]: + highlights = [] + for key, value in hit["highlight"].items(): + highlights.append((key.replace("_", " "), value["snippet"])) + hit["highlights"] = highlights context["search_result"].append({ "object": Condition.objects.get(pk=hit["document"]["id"]), - "highlights": hit["highlights"], + "highlights": highlights, }) return context @@ -262,10 +275,20 @@ def get_context_data(self, **kwargs): search_result = client.collections["referrals"].documents.search(search_q) context["referrals_count"] = search_result["found"] for hit in search_result["hits"]: + # Explanation for the line below: the Typesense API search response + # returns a list of document resources, each containing a `highlight` key + # that consists of a dict which contains 1+ `` keys, each of which + # consists of a dict containing the text snippet and matched tokens. + # Earlier (<0.25) versions of the API returned `highlights` as a list instead + # of `highlight` as this dict. + # This is REALLY AWKWARD in this instance, as the highlight(s) will be + # for some random `field_name`. So the next line just dumps out the FIRST + # element in the `highlight` dict for usage below (we only need one). + highlight = next(iter(hit["highlight"].values())) ref = Referral.objects.get(pk=hit["document"]["id"]) referrals[ref.pk] = { "referral": ref, - "highlights": hit["highlights"], + "highlight": highlight["snippet"], "records": [], "notes": [], "tasks": [], @@ -277,14 +300,15 @@ def get_context_data(self, **kwargs): search_result = client.collections["records"].documents.search(search_q) context["records_count"] = search_result["found"] for hit in search_result["hits"]: + highlight = next(iter(hit["highlight"].values())) ref = Referral.objects.get(pk=hit["document"]["referral_id"]) if ref.pk in referrals: - referrals[ref.pk]["records"].append((hit["document"]["id"], hit["highlights"][0])) + referrals[ref.pk]["records"].append((hit["document"]["id"], highlight["snippet"])) else: referrals[ref.pk] = { "referral": ref, - "highlights": [], - "records": [(hit["document"]["id"], hit["highlights"][0])], + "highlight": {}, + "records": [(hit["document"]["id"], highlight["snippet"])], "notes": [], "tasks": [], "conditions": [], @@ -295,15 +319,16 @@ def get_context_data(self, **kwargs): search_result = client.collections["notes"].documents.search(search_q) context["notes_count"] = search_result["found"] for hit in search_result["hits"]: + highlight = next(iter(hit["highlight"].values())) ref = Referral.objects.get(pk=hit["document"]["referral_id"]) if ref.pk in referrals: - referrals[ref.pk]["notes"].append((hit["document"]["id"], hit["highlights"][0])) + referrals[ref.pk]["notes"].append((hit["document"]["id"], highlight["snippet"])) else: referrals[ref.pk] = { "referral": ref, - "highlights": [], + "highlight": {}, "records": [], - "notes": [(hit["document"]["id"], hit["highlights"][0])], + "notes": [(hit["document"]["id"], highlight["snippet"])], "tasks": [], "conditions": [], } @@ -313,16 +338,17 @@ def get_context_data(self, **kwargs): search_result = client.collections["tasks"].documents.search(search_q) context["tasks_count"] = search_result["found"] for hit in search_result["hits"]: + highlight = next(iter(hit["highlight"].values())) ref = Referral.objects.get(pk=hit["document"]["referral_id"]) if ref.pk in referrals: - referrals[ref.pk]["tasks"].append((hit["document"]["id"], hit["highlights"][0])) + referrals[ref.pk]["tasks"].append((hit["document"]["id"], highlight["snippet"])) else: referrals[ref.pk] = { "referral": ref, - "highlights": [], + "highlight": {}, "records": [], "notes": [], - "tasks": [(hit["document"]["id"], hit["highlights"][0])], + "tasks": [(hit["document"]["id"], highlight["snippet"])], "conditions": [], } @@ -333,16 +359,17 @@ def get_context_data(self, **kwargs): for hit in search_result["hits"]: if "referral_id" in hit["document"]: ref = Referral.objects.get(pk=hit["document"]["referral_id"]) + highlight = next(iter(hit["highlight"].values())) if ref.pk in referrals: - referrals[ref.pk]["conditions"].append((hit["document"]["id"], hit["highlights"][0])) + referrals[ref.pk]["conditions"].append((hit["document"]["id"], highlight["snippet"])) else: referrals[ref.pk] = { "referral": ref, - "highlights": [], + "highlight": {}, "records": [], "notes": [], "tasks": [], - "conditions": [(hit["document"]["id"], hit["highlights"][0])], + "conditions": [(hit["document"]["id"], highlight["snippet"])], } # Combine the results into the template context (sort referrals by descending ID). From 43a41fcbbb053b7bda17919d75c7e96aa9eeb03d Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Tue, 18 Jun 2024 08:16:20 +0800 Subject: [PATCH 2/3] Increment project minor version. --- kustomize/overlays/prod/kustomization.yaml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kustomize/overlays/prod/kustomization.yaml b/kustomize/overlays/prod/kustomization.yaml index fab9132a..56319275 100644 --- a/kustomize/overlays/prod/kustomization.yaml +++ b/kustomize/overlays/prod/kustomization.yaml @@ -30,4 +30,4 @@ patches: - path: geoserver_service_patch.yaml images: - name: ghcr.io/dbca-wa/prs - newTag: 2.5.47 + newTag: 2.5.48 diff --git a/pyproject.toml b/pyproject.toml index 588bfac7..b6cf4901 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "prs" -version = "2.5.47" +version = "2.5.48" description = "Planning Referral System corporate application" authors = ["Ashley Felton "] license = "Apache-2.0" From 0c73565db20a2c48fc3df9c5e18a0abf8502b30d Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Tue, 18 Jun 2024 08:18:55 +0800 Subject: [PATCH 3/3] Increment project dependency versions. --- .github/workflows/image-build-scan.yml | 2 +- poetry.lock | 22 +++++++++++----------- pyproject.toml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/image-build-scan.yml b/.github/workflows/image-build-scan.yml index 8c242369..736445c3 100644 --- a/.github/workflows/image-build-scan.yml +++ b/.github/workflows/image-build-scan.yml @@ -58,7 +58,7 @@ jobs: # Build and push Docker image (not on PR) #---------------------------------------------- - name: Build and push Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: ${{ github.event_name != 'pull_request' }} diff --git a/poetry.lock b/poetry.lock index fa341455..14048a7e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -960,18 +960,18 @@ python-dateutil = ">=2.4" [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.1-py3-none-any.whl", hash = "sha256:71b3102950e91dfc1bb4209b64be4dc8854f40e5f534428d8684f953ac847fac"}, + {file = "filelock-3.15.1.tar.gz", hash = "sha256:58a2549afdf9e02e10720eaa4d4470f56386d7a6f72edd7d0596337af8ed7ad8"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -1923,13 +1923,13 @@ files = [ [[package]] name = "redis" -version = "5.0.5" +version = "5.0.6" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.5-py3-none-any.whl", hash = "sha256:30b47d4ebb6b7a0b9b40c1275a19b87bb6f46b3bed82a89012cf56dea4024ada"}, - {file = "redis-5.0.5.tar.gz", hash = "sha256:3417688621acf6ee368dec4a04dd95881be24efd34c79f00d31f62bb528800ae"}, + {file = "redis-5.0.6-py3-none-any.whl", hash = "sha256:c0d6d990850c627bbf7be01c5c4cbaadf67b48593e913bb71c9819c30df37eee"}, + {file = "redis-5.0.6.tar.gz", hash = "sha256:38473cd7c6389ad3e44a91f4c3eaf6bcb8a9f746007f29bf4fb20824ff0b2197"}, ] [package.dependencies] @@ -2167,13 +2167,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -2289,4 +2289,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "a917b827189e6885c4e057e9f90ee4df8947fd250c794054cbd11dfb0e6a3fb2" +content-hash = "9450871a0f0ae5453e270ddda0823727fb7926f0b8e10fa05f3920581c990c5a" diff --git a/pyproject.toml b/pyproject.toml index b6cf4901..711b8c5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ django-crum = "0.7.9" django-storages = {version = "1.14.3", extras = ["azure"]} sentry-sdk = {version = "2.5.1", extras = ["django"]} crispy-bootstrap5 = "2024.2" -redis = "5.0.5" +redis = "5.0.6" xlsxwriter = "3.2.0" [tool.poetry.group.dev.dependencies]