Skip to content

Commit 0339135

Browse files
authored
Merge branch 'main' into 599-feat-add-logic-to-download-results
2 parents cf4958e + 4013f8e commit 0339135

24 files changed

+1769
-248
lines changed

.github/workflows/lint.yml

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ jobs:
9292
cl/users/management/commands/cl_retry_failed_email.py \
9393
cl/users/tasks.py \
9494
cl/recap/management/commands/remove_appellate_entries_with_long_numbers.py \
95+
cl/recap/utils.py \
9596
cl/search/management/commands/cl_index_parent_and_child_docs.py \
9697
cl/search/management/commands/sweep_indexer.py \
9798
cl/search/management/commands/pacer_bulk_fetch.py

cl/assets/templates/base.html

-4
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,13 @@ <h1>You did not supply the "private" variable to your template.
142142
tabindex="204"><i class="fa fa-bookmark-o gray fa-fw"></i>&nbsp;Notes</a></li>
143143
<li><a href="{% url "tag_list" username=user.username %}"
144144
tabindex="205"><i class="fa fa-tags gray fa-fw"></i>&nbsp;Tags</a></li>
145-
{% flag "pray-and-pay" %}
146145
<li><a href="{% url 'user_prayers' user.username %}" tabindex="206">
147146
<div class="fa gray fa-fw">
148147
{% include "includes/hand-holding-heart.svg" %}
149148
</div>
150149
&nbsp;Prayers
151150
</a>
152151
</li><!--need to fix class-->
153-
{% endflag %}
154152
<li class="divider"></li>
155153
<li><a href="{% url "profile_your_support" %}"
156154
tabindex="207"><i class="fa fa-money gray fa-fw"></i>&nbsp;Your Support</a></li>
@@ -240,11 +238,9 @@ <h1>You did not supply the "private" variable to your template.
240238
<li>
241239
<a href="https://free.law/recap/" tabindex="202">Install RECAP</a>
242240
</li>
243-
{% flag "pray-and-pay" %}
244241
<li>
245242
<a href="{% url "top_prayers" %}" tabindex="203">Pray and Pay Project</a>
246243
</li>
247-
{% endflag %}
248244
<li>
249245
<a href="{% url "alert_help" %}#recap-alerts" tabindex="204">Get Case Alerts</a>
250246
</li>

cl/citations/admin.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from admin_cursor_paginator import CursorPaginatorAdmin
2+
from django.contrib import admin
3+
4+
from cl.citations.models import UnmatchedCitation
5+
6+
7+
@admin.register(UnmatchedCitation)
8+
class UnmatchedCitationAdmin(CursorPaginatorAdmin):
9+
list_display = (
10+
"__str__",
11+
"citing_opinion",
12+
)
13+
list_display_links = ("citing_opinion",)
14+
list_filter = ("type", "status")
15+
search_fields = (
16+
"volume",
17+
"reporter",
18+
"page",
19+
)
20+
raw_id_fields = ("citing_opinion",)
21+
22+
def formfield_for_choice_field(self, db_field, request, **kwargs):
23+
if db_field.name == "status":
24+
# Show only integer values in the dropdown
25+
kwargs["choices"] = [
26+
(value, value) for value, _ in db_field.choices
27+
]
28+
29+
# Generate a new help text including both value and description
30+
choices_text = "<br>".join(
31+
f"<strong>{value}:</strong> {desc}"
32+
for value, desc in db_field.choices
33+
)
34+
kwargs["help_text"] = (
35+
f"<div>{db_field.help_text}</div><div>{choices_text}</div>"
36+
)
37+
38+
return super().formfield_for_choice_field(db_field, request, **kwargs)

cl/corpus_importer/task_canvases.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
get_bankr_claims_registry,
1212
get_docket_by_pacer_case_id,
1313
get_pacer_case_id_and_title,
14-
make_attachment_pq_object,
14+
save_attachment_pq_object,
1515
)
1616
from cl.lib.celery_utils import CeleryThrottle
1717
from cl.recap.tasks import process_recap_attachment
@@ -73,6 +73,6 @@ def get_district_attachment_pages(options, rd_pks, tag_names, session):
7373
throttle.maybe_wait()
7474
chain(
7575
get_attachment_page_by_rd.s(rd_pk, session).set(queue=q),
76-
make_attachment_pq_object.s(rd_pk, recap_user.pk).set(queue=q),
76+
save_attachment_pq_object.s(rd_pk, recap_user.pk).set(queue=q),
7777
process_recap_attachment.s(tag_names=tag_names).set(queue=q),
7878
).apply_async()

cl/corpus_importer/tasks.py

+85
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,33 @@ def get_bankr_claims_registry(
19381938
return data
19391939

19401940

1941+
def create_attachment_pq(
1942+
rd_pk: int,
1943+
user_pk: int,
1944+
) -> ProcessingQueue:
1945+
"""Create a ProcessingQueue instance for an attachment.
1946+
1947+
Note that the PQ returned hasn't been persisted in the database.
1948+
It must be saved in a subsequent step.
1949+
1950+
:param rd_pk: The pk of the RECAPDocument.
1951+
:param user_pk: The pk of the User uploading the attachment.
1952+
:return: A ProcessingQueue instance for the attachment upload.
1953+
"""
1954+
1955+
rd = RECAPDocument.objects.get(pk=rd_pk)
1956+
user = User.objects.get(pk=user_pk)
1957+
pq = ProcessingQueue(
1958+
court_id=rd.docket_entry.docket.court_id,
1959+
pacer_doc_id=rd.pacer_doc_id,
1960+
uploader=user,
1961+
upload_type=UPLOAD_TYPE.ATTACHMENT_PAGE,
1962+
pacer_case_id=rd.docket_entry.docket.pacer_case_id,
1963+
)
1964+
return pq
1965+
1966+
1967+
# TODO: Remove after the new related methods have been rolled out.
19411968
@app.task(bind=True, ignore_result=True)
19421969
def make_attachment_pq_object(
19431970
self: Task,
@@ -1975,7 +2002,65 @@ def make_attachment_pq_object(
19752002
pq.filepath_local.save(
19762003
"attachment_page.html", ContentFile(att_report_text.encode())
19772004
)
2005+
return pq.pk
2006+
2007+
2008+
@app.task(bind=True, ignore_result=True)
2009+
def save_attachment_pq_object(
2010+
self: Task,
2011+
attachment_report: AttachmentPage,
2012+
rd_pk: int,
2013+
user_pk: int,
2014+
) -> int:
2015+
"""Create an item in the processing queue for an attachment page.
2016+
2017+
This is a helper shim to convert attachment page results into processing
2018+
queue objects that can be processed by our standard pipeline.
19782019
2020+
:param self: The celery task
2021+
:param attachment_report: An AttachmentPage object that's already queried
2022+
a page and populated its data attribute.
2023+
:param rd_pk: The RECAP document that the attachment page is associated
2024+
with
2025+
:param user_pk: The user to associate with the ProcessingQueue object when
2026+
it's created.
2027+
:return: The pk of the ProcessingQueue object that's created.
2028+
"""
2029+
2030+
pq = create_attachment_pq(
2031+
rd_pk,
2032+
user_pk,
2033+
)
2034+
att_report_text = attachment_report.response.text
2035+
pq.filepath_local.save(
2036+
"attachment_page.html", ContentFile(att_report_text.encode())
2037+
)
2038+
return pq.pk
2039+
2040+
2041+
def save_attachment_pq_from_text(
2042+
rd_pk: int,
2043+
user_pk: int,
2044+
att_report_text: str,
2045+
) -> int:
2046+
"""Create an item in the processing queue for an attachment page from the
2047+
att report text.
2048+
2049+
:param rd_pk: The RECAP document that the attachment page is associated
2050+
with
2051+
:param user_pk: The user to associate with the ProcessingQueue object when
2052+
it's created.
2053+
:param att_report_text: The attachment page report text.
2054+
:return: The pk of the ProcessingQueue object that's created.
2055+
"""
2056+
2057+
pq = create_attachment_pq(
2058+
rd_pk,
2059+
user_pk,
2060+
)
2061+
pq.filepath_local.save(
2062+
"attachment_page.html", ContentFile(att_report_text.encode())
2063+
)
19792064
return pq.pk
19802065

19812066

cl/favorites/tests.py

+29
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
get_prayer_counts_in_bulk,
3030
get_top_prayers,
3131
get_user_prayer_history,
32+
get_user_prayers,
3233
prayer_eligible,
3334
)
3435
from cl.lib.test_helpers import AudioTestCase, SimpleUserDataMixin
@@ -889,6 +890,34 @@ async def test_get_top_prayers_by_number_and_age(self) -> None:
889890
top_prayers[3].geometric_mean, rd_3_score, places=2
890891
)
891892

893+
async def test_get_user_prayers(self) -> None:
894+
"""Does the get_user_prayer method work properly?"""
895+
# Create prayers for user and user_2 to establish test data.
896+
prayer_rd_2 = await create_prayer(self.user, self.rd_2)
897+
await create_prayer(self.user_2, self.rd_2)
898+
await create_prayer(self.user, self.rd_3)
899+
900+
user_prayers = await get_user_prayers(user=self.user)
901+
user_2_prayers = await get_user_prayers(user=self.user_2)
902+
903+
# Verify the correct number of prayers are returned for each user
904+
self.assertEqual(
905+
await user_prayers.acount(), 2, "User 1 should have 2 prayers."
906+
)
907+
self.assertEqual(
908+
await user_2_prayers.acount(), 1, "User 2 should have 1 prayer."
909+
)
910+
911+
# Update the status of one of user's prayers to 'GRANTED'.
912+
prayer_rd_2.status = Prayer.GRANTED
913+
await prayer_rd_2.asave()
914+
915+
# Verify only the 'GRANTED' prayer is returned.
916+
user_granted_prayers = await get_user_prayers(
917+
user=self.user, status=Prayer.GRANTED
918+
)
919+
self.assertEqual(await user_granted_prayers.acount(), 1)
920+
892921
async def test_get_user_prayer_history(self) -> None:
893922
"""Does the get_user_prayer_history method work properly?"""
894923
# # Prayers for user_2

cl/favorites/utils.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,12 @@ async def get_top_prayers() -> QuerySet[RECAPDocument]:
166166
async def get_user_prayers(
167167
user: User, status: str | None = None
168168
) -> QuerySet[RECAPDocument]:
169-
user_prayers = Prayer.objects.filter(user=user)
170-
169+
filters = {"prayers__user": user}
171170
if status is not None:
172-
user_prayers = user_prayers.filter(status=status)
173-
174-
user_prayer_ids = user_prayers.values("recap_document_id")
171+
filters["prayers__status"] = status
175172

176173
documents = (
177-
RECAPDocument.objects.filter(id__in=Subquery(user_prayer_ids))
174+
RECAPDocument.objects.filter(**filters)
178175
.select_related(
179176
"docket_entry",
180177
"docket_entry__docket",

cl/opinion_page/templates/docket_tabs.html

+1-5
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@
5555
src="{% static "js/react/vendor.js" %}"></script>
5656

5757
<script type="text/javascript" src="{% static "js/export-csv.js" %}"></script>
58-
{% flag "pray-and-pay" %}
5958
<script src="{% static "js/pray_and_pay.js" %}"></script>
60-
{% endflag %}
6159
{% endblock %}
6260

6361
{% block nav %}
@@ -88,9 +86,7 @@ <h1 class="bottom inline" data-type="search.Docket" data-id="{{ docket.pk }}">
8886
</h1>
8987
{% include "includes/notes_modal.html" %}
9088
{% include "includes/docket_alerts_modal.html" %}
91-
{% flag "pray-and-pay" %}
92-
{% include "includes/first_prayer_modal.html" %}
93-
{% endflag %}
89+
{% include "includes/first_prayer_modal.html" %}
9490

9591
<h2>{{ docket.court }}</h2>
9692

cl/opinion_page/templates/includes/de_list.html

-2
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,9 @@
171171
target="_blank"
172172
rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %}
173173
</a>
174-
{% flag "pray-and-pay" %}
175174
<div class="prayer-button" data-gap-size="{% if rd.page_count %}small{% else %}large{% endif %}">
176175
{% include "includes/pray_and_pay_htmx/pray_button.html" with prayer_exists=rd.prayer_exists document_id=rd.id count=rd.prayer_count%}
177176
</div>
178-
{% endflag %}
179177
{% endif %}
180178
{% endif %}
181179
{% endif %}

cl/opinion_page/templates/includes/redirect_to_pacer_modal.html

-2
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,9 @@ <h2 class="modal-title">Sorry, this document isn't in the RECAP Archive yet</h2>
3535
rel="nofollow"
3636
target="_blank"><i class="fa fa-dollar"></i>&nbsp;Buy on PACER</a>
3737
</div>
38-
{% flag "pray-and-pay" %}
3938
<div class="prayer-button" data-gap-size="2px">
4039
{% include "includes/pray_and_pay_htmx/pray_button.html" with prayer_exists=rd.prayer_exists document_id=rd.id count=rd.prayer_count regular_size=True%}
4140
</div>
42-
{% endflag %}
4341
</div>
4442
</div>
4543
</div>

cl/opinion_page/templates/recap_document.html

+2-8
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@
3636
{% else %}
3737
<script src="{% static "js/htmx.min.js" %}"></script>
3838
{% endif %}
39-
{% flag "pray-and-pay" %}
40-
<script src="{% static "js/pray_and_pay.js" %}"></script>
41-
{% endflag %}
39+
<script src="{% static "js/pray_and_pay.js" %}"></script>
4240
{% endblock %}
4341

4442
{% block sidebar %}
@@ -86,9 +84,7 @@ <h2 class="inline"><a
8684
{% if redirect_to_pacer_modal %}
8785
{% include "includes/redirect_to_pacer_modal.html" %}
8886
{% endif %}
89-
{% flag "pray-and-pay" %}
90-
{% include "includes/first_prayer_modal.html" %}
91-
{% endflag %}
87+
{% include "includes/first_prayer_modal.html" %}
9288
{% include "includes/rd_metadata_headers.html" %}
9389
<br>
9490

@@ -202,11 +198,9 @@ <h4>Description</h4>
202198
<a href="https://free.law/recap/"
203199
class="btn btn-success btn-sm recap_install_plea">Install RECAP</a>
204200
{% endif %}
205-
{% flag "pray-and-pay" %}
206201
<div class="prayer-button">
207202
{% include "includes/pray_and_pay_htmx/pray_button.html" with prayer_exists=rd.prayer_exists document_id=rd.id count=rd.prayer_count regular_size=True%}
208203
</div>
209-
{% endflag %}
210204
</div>
211205
</div>
212206
{% endif %}

0 commit comments

Comments
 (0)