From cdc2172976d8c9e7f63d22a9832011b0e16b2109 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Fri, 9 Oct 2026 18:06:38 -0400 Subject: [PATCH 1/4] Infer Massachusetts courts only from verified docket formats --- efile_app/efile/services/docket_courts.py | 50 +++++++++++++ efile_app/efile/static/js/case-lookup.js | 74 ++++++++++++++++++- .../efile/templates/efile/case_lookup.html | 13 +++- .../tests/fixtures/massachusetts_dockets.json | 14 ++++ efile_app/efile/tests/test_docket_courts.py | 54 ++++++++++++++ efile_app/efile/urls.py | 3 +- efile_app/efile/views/case_lookup.py | 19 +++++ 7 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 efile_app/efile/services/docket_courts.py create mode 100644 efile_app/efile/tests/fixtures/massachusetts_dockets.json create mode 100644 efile_app/efile/tests/test_docket_courts.py diff --git a/efile_app/efile/services/docket_courts.py b/efile_app/efile/services/docket_courts.py new file mode 100644 index 00000000..0d3f7ce2 --- /dev/null +++ b/efile_app/efile/services/docket_courts.py @@ -0,0 +1,50 @@ +"""Conservative Massachusetts docket inference from documented Trial Court formats. + +Format references and official examples are recorded in tests/fixtures/massachusetts_dockets.json. +MACourts supplies the mapping from Trial Court identifiers to Tyler identifiers; +we never assume the two systems use the same number. +""" + +import re + +from efile.services.court_location import _finder, normalize_court_code + +PROBATE_SITES = { + "BA": "P72", + "BR": "P73", + "DU": "P74", + "NA": "P75", + "BE": "P76", + "ES": "P77", + "FR": "P78", + "HD": "P79", + "HS": "P80", + "MI": "P81", + "NO": "P82", + "PL": "P83", + "SU": "P84", + "WO": "P85", +} + + +def infer_massachusetts_court(docket, courts, *, records=None): + number = re.sub(r"[\s-]", "", str(docket or "")).upper() + code, department = "", "" + if match := re.fullmatch(r"[0-9]{2}([0-9]{2})[A-Z]{2}([0-9]{5,6})", number): + code = str(int(match[1])) + department = "Superior Court" if len(match[2]) == 5 else "District Court" + elif match := re.fullmatch(r"([A-Z]{2})[0-9]{2}[ACDEWPRXS][0-9]{4}[A-Z]{2}", number): + code = PROBATE_SITES.get(match[1], "") + department = "Probate and Family Court" + if not code: + return None + records = _finder().catalog.records if records is None else records + candidates = { + normalize_court_code(record.tyler_code) + for record in records + if record.court_code == code and record.department == department and record.tyler_code + } + if len(candidates) != 1: + return None + matches = [court for court in courts if normalize_court_code(court["value"]) in candidates] + return matches[0] if len(matches) == 1 else None diff --git a/efile_app/efile/static/js/case-lookup.js b/efile_app/efile/static/js/case-lookup.js index 14174163..71340af2 100644 --- a/efile_app/efile/static/js/case-lookup.js +++ b/efile_app/efile/static/js/case-lookup.js @@ -23,6 +23,7 @@ async function mountCourtSelector() { const container = document.getElementById("court-selector"); + if (apiUtils.getCurrentJurisdiction() === "massachusetts") return false; if (!container || !window.courtSelector) return false; const selector = window.courtSelector.mount({ container, @@ -73,6 +74,73 @@ } } + const inferred = document.getElementById("inferred-court"); + if (inferred) courtSelect.required = false; + let inferenceGeneration = 0; + let manualCourt = Boolean(selectedCourtCode); + let inferredCode = ""; + let inferenceTimer; + async function inferCourt() { + if (!inferred || manualCourt) return; + const generation = ++inferenceGeneration; + try { + const params = new URLSearchParams({ + docket_number: caseNumber.value + }); + const response = await fetch(`${form.dataset.inferenceUrl}?${params}`); + const result = await response.json(); + if (generation !== inferenceGeneration || manualCourt) return; + const court = result.success && result.court; + inferred.hidden = !court; + document.getElementById("manual-court-field").hidden = Boolean(court); + courtSelect.required = false; + if (court) { + if (!Array.from(courtSelect.options).some(option => option.value === court.value)) { + courtSelect.add(new Option(court.text, court.value)); + } + courtSelect.value = court.value; + inferredCode = court.value; + document.getElementById("inferred-court-name").textContent = `${gettext("Court identified from your case number:")} ${court.text}`; + } else if (inferredCode) { + courtSelect.value = ""; + inferredCode = ""; + } + availability.check(); + } catch { + if (generation !== inferenceGeneration) return; + inferred.hidden = true; + document.getElementById("manual-court-field").hidden = false; + courtSelect.required = false; + if (inferredCode) courtSelect.value = ""; + inferredCode = ""; + availability.check(); + } + } + if (inferred) { + document.getElementById("change-inferred-court").addEventListener("click", () => { + manualCourt = true; + ++inferenceGeneration; + inferred.hidden = true; + document.getElementById("manual-court-field").hidden = false; + courtSelect.required = false; + courtSelect.focus(); + }); + courtSelect.addEventListener("change", () => { + manualCourt = true; + ++inferenceGeneration; + }); + caseNumber.addEventListener("input", () => { + ++inferenceGeneration; + if (!manualCourt && inferredCode) { + courtSelect.value = ""; + inferred.hidden = true; + document.getElementById("manual-court-field").hidden = false; + } + clearTimeout(inferenceTimer); + inferenceTimer = setTimeout(inferCourt, 250); + }); + } + form.addEventListener("submit", async (event) => { event.preventDefault(); errorBox.hidden = true; @@ -80,6 +148,7 @@ submitButton.disabled = true; try { + if (!courtSelect.value && inferred && !manualCourt) await inferCourt(); if (!courtSelect.value) throw new Error("Choose a court to search for your case."); const jurisdiction = apiUtils.getCurrentJurisdiction(); const lookup = await apiUtils.fetchJSON("/api/suffolk/lookup-case/", "GET", { @@ -122,5 +191,8 @@ } }); - loadCourts().then(() => availability.check(courtSelect.closest(".form-field"))); + loadCourts().then(() => { + availability.check(courtSelect.closest(".form-field")); + inferCourt(); + }); })(); \ No newline at end of file diff --git a/efile_app/efile/templates/efile/case_lookup.html b/efile_app/efile/templates/efile/case_lookup.html index b26cabf7..3b146618 100644 --- a/efile_app/efile/templates/efile/case_lookup.html +++ b/efile_app/efile/templates/efile/case_lookup.html @@ -19,11 +19,18 @@

{% translate "Find your court case" %}

{% include "efile/components/extraction_marker_help.html" %} {% endif %} -
+ {% csrf_token %} {% include "efile/components/filing_availability_notice.html" %} + {% if jurisdiction == "massachusetts" %} + + {% endif %}
-
+
{% translate "Court" %} {# Filled in by court-selector.js where the jurisdiction configures guided questions. The select below keeps carrying the answer either way. #}
@@ -45,7 +52,7 @@

{% translate "Find your court case" %}

id="case-number" name="case_number" value="{{ docket_number }}" - placeholder="e.g., 2025MR000123" + placeholder="{% if jurisdiction == 'massachusetts' %}e.g., 1473CV00213{% elif jurisdiction == 'vermont' %}e.g., 24-CV-00123{% else %}e.g., 2025MR000123{% endif %}" autocomplete="off" aria-describedby="case-number-hint" required /> diff --git a/efile_app/efile/tests/fixtures/massachusetts_dockets.json b/efile_app/efile/tests/fixtures/massachusetts_dockets.json new file mode 100644 index 00000000..f94ac5da --- /dev/null +++ b/efile_app/efile/tests/fixtures/massachusetts_dockets.json @@ -0,0 +1,14 @@ +{ + "sources": [ + "https://www.mass.gov/info-details/district-court-get-to-know-the-case-number-format", + "https://www.mass.gov/info-details/superior-court-get-to-know-the-case-number-format", + "https://www.mass.gov/info-details/probate-and-family-court-get-to-know-the-case-number-format", + "https://www.mass.gov/info-details/trial-court-codes-numerical-listing" + ], + "verified_examples": [ + {"docket": "1448CV001026", "court_code": "48", "tyler_code": "336", "name": "Ayer District Court"}, + {"docket": "1473CV00213", "court_code": "73", "tyler_code": "1126", "name": "Bristol County Superior Court"}, + {"docket": "ES15A0064AD", "court_code": "P77", "tyler_code": "352", "name": "Essex Probate and Family Court"} + ], + "manual_examples": ["98-1234", "123456", "24-CV-12", "1448CV001026-extra", "1499CV001026", "ES15Z0064AD", "", "1:24-cv-00123"] +} diff --git a/efile_app/efile/tests/test_docket_courts.py b/efile_app/efile/tests/test_docket_courts.py new file mode 100644 index 00000000..a561d837 --- /dev/null +++ b/efile_app/efile/tests/test_docket_courts.py @@ -0,0 +1,54 @@ +import json +from pathlib import Path +from types import SimpleNamespace + +import pytest + +from efile.services.docket_courts import infer_massachusetts_court + +FIXTURES = json.loads((Path(__file__).parent / "fixtures/massachusetts_dockets.json").read_text()) + + +@pytest.mark.parametrize("example", FIXTURES["verified_examples"]) +def test_official_examples_resolve_only_to_an_offered_court(example): + offered = [{"value": example["tyler_code"], "text": example["name"]}] + assert infer_massachusetts_court(example["docket"], offered) == offered[0] + assert infer_massachusetts_court(example["docket"], []) is None + + +@pytest.mark.parametrize("docket", FIXTURES["manual_examples"]) +def test_unrecognized_and_legacy_numbers_need_manual_selection(docket): + assert infer_massachusetts_court(docket, [{"value": "336", "text": "Ayer"}]) is None + + +def test_ambiguous_mapping_does_not_choose_a_court(): + records = [ + SimpleNamespace(court_code="48", department="District Court", tyler_code=code) for code in ["one", "two"] + ] + offered = [{"value": code, "text": code} for code in ["one", "two"]] + assert infer_massachusetts_court("1448CV001026", offered, records=records) is None + + +def test_spacing_and_case_do_not_change_a_verified_match(): + offered = [{"value": "336", "text": "Ayer District Court"}] + assert infer_massachusetts_court("14 48 cv 001026", offered) == offered[0] + + +@pytest.mark.django_db +def test_inference_endpoint_requires_auth_and_returns_an_offered_court(client, django_user_model): + from unittest.mock import patch + + from django.urls import reverse + + from efile.models import FilingDraft + from efile.tests.test_document_extractions import authorize + + url = reverse("docket_court", kwargs={"jurisdiction": "massachusetts"}) + assert client.get(url).status_code == 401 + user = django_user_model.objects.create_user(username="docket-test", tyler_jurisdiction="massachusetts") + draft = FilingDraft.objects.create(user=user, jurisdiction="massachusetts") + authorize(client, draft) + offered = [{"value": "336", "text": "Ayer District Court"}] + with patch("efile.services.court_selection.fetch_courts", return_value=offered): + response = client.get(url, {"docket_number": "1448CV001026"}) + assert response.json() == {"success": True, "court": offered[0]} diff --git a/efile_app/efile/urls.py b/efile_app/efile/urls.py index fdbfd4fe..7280620a 100644 --- a/efile_app/efile/urls.py +++ b/efile_app/efile/urls.py @@ -9,7 +9,7 @@ from .views.api_views import get_case_data_api, get_filing_components from .views.case_confirmation import case_confirmation -from .views.case_lookup import case_lookup +from .views.case_lookup import case_lookup, docket_court from .views.case_questions import case_questions from .views.choose_jurisdiction import change_jurisdiction, choose_jurisdiction from .views.confirmation import filing_confirmation @@ -107,6 +107,7 @@ def jurisdiction_homepage(request, jurisdiction): name="document_extraction_status", ), path("jurisdiction//extraction-review/", extraction_review, name="extraction_review"), + path("jurisdiction//docket-court/", docket_court, name="docket_court"), path("jurisdiction//case-lookup/", case_lookup, name="case_lookup"), path("jurisdiction//case-confirmation/", case_confirmation, name="case_confirmation"), path("jurisdiction//document-checklist/", document_checklist, name="document_checklist"), diff --git a/efile_app/efile/views/case_lookup.py b/efile_app/efile/views/case_lookup.py index 83b17715..cc3d65b9 100644 --- a/efile_app/efile/views/case_lookup.py +++ b/efile_app/efile/views/case_lookup.py @@ -91,3 +91,22 @@ def case_lookup(request, jurisdiction): } context.update(get_workflow_context(WorkflowStepKey.CASE_LOOKUP, jurisdiction, draft)) return render(request, "efile/case_lookup.html", context) + + +@require_http_methods(["GET"]) +def docket_court(request, jurisdiction): + """Resolve only a documented number to one court offered by this service.""" + if not request.user.is_authenticated or not get_tyler_token(request, jurisdiction): + return JsonResponse({"success": False}, status=401) + if jurisdiction != "massachusetts": + return JsonResponse({"success": True, "court": None}) + import requests + + from efile.services.court_selection import fetch_courts + from efile.services.docket_courts import infer_massachusetts_court + + try: + court = infer_massachusetts_court(request.GET.get("docket_number", ""), fetch_courts(jurisdiction)) + except (requests.RequestException, ValueError, ImportError): + return JsonResponse({"success": False, "court": None}, status=503) + return JsonResponse({"success": True, "court": court}) From 525a1a6286ae4a4d9616ca83a7fa80ce57e73420 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Fri, 9 Oct 2026 20:28:33 -0400 Subject: [PATCH 2/4] Import docket inference at module level and set court optional once Co-Authored-By: Claude Opus 5.5 --- efile_app/efile/static/js/case-lookup.js | 4 +--- efile_app/efile/tests/test_docket_courts.py | 2 +- efile_app/efile/views/case_lookup.py | 10 ++++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/efile_app/efile/static/js/case-lookup.js b/efile_app/efile/static/js/case-lookup.js index 71340af2..7012a039 100644 --- a/efile_app/efile/static/js/case-lookup.js +++ b/efile_app/efile/static/js/case-lookup.js @@ -75,6 +75,7 @@ } const inferred = document.getElementById("inferred-court"); + // The inferred court or the submit check asks for a court, not the browser. if (inferred) courtSelect.required = false; let inferenceGeneration = 0; let manualCourt = Boolean(selectedCourtCode); @@ -93,7 +94,6 @@ const court = result.success && result.court; inferred.hidden = !court; document.getElementById("manual-court-field").hidden = Boolean(court); - courtSelect.required = false; if (court) { if (!Array.from(courtSelect.options).some(option => option.value === court.value)) { courtSelect.add(new Option(court.text, court.value)); @@ -110,7 +110,6 @@ if (generation !== inferenceGeneration) return; inferred.hidden = true; document.getElementById("manual-court-field").hidden = false; - courtSelect.required = false; if (inferredCode) courtSelect.value = ""; inferredCode = ""; availability.check(); @@ -122,7 +121,6 @@ ++inferenceGeneration; inferred.hidden = true; document.getElementById("manual-court-field").hidden = false; - courtSelect.required = false; courtSelect.focus(); }); courtSelect.addEventListener("change", () => { diff --git a/efile_app/efile/tests/test_docket_courts.py b/efile_app/efile/tests/test_docket_courts.py index a561d837..2f8dd29d 100644 --- a/efile_app/efile/tests/test_docket_courts.py +++ b/efile_app/efile/tests/test_docket_courts.py @@ -49,6 +49,6 @@ def test_inference_endpoint_requires_auth_and_returns_an_offered_court(client, d draft = FilingDraft.objects.create(user=user, jurisdiction="massachusetts") authorize(client, draft) offered = [{"value": "336", "text": "Ayer District Court"}] - with patch("efile.services.court_selection.fetch_courts", return_value=offered): + with patch("efile.views.case_lookup.fetch_courts", return_value=offered): response = client.get(url, {"docket_number": "1448CV001026"}) assert response.json() == {"success": True, "court": offered[0]} diff --git a/efile_app/efile/views/case_lookup.py b/efile_app/efile/views/case_lookup.py index cc3d65b9..5d653b9a 100644 --- a/efile_app/efile/views/case_lookup.py +++ b/efile_app/efile/views/case_lookup.py @@ -1,12 +1,15 @@ import json +import requests from django.contrib import messages from django.http import JsonResponse from django.shortcuts import redirect, render from django.views.decorators.http import require_http_methods from efile.api.suffolk_api_views import get_tyler_token +from efile.services.court_selection import fetch_courts from efile.services.current_drafts import ensure_current_draft +from efile.services.docket_courts import infer_massachusetts_court from efile.services.drafts import draft_snapshot, write_case_data from efile.workflow import ( ExistingCase, @@ -100,13 +103,8 @@ def docket_court(request, jurisdiction): return JsonResponse({"success": False}, status=401) if jurisdiction != "massachusetts": return JsonResponse({"success": True, "court": None}) - import requests - - from efile.services.court_selection import fetch_courts - from efile.services.docket_courts import infer_massachusetts_court - try: court = infer_massachusetts_court(request.GET.get("docket_number", ""), fetch_courts(jurisdiction)) - except (requests.RequestException, ValueError, ImportError): + except (requests.RequestException, ValueError): return JsonResponse({"success": False, "court": None}, status=503) return JsonResponse({"success": True, "court": court}) From 67c2689159c0e8516cec5e1eab31e6e0a1aab1e2 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Fri, 9 Oct 2026 21:04:22 -0400 Subject: [PATCH 3/4] Read MACourts records through a public accessor Co-Authored-By: Claude Opus 5.5 --- efile_app/efile/services/court_location.py | 5 +++++ efile_app/efile/services/docket_courts.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/efile_app/efile/services/court_location.py b/efile_app/efile/services/court_location.py index 119536e6..7364e3ad 100644 --- a/efile_app/efile/services/court_location.py +++ b/efile_app/efile/services/court_location.py @@ -103,6 +103,11 @@ def _finder(): return build_default_finder() +def massachusetts_court_records(): + """MACourts catalog rows, which map Trial Court identifiers to Tyler's.""" + return _finder().catalog.records + + def _massachusetts_matches(place: str, court_types: list[str]) -> list[dict[str, Any]]: try: from macourts import Location diff --git a/efile_app/efile/services/docket_courts.py b/efile_app/efile/services/docket_courts.py index 0d3f7ce2..3d459e4a 100644 --- a/efile_app/efile/services/docket_courts.py +++ b/efile_app/efile/services/docket_courts.py @@ -7,7 +7,7 @@ import re -from efile.services.court_location import _finder, normalize_court_code +from efile.services.court_location import massachusetts_court_records, normalize_court_code PROBATE_SITES = { "BA": "P72", @@ -38,7 +38,7 @@ def infer_massachusetts_court(docket, courts, *, records=None): department = "Probate and Family Court" if not code: return None - records = _finder().catalog.records if records is None else records + records = massachusetts_court_records() if records is None else records candidates = { normalize_court_code(record.tyler_code) for record in records From 16aed8750b08b3604e8b1d4e2e539cefec81a754 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Fri, 9 Oct 2026 22:05:41 -0400 Subject: [PATCH 4/4] Ask Massachusetts court questions only when the case number cannot The guided court selector was skipped for Massachusetts, so a number that names no court left filers with the flat court list. The questions now appear once inference fails, or when the filer chooses Change court, where they open on the inferred court. A court the selector publishes while it is starting no longer counts as the filer's choice, so it cannot stop a verified case number from settling the court. Co-Authored-By: Claude Opus 5.5 --- efile_app/efile/static/js/case-lookup.js | 70 +++++++++++++------ .../efile/templates/efile/case_lookup.html | 4 +- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/efile_app/efile/static/js/case-lookup.js b/efile_app/efile/static/js/case-lookup.js index 7012a039..be51f6d7 100644 --- a/efile_app/efile/static/js/case-lookup.js +++ b/efile_app/efile/static/js/case-lookup.js @@ -21,20 +21,37 @@ }); courtSelect.addEventListener("change", () => availability.check(courtSelect.closest(".form-field"))); - async function mountCourtSelector() { + // Only Massachusetts shows this: its case numbers can name the court. The + // guided court questions wait until the number has not settled the court, + // so they never compete with an inferred one. + const inferred = document.getElementById("inferred-court"); + const manualCourtField = document.getElementById("manual-court-field"); + let selector = null; + let guidedCourt = false; + // A court published while the questions are being drawn is not the filer's + // own answer, so it does not stop the case number from settling the court. + let selectorStarting = false; + + async function mountCourtSelector(courtCode) { const container = document.getElementById("court-selector"); - if (apiUtils.getCurrentJurisdiction() === "massachusetts") return false; if (!container || !window.courtSelector) return false; - const selector = window.courtSelector.mount({ + selector ||= window.courtSelector.mount({ container, jurisdiction: apiUtils.getCurrentJurisdiction(), select: courtSelect, }); - const started = await selector.start(selectedCourtCode || "", guessedCourt || ""); + selectorStarting = true; + let started; + try { + started = await selector.start(courtCode || "", guessedCourt || ""); + } finally { + selectorStarting = false; + } if (!started) { - container.remove(); - return false; + if (!guidedCourt) container.remove(); + return guidedCourt; } + guidedCourt = true; courtSelect.hidden = true; // Native validation cannot point at a hidden field, and the selector is // what asks for the court now, so the check moves into the submit below. @@ -45,7 +62,7 @@ async function loadCourts() { // Guided questions where the jurisdiction configures them, the flat // list everywhere else. Either way the answer lands in the same select. - if (await mountCourtSelector()) return; + if (!inferred && await mountCourtSelector(selectedCourtCode)) return; try { const response = await apiUtils.fetchJSON("/api/dropdowns/courts/", "GET", { jurisdiction: apiUtils.getCurrentJurisdiction(), @@ -74,13 +91,20 @@ } } - const inferred = document.getElementById("inferred-court"); // The inferred court or the submit check asks for a court, not the browser. if (inferred) courtSelect.required = false; let inferenceGeneration = 0; let manualCourt = Boolean(selectedCourtCode); let inferredCode = ""; let inferenceTimer; + + async function showManualCourt(courtCode = "") { + inferred.hidden = true; + if (!manualCourtField.hidden) return; + manualCourtField.hidden = false; + await mountCourtSelector(courtCode); + } + async function inferCourt() { if (!inferred || manualCourt) return; const generation = ++inferenceGeneration; @@ -92,47 +116,52 @@ const result = await response.json(); if (generation !== inferenceGeneration || manualCourt) return; const court = result.success && result.court; - inferred.hidden = !court; - document.getElementById("manual-court-field").hidden = Boolean(court); if (court) { + inferred.hidden = false; + manualCourtField.hidden = true; if (!Array.from(courtSelect.options).some(option => option.value === court.value)) { courtSelect.add(new Option(court.text, court.value)); } courtSelect.value = court.value; inferredCode = court.value; document.getElementById("inferred-court-name").textContent = `${gettext("Court identified from your case number:")} ${court.text}`; - } else if (inferredCode) { - courtSelect.value = ""; + } else { + if (inferredCode) courtSelect.value = ""; inferredCode = ""; + await showManualCourt(); } availability.check(); } catch { if (generation !== inferenceGeneration) return; - inferred.hidden = true; - document.getElementById("manual-court-field").hidden = false; if (inferredCode) courtSelect.value = ""; inferredCode = ""; + await showManualCourt(); availability.check(); } } if (inferred) { - document.getElementById("change-inferred-court").addEventListener("click", () => { + document.getElementById("change-inferred-court").addEventListener("click", async () => { manualCourt = true; ++inferenceGeneration; - inferred.hidden = true; - document.getElementById("manual-court-field").hidden = false; - courtSelect.focus(); + // The questions open on the inferred court, so changing it starts + // from what the filer was just shown. + await showManualCourt(inferredCode); + const firstQuestion = guidedCourt && manualCourtField.querySelector("#court-selector input, #court-selector select, #court-selector button"); + (firstQuestion || courtSelect).focus(); }); courtSelect.addEventListener("change", () => { + if (selectorStarting) return; manualCourt = true; ++inferenceGeneration; }); caseNumber.addEventListener("input", () => { ++inferenceGeneration; if (!manualCourt && inferredCode) { + // Wait for the new number to settle the court or not before + // asking for one. courtSelect.value = ""; + inferredCode = ""; inferred.hidden = true; - document.getElementById("manual-court-field").hidden = false; } clearTimeout(inferenceTimer); inferenceTimer = setTimeout(inferCourt, 250); @@ -191,6 +220,7 @@ loadCourts().then(() => { availability.check(courtSelect.closest(".form-field")); - inferCourt(); + if (inferred && manualCourt) showManualCourt(selectedCourtCode); + else inferCourt(); }); })(); \ No newline at end of file diff --git a/efile_app/efile/templates/efile/case_lookup.html b/efile_app/efile/templates/efile/case_lookup.html index 3b146618..cc73d63c 100644 --- a/efile_app/efile/templates/efile/case_lookup.html +++ b/efile_app/efile/templates/efile/case_lookup.html @@ -30,7 +30,9 @@

{% translate "Find your court case" %}

{% endif %}
-
+
{% translate "Court" %} {# Filled in by court-selector.js where the jurisdiction configures guided questions. The select below keeps carrying the answer either way. #}