From 43d37e37d76e3e0fed06f941d848118ccc84eb40 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 11:11:16 -0400
Subject: [PATCH 01/74] beginning work on API
---
cl/favorites/api_serializers.py | 2 +-
cl/favorites/api_views.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/cl/favorites/api_serializers.py b/cl/favorites/api_serializers.py
index 7f0ed014df..85b7cb506c 100644
--- a/cl/favorites/api_serializers.py
+++ b/cl/favorites/api_serializers.py
@@ -2,7 +2,7 @@
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
-from cl.favorites.models import DocketTag, UserTag
+from cl.favorites.models import DocketTag, Prayer, UserTag
from cl.search.models import Docket
diff --git a/cl/favorites/api_views.py b/cl/favorites/api_views.py
index f53d5c4fb1..c201d77a2d 100644
--- a/cl/favorites/api_views.py
+++ b/cl/favorites/api_views.py
@@ -7,7 +7,7 @@
from cl.favorites.api_permissions import IsTagOwner
from cl.favorites.api_serializers import DocketTagSerializer, UserTagSerializer
from cl.favorites.filters import DocketTagFilter, UserTagFilter
-from cl.favorites.models import DocketTag, UserTag
+from cl.favorites.models import DocketTag, Prayer, UserTag
class UserTagViewSet(ModelViewSet):
From 6677f72b5d528e2626e3210104bc5d8ecdecf9fa Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 11:25:02 -0400
Subject: [PATCH 02/74] PrayerSerializer
---
cl/favorites/api_serializers.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/cl/favorites/api_serializers.py b/cl/favorites/api_serializers.py
index 85b7cb506c..dd2cb6765b 100644
--- a/cl/favorites/api_serializers.py
+++ b/cl/favorites/api_serializers.py
@@ -37,3 +37,17 @@ class DocketTagSerializer(DynamicFieldsMixin, ModelSerializer):
class Meta:
model = DocketTag
fields = "__all__"
+
+class PrayerSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
+ user = serializers.HiddenField(default=serializers.CurrentUserDefault())
+
+ class Meta:
+ model = Prayer
+ fields = "__all__"
+ read_only_fields = (
+ "date_created",
+ "user",
+ "recap_document",
+ "status",
+ )
+
From 611b1379d3fc6804e395e0a285edfb04c42b04a4 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 1 Oct 2024 15:25:43 +0000
Subject: [PATCH 03/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/api_serializers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cl/favorites/api_serializers.py b/cl/favorites/api_serializers.py
index dd2cb6765b..b05681bc23 100644
--- a/cl/favorites/api_serializers.py
+++ b/cl/favorites/api_serializers.py
@@ -38,6 +38,7 @@ class Meta:
model = DocketTag
fields = "__all__"
+
class PrayerSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
@@ -50,4 +51,3 @@ class Meta:
"recap_document",
"status",
)
-
From 18498f63050a288253b53c045adb6db8171ffa6c Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 11:50:46 -0400
Subject: [PATCH 04/74] filters
---
cl/favorites/filters.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/cl/favorites/filters.py b/cl/favorites/filters.py
index e0e2e0e724..0a104c458d 100644
--- a/cl/favorites/filters.py
+++ b/cl/favorites/filters.py
@@ -1,7 +1,7 @@
import rest_framework_filters as filters
from cl.api.utils import BASIC_TEXT_LOOKUPS, BOOLEAN_LOOKUPS, NoEmptyFilterSet
-from cl.favorites.models import DocketTag, UserTag
+from cl.favorites.models import DocketTag, Prayer, UserTag
class UserTagFilter(NoEmptyFilterSet):
@@ -21,3 +21,12 @@ class DocketTagFilter(NoEmptyFilterSet):
class Meta:
model = DocketTag
fields = {"id": ["exact"], "docket": ["exact"]}
+
+class PrayerFilter(NoEmptyFilterSet):
+ date_created = filters.DateFromToRangeFilter(
+ field_name="date_created",
+ help_text="Filter prayers by a date range (e.g., ?date_created_after=2024-09-01&date_created_before=2024-12-31)."
+)
+ class Meta:
+ model = Prayer
+ fields = {"date_created": ["exact", "range"], "user": ["exact"], "recap_document": ["exact"], "status": ["exact", "in"]}
\ No newline at end of file
From 114bbf93ad4c01d090c97a7e251a60391671565e Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 1 Oct 2024 15:51:53 +0000
Subject: [PATCH 05/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/filters.py | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/cl/favorites/filters.py b/cl/favorites/filters.py
index 0a104c458d..cbd3c24a1f 100644
--- a/cl/favorites/filters.py
+++ b/cl/favorites/filters.py
@@ -22,11 +22,18 @@ class Meta:
model = DocketTag
fields = {"id": ["exact"], "docket": ["exact"]}
+
class PrayerFilter(NoEmptyFilterSet):
date_created = filters.DateFromToRangeFilter(
- field_name="date_created",
- help_text="Filter prayers by a date range (e.g., ?date_created_after=2024-09-01&date_created_before=2024-12-31)."
-)
+ field_name="date_created",
+ help_text="Filter prayers by a date range (e.g., ?date_created_after=2024-09-01&date_created_before=2024-12-31).",
+ )
+
class Meta:
model = Prayer
- fields = {"date_created": ["exact", "range"], "user": ["exact"], "recap_document": ["exact"], "status": ["exact", "in"]}
\ No newline at end of file
+ fields = {
+ "date_created": ["exact", "range"],
+ "user": ["exact"],
+ "recap_document": ["exact"],
+ "status": ["exact", "in"],
+ }
From ea76f6c078919329089c425fc3d65b57ad6d64c4 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 11:53:04 -0400
Subject: [PATCH 06/74] views
---
cl/favorites/api_views.py | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/cl/favorites/api_views.py b/cl/favorites/api_views.py
index c201d77a2d..b04f1824fb 100644
--- a/cl/favorites/api_views.py
+++ b/cl/favorites/api_views.py
@@ -4,9 +4,10 @@
from rest_framework.viewsets import ModelViewSet
from cl.api.pagination import MediumAdjustablePagination
+from cl.api.utils import LoggingMixin
from cl.favorites.api_permissions import IsTagOwner
-from cl.favorites.api_serializers import DocketTagSerializer, UserTagSerializer
-from cl.favorites.filters import DocketTagFilter, UserTagFilter
+from cl.favorites.api_serializers import DocketTagSerializer, PrayerSerializer, UserTagSerializer
+from cl.favorites.filters import DocketTagFilter, PrayerFilter, UserTagFilter
from cl.favorites.models import DocketTag, Prayer, UserTag
@@ -51,3 +52,26 @@ def get_queryset(self):
return DocketTag.objects.filter(
Q(tag__user=self.request.user) | Q(tag__published=True)
)
+
+class PrayerViewSet(LoggingMixin, ModelViewSet):
+ """A ModelViewset to handle CRUD operations for Prayer."""
+
+ permission_classes = [IsAuthenticated]
+ serializer_class = PrayerSerializer
+ pagination_class = MediumAdjustablePagination
+ filterset_class = PrayerFilter
+ ordering_fields = (
+ "date_created",
+ )
+ # Default cursor ordering key
+ ordering = "-date_created"
+ # Additional cursor ordering fields
+ cursor_ordering_fields = ["date_created"]
+
+ def get_queryset(self):
+ """
+ Return a list of all the open prayers
+ for the currently authenticated user.
+ """
+ user = self.request.user
+ return Prayer.objects.filter(user=user, status=Prayer.WAITING).order_by("-date_created")
From 2707ebd046c4a6d1a6a6a14b471862ca3d3cc953 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 1 Oct 2024 15:54:12 +0000
Subject: [PATCH 07/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/api_views.py | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/cl/favorites/api_views.py b/cl/favorites/api_views.py
index b04f1824fb..36cc655f3b 100644
--- a/cl/favorites/api_views.py
+++ b/cl/favorites/api_views.py
@@ -6,7 +6,11 @@
from cl.api.pagination import MediumAdjustablePagination
from cl.api.utils import LoggingMixin
from cl.favorites.api_permissions import IsTagOwner
-from cl.favorites.api_serializers import DocketTagSerializer, PrayerSerializer, UserTagSerializer
+from cl.favorites.api_serializers import (
+ DocketTagSerializer,
+ PrayerSerializer,
+ UserTagSerializer,
+)
from cl.favorites.filters import DocketTagFilter, PrayerFilter, UserTagFilter
from cl.favorites.models import DocketTag, Prayer, UserTag
@@ -53,6 +57,7 @@ def get_queryset(self):
Q(tag__user=self.request.user) | Q(tag__published=True)
)
+
class PrayerViewSet(LoggingMixin, ModelViewSet):
"""A ModelViewset to handle CRUD operations for Prayer."""
@@ -60,9 +65,7 @@ class PrayerViewSet(LoggingMixin, ModelViewSet):
serializer_class = PrayerSerializer
pagination_class = MediumAdjustablePagination
filterset_class = PrayerFilter
- ordering_fields = (
- "date_created",
- )
+ ordering_fields = ("date_created",)
# Default cursor ordering key
ordering = "-date_created"
# Additional cursor ordering fields
@@ -74,4 +77,6 @@ def get_queryset(self):
for the currently authenticated user.
"""
user = self.request.user
- return Prayer.objects.filter(user=user, status=Prayer.WAITING).order_by("-date_created")
+ return Prayer.objects.filter(
+ user=user, status=Prayer.WAITING
+ ).order_by("-date_created")
From 4586a36c25df77edc8b3662825efe19d30b7a0ca Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 12:07:28 -0400
Subject: [PATCH 08/74] fixing email test (single-digit dates don't have zero
padding in the email).
---
cl/favorites/tests.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cl/favorites/tests.py b/cl/favorites/tests.py
index 8ece116a5a..cd8ae0bf8d 100644
--- a/cl/favorites/tests.py
+++ b/cl/favorites/tests.py
@@ -924,7 +924,7 @@ async def test_prayers_integration(self) -> None:
email_text_content,
)
self.assertIn(
- f"You requested it on {prayer_1.date_created.strftime("%b %d, %Y")}",
+ f"You requested it on {prayer_1.date_created.strftime("%b %-d, %Y")}",
email_text_content,
)
self.assertIn(
@@ -945,7 +945,7 @@ async def test_prayers_integration(self) -> None:
html_content,
)
self.assertIn(
- f"You requested it on {prayer_1.date_created.strftime("%b %d, %Y")}",
+ f"You requested it on {prayer_1.date_created.strftime("%b %-d, %Y")}",
html_content,
)
self.assertIn(
From c687c40126f2ac2a6fb8e66f85683a2ee8940f86 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 1 Oct 2024 18:20:44 +0000
Subject: [PATCH 09/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/tests.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cl/favorites/tests.py b/cl/favorites/tests.py
index a2c6160528..9af49eb0c2 100644
--- a/cl/favorites/tests.py
+++ b/cl/favorites/tests.py
@@ -947,7 +947,7 @@ async def test_prayers_integration(self) -> None:
)
self.assertIn(
f"You requested it on {template_date(prayer_1.date_created, 'M j, Y')}",
- html_content,
+ html_content,
)
self.assertIn(
f"Somebody paid ${price(rd_6)}",
From a31bcceca64d7712567f8ade5a088ac8ad0deb4a Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 14:37:50 -0400
Subject: [PATCH 10/74] route
---
cl/api/urls.py | 3 +++
cl/favorites/api_permissions.py | 1 +
2 files changed, 4 insertions(+)
diff --git a/cl/api/urls.py b/cl/api/urls.py
index cf600790d9..85c4cd7691 100644
--- a/cl/api/urls.py
+++ b/cl/api/urls.py
@@ -96,6 +96,9 @@
r"docket-tags", favorite_views.DocketTagViewSet, basename="DocketTag"
)
+# Prayers
+router.register(r"prayers", favorite_views.PrayerViewSet, basename="Prayer")
+
# Visualizations
router.register(
r"visualizations/json", viz_views.JSONViewSet, basename="jsonversion"
diff --git a/cl/favorites/api_permissions.py b/cl/favorites/api_permissions.py
index 168b2fa6ce..d14fccb7b8 100644
--- a/cl/favorites/api_permissions.py
+++ b/cl/favorites/api_permissions.py
@@ -10,3 +10,4 @@ def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.tag.user == request.user
+
From ad42a89048d8ae9942baaf625ba71c7606d98bd4 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 1 Oct 2024 18:38:39 +0000
Subject: [PATCH 11/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/api_permissions.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/cl/favorites/api_permissions.py b/cl/favorites/api_permissions.py
index d14fccb7b8..168b2fa6ce 100644
--- a/cl/favorites/api_permissions.py
+++ b/cl/favorites/api_permissions.py
@@ -10,4 +10,3 @@ def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.tag.user == request.user
-
From f32cfd518ce692665b5437e418e919e2542add8c Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 1 Oct 2024 18:52:52 -0400
Subject: [PATCH 12/74] adding link to open document requests to base.html
---
cl/assets/templates/base.html | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/cl/assets/templates/base.html b/cl/assets/templates/base.html
index 33181f52e1..4a8f240880 100644
--- a/cl/assets/templates/base.html
+++ b/cl/assets/templates/base.html
@@ -231,17 +231,20 @@
You did not supply the "private" variable to your template.
Install RECAP
+ {% comment %}
+ Pray and Pay Project
+ {% endcomment %}
- Get Case Alerts
+ Get Case Alerts
- About this Collection
+ About this Collection
- Bulk Data Service
+ Bulk Data Service
- API
+ API
From b2f276ba25dc365ea4c559fc7f5eb869281295e3 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Thu, 3 Oct 2024 16:27:31 -0400
Subject: [PATCH 13/74] function to get how many open requests for a given
document
---
cl/favorites/utils.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index dae437abad..2f873140d1 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -148,3 +148,8 @@ def send_prayer_emails(instance: RECAPDocument) -> None:
messages.append(msg)
connection = get_connection()
connection.send_messages(messages)
+
+async def get_prayer_count(
+ recap_document: RECAPDocument
+) -> int:
+ return await Prayer.objects.filter(recap_document=recap_document, status=Prayer.WAITING).acount()
\ No newline at end of file
From 0fb956e0747cdfc48870799eaba91bd6a9821ea8 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:28:10 +0000
Subject: [PATCH 14/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/utils.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index 2f873140d1..b5b7d68cf9 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -149,7 +149,8 @@ def send_prayer_emails(instance: RECAPDocument) -> None:
connection = get_connection()
connection.send_messages(messages)
-async def get_prayer_count(
- recap_document: RECAPDocument
-) -> int:
- return await Prayer.objects.filter(recap_document=recap_document, status=Prayer.WAITING).acount()
\ No newline at end of file
+
+async def get_prayer_count(recap_document: RECAPDocument) -> int:
+ return await Prayer.objects.filter(
+ recap_document=recap_document, status=Prayer.WAITING
+ ).acount()
From 8bba545ad1a8a3b5d2dbdf8bf48be67f5cec1a31 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Thu, 3 Oct 2024 16:55:14 -0400
Subject: [PATCH 15/74] function to check if user can request a given document
---
cl/favorites/utils.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index b5b7d68cf9..b1d83b6b96 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -154,3 +154,7 @@ async def get_prayer_count(recap_document: RECAPDocument) -> int:
return await Prayer.objects.filter(
recap_document=recap_document, status=Prayer.WAITING
).acount()
+
+
+async def prayer_exists(user: User, recap_document: RECAPDocument) -> bool:
+ return await Prayer.objects.filter(user=user, recap_document=recap_document).aexists()
\ No newline at end of file
From d676edef885680b474c36061e29662054bd05341 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:56:20 +0000
Subject: [PATCH 16/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/utils.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index b1d83b6b96..30450dd3ca 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -157,4 +157,6 @@ async def get_prayer_count(recap_document: RECAPDocument) -> int:
async def prayer_exists(user: User, recap_document: RECAPDocument) -> bool:
- return await Prayer.objects.filter(user=user, recap_document=recap_document).aexists()
\ No newline at end of file
+ return await Prayer.objects.filter(
+ user=user, recap_document=recap_document
+ ).aexists()
From 20f1ec60de9d1ce81e883a7e1b690d2d1313e271 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Fri, 4 Oct 2024 11:26:32 -0400
Subject: [PATCH 17/74] showing how many open prayers on docket entry page
---
cl/opinion_page/views.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py
index c96cc3af85..659bd210bc 100644
--- a/cl/opinion_page/views.py
+++ b/cl/opinion_page/views.py
@@ -44,6 +44,7 @@
from cl.custom_filters.templatetags.text_filters import best_case_name
from cl.favorites.forms import NoteForm
from cl.favorites.models import Note
+from cl.favorites.utils import get_prayer_count
from cl.lib.auth import group_required
from cl.lib.bot_detector import is_og_bot
from cl.lib.http import is_ajax
@@ -377,6 +378,12 @@ async def view_docket(
"-recap_sequence_number", "-entry_number"
)
+ for entry in await sync_to_async(list)(de_list):
+ if await sync_to_async(entry.recap_documents.count)() > 0:
+ for rd in await sync_to_async(list)(entry.recap_documents.all()):
+ if rd.pacer_url and not(rd.is_free_on_pacer or rd.is_sealed):
+ rd.prayer_count = await get_prayer_count(rd)
+
page = request.GET.get("page", 1)
@sync_to_async
From 1b1975cf20718095b2be2f503ab0109982c8a26a Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Fri, 4 Oct 2024 11:27:53 -0400
Subject: [PATCH 18/74] adding prayer count to docket entry
---
cl/opinion_page/views.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py
index 82c1c60efc..5b8e6f61d1 100644
--- a/cl/opinion_page/views.py
+++ b/cl/opinion_page/views.py
@@ -384,6 +384,7 @@ async def view_docket(
for rd in await sync_to_async(list)(entry.recap_documents.all()):
if rd.pacer_url and not(rd.is_free_on_pacer or rd.is_sealed):
rd.prayer_count = await get_prayer_count(rd)
+
page = request.GET.get("page", 1)
From 027edbf542fda8acdcaf25bb1f3dad375b2b2e0f Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Fri, 4 Oct 2024 15:28:16 +0000
Subject: [PATCH 19/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/opinion_page/views.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py
index 5b8e6f61d1..f6dcb4a5c0 100644
--- a/cl/opinion_page/views.py
+++ b/cl/opinion_page/views.py
@@ -382,9 +382,8 @@ async def view_docket(
for entry in await sync_to_async(list)(de_list):
if await sync_to_async(entry.recap_documents.count)() > 0:
for rd in await sync_to_async(list)(entry.recap_documents.all()):
- if rd.pacer_url and not(rd.is_free_on_pacer or rd.is_sealed):
+ if rd.pacer_url and not (rd.is_free_on_pacer or rd.is_sealed):
rd.prayer_count = await get_prayer_count(rd)
-
page = request.GET.get("page", 1)
From 7920547989650160df6dbcfc9fb93eec274c6e8c Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Fri, 4 Oct 2024 11:40:30 -0400
Subject: [PATCH 20/74] url
---
cl/favorites/urls.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index 65ef65544d..ca211d8cd7 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -1,6 +1,7 @@
from django.urls import path
from cl.favorites.views import (
+ create_prayer_view,
delete_note,
open_prayers,
save_or_update_note,
@@ -24,4 +25,5 @@
),
path("tags//", view_tags, name="tag_list"),
path("prayers/top/", open_prayers, name="top_prayers"),
+ path("prayer/create/", create_prayer_view, name="create_prayer")
]
From 725b3e910cc002dd0bf23a952403f1f34d1cf27d Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Fri, 4 Oct 2024 15:41:30 +0000
Subject: [PATCH 21/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/urls.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index ca211d8cd7..be24a17cca 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -25,5 +25,5 @@
),
path("tags//", view_tags, name="tag_list"),
path("prayers/top/", open_prayers, name="top_prayers"),
- path("prayer/create/", create_prayer_view, name="create_prayer")
+ path("prayer/create/", create_prayer_view, name="create_prayer"),
]
From d40f02672b61cd56cff399a1d1a17f3ab6b54ae0 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Fri, 4 Oct 2024 14:15:35 -0400
Subject: [PATCH 22/74] rough work on html
---
cl/favorites/views.py | 15 +++++++++++++++
cl/opinion_page/templates/includes/de_list.html | 4 ++++
2 files changed, 19 insertions(+)
diff --git a/cl/favorites/views.py b/cl/favorites/views.py
index 1cd5b8ba15..b1d7fe0b8d 100644
--- a/cl/favorites/views.py
+++ b/cl/favorites/views.py
@@ -14,9 +14,13 @@
from django.shortcuts import aget_object_or_404
from django.template.response import TemplateResponse
from django.utils.datastructures import MultiValueDictKeyError
+from django.http import HttpResponseRedirect
+from django.urls import reverse
from cl.favorites.forms import NoteForm
from cl.favorites.models import DocketTag, Note, UserTag
+from cl.favorites.utils import create_prayer
+from cl.search.models import RECAPDocument
from cl.favorites.utils import get_top_prayers
from cl.lib.decorators import cache_page_ignore_params
from cl.lib.http import is_ajax
@@ -190,3 +194,14 @@ async def open_prayers(request: HttpRequest) -> HttpResponse:
"private": True, # temporary to prevent Google indexing
},
)
+
+# this is a rough function just to assess the test cases. It needs a lot of work before it's ready for showtime.
+@login_required
+async def create_prayer_view(request: HttpRequest, recap_document: RECAPDocument) -> HttpResponse:
+ user = request.user
+
+ # Call the create_prayer async function
+ new_prayer = await create_prayer(user, recap_document)
+
+ # Redirect back to the referring page after creating the prayer
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('view_docket')))
\ No newline at end of file
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index 0c0776ef9f..6b10dab69f 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -171,6 +171,10 @@
target="_blank"
rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %}
+
+ {{rd.prayer_count}} 🙏
+
{% endif %}
{% endif %}
{% endif %}
From 703d6e76d2b37d39346ff625f35c847cde7cebe5 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Fri, 4 Oct 2024 18:18:31 +0000
Subject: [PATCH 23/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/views.py | 22 +++++++++++--------
.../templates/includes/de_list.html | 2 +-
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/cl/favorites/views.py b/cl/favorites/views.py
index b1d7fe0b8d..646cf55bb7 100644
--- a/cl/favorites/views.py
+++ b/cl/favorites/views.py
@@ -9,22 +9,21 @@
HttpRequest,
HttpResponse,
HttpResponseNotAllowed,
+ HttpResponseRedirect,
HttpResponseServerError,
)
from django.shortcuts import aget_object_or_404
from django.template.response import TemplateResponse
-from django.utils.datastructures import MultiValueDictKeyError
-from django.http import HttpResponseRedirect
from django.urls import reverse
+from django.utils.datastructures import MultiValueDictKeyError
from cl.favorites.forms import NoteForm
from cl.favorites.models import DocketTag, Note, UserTag
-from cl.favorites.utils import create_prayer
-from cl.search.models import RECAPDocument
-from cl.favorites.utils import get_top_prayers
+from cl.favorites.utils import create_prayer, get_top_prayers
from cl.lib.decorators import cache_page_ignore_params
from cl.lib.http import is_ajax
from cl.lib.view_utils import increment_view_count
+from cl.search.models import RECAPDocument
async def get_note(request: HttpRequest) -> HttpResponse:
@@ -195,13 +194,18 @@ async def open_prayers(request: HttpRequest) -> HttpResponse:
},
)
+
# this is a rough function just to assess the test cases. It needs a lot of work before it's ready for showtime.
@login_required
-async def create_prayer_view(request: HttpRequest, recap_document: RECAPDocument) -> HttpResponse:
+async def create_prayer_view(
+ request: HttpRequest, recap_document: RECAPDocument
+) -> HttpResponse:
user = request.user
-
+
# Call the create_prayer async function
new_prayer = await create_prayer(user, recap_document)
-
+
# Redirect back to the referring page after creating the prayer
- return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('view_docket')))
\ No newline at end of file
+ return HttpResponseRedirect(
+ request.META.get("HTTP_REFERER", reverse("view_docket"))
+ )
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index 6b10dab69f..a72cb90907 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -171,7 +171,7 @@
target="_blank"
rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %}
-
{{rd.prayer_count}} 🙏
From 3a32ebcf0c26fa1fbf22707e8317a936fe9ac89d Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Sun, 6 Oct 2024 17:13:44 -0400
Subject: [PATCH 24/74] grouping similar functions together
---
cl/favorites/utils.py | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index 30450dd3ca..a59974db12 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -35,6 +35,18 @@ async def prayer_eligible(user: User) -> bool:
return prayer_count < allowed_prayer_count
+async def get_prayer_count(recap_document: RECAPDocument) -> int:
+ return await Prayer.objects.filter(
+ recap_document=recap_document, status=Prayer.WAITING
+ ).acount()
+
+
+async def prayer_exists(user: User, recap_document: RECAPDocument) -> bool:
+ return await Prayer.objects.filter(
+ user=user, recap_document=recap_document
+ ).aexists()
+
+
async def create_prayer(
user: User, recap_document: RECAPDocument
) -> Prayer | None:
@@ -148,15 +160,3 @@ def send_prayer_emails(instance: RECAPDocument) -> None:
messages.append(msg)
connection = get_connection()
connection.send_messages(messages)
-
-
-async def get_prayer_count(recap_document: RECAPDocument) -> int:
- return await Prayer.objects.filter(
- recap_document=recap_document, status=Prayer.WAITING
- ).acount()
-
-
-async def prayer_exists(user: User, recap_document: RECAPDocument) -> bool:
- return await Prayer.objects.filter(
- user=user, recap_document=recap_document
- ).aexists()
From c1e7b9f40c8d532d7379f0b7f35cc7277ed4cb73 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Sun, 6 Oct 2024 17:15:17 -0400
Subject: [PATCH 25/74] commenting out problematic function
---
cl/favorites/views.py | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/cl/favorites/views.py b/cl/favorites/views.py
index 646cf55bb7..cc92d97aa0 100644
--- a/cl/favorites/views.py
+++ b/cl/favorites/views.py
@@ -195,17 +195,17 @@ async def open_prayers(request: HttpRequest) -> HttpResponse:
)
-# this is a rough function just to assess the test cases. It needs a lot of work before it's ready for showtime.
-@login_required
-async def create_prayer_view(
- request: HttpRequest, recap_document: RECAPDocument
-) -> HttpResponse:
- user = request.user
-
- # Call the create_prayer async function
- new_prayer = await create_prayer(user, recap_document)
-
- # Redirect back to the referring page after creating the prayer
- return HttpResponseRedirect(
- request.META.get("HTTP_REFERER", reverse("view_docket"))
- )
+# # this is a rough function just to assess the test cases. It needs a lot of work before it's ready for showtime.
+# @login_required
+# async def create_prayer_view(
+# request: HttpRequest, recap_document: RECAPDocument
+# ) -> HttpResponse:
+# user = request.user
+
+# # Call the create_prayer async function
+# new_prayer = await create_prayer(user, recap_document)
+
+# # Redirect back to the referring page after creating the prayer
+# return HttpResponseRedirect(
+# request.META.get("HTTP_REFERER", reverse("view_docket"))
+# )
From 98b0ac2ba4170c3d7a74a7da1a7da85477478abe Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Sun, 6 Oct 2024 17:21:41 -0400
Subject: [PATCH 26/74] comment out dead url path
---
cl/favorites/urls.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index be24a17cca..ca931d9a9a 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -25,5 +25,5 @@
),
path("tags//", view_tags, name="tag_list"),
path("prayers/top/", open_prayers, name="top_prayers"),
- path("prayer/create/", create_prayer_view, name="create_prayer"),
+ # path("prayer/create/", create_prayer_view, name="create_prayer"),
]
From 2aabc991e4143270f78758e68037439dc692de14 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Sun, 6 Oct 2024 17:27:03 -0400
Subject: [PATCH 27/74] fix
---
cl/favorites/urls.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index ca931d9a9a..1238b43abc 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -1,7 +1,7 @@
from django.urls import path
from cl.favorites.views import (
- create_prayer_view,
+ # create_prayer_view,
delete_note,
open_prayers,
save_or_update_note,
From 4291b1b2c83371370eaf768ed02d8cc6468ab999 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Sun, 6 Oct 2024 21:27:43 +0000
Subject: [PATCH 28/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/urls.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index 1238b43abc..6196727103 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -1,7 +1,6 @@
from django.urls import path
-from cl.favorites.views import (
- # create_prayer_view,
+from cl.favorites.views import ( # create_prayer_view,
delete_note,
open_prayers,
save_or_update_note,
From e96d1462000fc44bd586df3b573ee6f19c4da5ad Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 8 Oct 2024 11:29:44 -0400
Subject: [PATCH 29/74] grouping common functions together
---
cl/favorites/utils.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index a59974db12..2ba8914590 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -35,18 +35,18 @@ async def prayer_eligible(user: User) -> bool:
return prayer_count < allowed_prayer_count
-async def get_prayer_count(recap_document: RECAPDocument) -> int:
- return await Prayer.objects.filter(
- recap_document=recap_document, status=Prayer.WAITING
- ).acount()
-
-
async def prayer_exists(user: User, recap_document: RECAPDocument) -> bool:
return await Prayer.objects.filter(
user=user, recap_document=recap_document
).aexists()
+async def get_prayer_count(recap_document: RECAPDocument) -> int:
+ return await Prayer.objects.filter(
+ recap_document=recap_document, status=Prayer.WAITING
+ ).acount()
+
+
async def create_prayer(
user: User, recap_document: RECAPDocument
) -> Prayer | None:
From 479aef5ec54cd47249acc7f95d4f3aa0a7be7e6a Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 8 Oct 2024 11:32:14 -0400
Subject: [PATCH 30/74] adding checks for whether user can request a particular
document
---
cl/opinion_page/views.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py
index f6dcb4a5c0..b6dbcb2ddb 100644
--- a/cl/opinion_page/views.py
+++ b/cl/opinion_page/views.py
@@ -44,7 +44,7 @@
from cl.custom_filters.templatetags.text_filters import best_case_name
from cl.favorites.forms import NoteForm
from cl.favorites.models import Note
-from cl.favorites.utils import get_prayer_count
+from cl.favorites.utils import get_prayer_count, prayer_eligible, prayer_exists
from cl.lib.auth import group_required
from cl.lib.bot_detector import is_og_bot
from cl.lib.decorators import cache_page_ignore_params
@@ -385,6 +385,10 @@ async def view_docket(
if rd.pacer_url and not (rd.is_free_on_pacer or rd.is_sealed):
rd.prayer_count = await get_prayer_count(rd)
+ if request.user.is_authenticated:
+ rd.prayer_exists = await prayer_exists(request.user, rd)
+ rd.prayer_eligible = await prayer_eligible(request.user)
+
page = request.GET.get("page", 1)
@sync_to_async
From 842389298628dabf08c950e2ed11a43a08e2e38e Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 8 Oct 2024 15:32:58 +0000
Subject: [PATCH 31/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/opinion_page/views.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py
index b6dbcb2ddb..4828468232 100644
--- a/cl/opinion_page/views.py
+++ b/cl/opinion_page/views.py
@@ -386,8 +386,12 @@ async def view_docket(
rd.prayer_count = await get_prayer_count(rd)
if request.user.is_authenticated:
- rd.prayer_exists = await prayer_exists(request.user, rd)
- rd.prayer_eligible = await prayer_eligible(request.user)
+ rd.prayer_exists = await prayer_exists(
+ request.user, rd
+ )
+ rd.prayer_eligible = await prayer_eligible(
+ request.user
+ )
page = request.GET.get("page", 1)
From 120ebad35db59dc5017f7c3983540647e634a0fe Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 8 Oct 2024 12:06:11 -0400
Subject: [PATCH 32/74] this all seems to work. I'm not 100% happy with how
it's written, but it is functional.
---
cl/favorites/urls.py | 5 ++--
cl/favorites/views.py | 24 +++++++++----------
.../templates/includes/de_list.html | 24 +++++++++++++++----
3 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index 6196727103..04160578ed 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -1,6 +1,7 @@
from django.urls import path
-from cl.favorites.views import ( # create_prayer_view,
+from cl.favorites.views import (
+ create_prayer_view,
delete_note,
open_prayers,
save_or_update_note,
@@ -24,5 +25,5 @@
),
path("tags//", view_tags, name="tag_list"),
path("prayers/top/", open_prayers, name="top_prayers"),
- # path("prayer/create/", create_prayer_view, name="create_prayer"),
+ path("prayer/create//", create_prayer_view, name="create_prayer"),
]
diff --git a/cl/favorites/views.py b/cl/favorites/views.py
index cc92d97aa0..113b9bd910 100644
--- a/cl/favorites/views.py
+++ b/cl/favorites/views.py
@@ -196,16 +196,14 @@ async def open_prayers(request: HttpRequest) -> HttpResponse:
# # this is a rough function just to assess the test cases. It needs a lot of work before it's ready for showtime.
-# @login_required
-# async def create_prayer_view(
-# request: HttpRequest, recap_document: RECAPDocument
-# ) -> HttpResponse:
-# user = request.user
-
-# # Call the create_prayer async function
-# new_prayer = await create_prayer(user, recap_document)
-
-# # Redirect back to the referring page after creating the prayer
-# return HttpResponseRedirect(
-# request.META.get("HTTP_REFERER", reverse("view_docket"))
-# )
+@login_required
+async def create_prayer_view(
+ request: HttpRequest, recap_document: int
+) -> HttpResponse:
+ user = request.user
+ recap_document = await RECAPDocument.objects.aget(id=recap_document)
+
+ # Call the create_prayer async function
+ new_prayer = await create_prayer(user, recap_document)
+
+ return HttpResponse("It worked.")
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index a72cb90907..f9719fa46d 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -171,10 +171,26 @@
target="_blank"
rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %}
-
- {{rd.prayer_count}} 🙏
-
+ {% if request.user.is_authenticated %}
+
+ {{rd.prayer_count}} 🙏
+
+ {% else %}
+
+ {{rd.prayer_count}} 🙏
+
+ {% endif %}
{% endif %}
{% endif %}
{% endif %}
From a0c95116c318719eb31b9c151f2c4a5a75d45b8a Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Tue, 8 Oct 2024 16:06:51 +0000
Subject: [PATCH 33/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/urls.py | 6 +++++-
cl/favorites/views.py | 2 +-
cl/opinion_page/templates/includes/de_list.html | 2 +-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/cl/favorites/urls.py b/cl/favorites/urls.py
index 04160578ed..27547bcd32 100644
--- a/cl/favorites/urls.py
+++ b/cl/favorites/urls.py
@@ -25,5 +25,9 @@
),
path("tags//", view_tags, name="tag_list"),
path("prayers/top/", open_prayers, name="top_prayers"),
- path("prayer/create//", create_prayer_view, name="create_prayer"),
+ path(
+ "prayer/create//",
+ create_prayer_view,
+ name="create_prayer",
+ ),
]
diff --git a/cl/favorites/views.py b/cl/favorites/views.py
index 113b9bd910..337d8a31b1 100644
--- a/cl/favorites/views.py
+++ b/cl/favorites/views.py
@@ -201,7 +201,7 @@ async def create_prayer_view(
request: HttpRequest, recap_document: int
) -> HttpResponse:
user = request.user
- recap_document = await RECAPDocument.objects.aget(id=recap_document)
+ recap_document = await RECAPDocument.objects.aget(id=recap_document)
# Call the create_prayer async function
new_prayer = await create_prayer(user, recap_document)
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index f9719fa46d..4c97d9d509 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -172,7 +172,7 @@
rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %}
{% if request.user.is_authenticated %}
-
Date: Tue, 8 Oct 2024 12:17:05 -0400
Subject: [PATCH 34/74] Update .env.example
adding new variable for CL API key
---
.env.example | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.env.example b/.env.example
index 7d111c1b3f..25cd8994a9 100644
--- a/.env.example
+++ b/.env.example
@@ -42,3 +42,6 @@ IA_ACCESS_KEY=""
IA_SECRET_KEY=""
FTM_KEY=""
+
+# CL API key for cloning data
+CL_API_KEY=""
From 2e2840dbe1417110bc885b39fc4dd913b342ce46 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Tue, 8 Oct 2024 16:06:05 -0400
Subject: [PATCH 35/74] adding document cost to wishlist
---
cl/favorites/templates/top_prayers.html | 12 +++++++++++-
cl/favorites/utils.py | 2 ++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/cl/favorites/templates/top_prayers.html b/cl/favorites/templates/top_prayers.html
index a12a5edba3..9afe9dafce 100644
--- a/cl/favorites/templates/top_prayers.html
+++ b/cl/favorites/templates/top_prayers.html
@@ -2,7 +2,7 @@
{% load extras %}
{% load text_filters %}
{% load static %}
-
+{% load pacer %}
{% block title %}RECAP Requests – CourtListener.com{% endblock %}
{% block og_title %}RECAP Requests – CourtListener.com{% endblock %}
@@ -21,6 +21,7 @@
Document Number |
PACER Doc ID |
Document Court |
+ Buy on Pacer |
@@ -31,6 +32,15 @@
{{ prayer.document_number }} |
{{ prayer.pacer_doc_id }} |
{{ prayer.docket_entry.docket.court_id }} |
+ Buy on PACER {% if prayer.page_count %}(${{ prayer|price }}){% endif %} |
{% empty %}
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index 2ba8914590..79307c6645 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -81,6 +81,7 @@ async def get_top_prayers() -> list[RECAPDocument]:
"document_number",
"attachment_number",
"pacer_doc_id",
+ "page_count",
"description",
"docket_entry__docket_id",
"docket_entry__docket__slug",
@@ -107,6 +108,7 @@ async def get_top_prayers() -> list[RECAPDocument]:
)
.order_by("-geometric_mean")[:50]
)
+
return [doc async for doc in documents.aiterator()]
From 385a943ef9800096cbe5f055ca42d92d4868d260 Mon Sep 17 00:00:00 2001
From: Alberto Islas
Date: Wed, 9 Oct 2024 10:49:22 -0600
Subject: [PATCH 36/74] fix(favorites): Improved prayers frontend query
performance and added tests
- Added PrayerAPITests
---
cl/api/urls.py | 2 +-
cl/favorites/api_serializers.py | 25 +-
cl/favorites/api_views.py | 2 +
cl/favorites/templates/top_prayers.html | 6 +
cl/favorites/tests.py | 237 +++++++++++++++++-
cl/favorites/utils.py | 51 +++-
.../templates/includes/de_list.html | 4 +-
cl/opinion_page/views.py | 47 ++--
8 files changed, 332 insertions(+), 42 deletions(-)
diff --git a/cl/api/urls.py b/cl/api/urls.py
index 85c4cd7691..e407d4b94a 100644
--- a/cl/api/urls.py
+++ b/cl/api/urls.py
@@ -97,7 +97,7 @@
)
# Prayers
-router.register(r"prayers", favorite_views.PrayerViewSet, basename="Prayer")
+router.register(r"prayers", favorite_views.PrayerViewSet, basename="prayer")
# Visualizations
router.register(
diff --git a/cl/favorites/api_serializers.py b/cl/favorites/api_serializers.py
index b05681bc23..a12bb4c101 100644
--- a/cl/favorites/api_serializers.py
+++ b/cl/favorites/api_serializers.py
@@ -1,8 +1,12 @@
+from asgiref.sync import async_to_sync
+from django.conf import settings
from drf_dynamic_fields import DynamicFieldsMixin
from rest_framework import serializers
+from rest_framework.exceptions import ValidationError
from rest_framework.serializers import ModelSerializer
from cl.favorites.models import DocketTag, Prayer, UserTag
+from cl.favorites.utils import prayer_eligible
from cl.search.models import Docket
@@ -48,6 +52,23 @@ class Meta:
read_only_fields = (
"date_created",
"user",
- "recap_document",
- "status",
)
+
+ def validate(self, data):
+ user = self.context["request"].user
+ recap_document = data.get("recap_document")
+
+ # Check if a Prayer for the same user and recap_document already exists
+ if Prayer.objects.filter(
+ user=user, recap_document=recap_document
+ ).exists():
+ raise ValidationError(
+ "A prayer for this recap document already exists."
+ )
+
+ # Check if the user is eligible to create a new prayer
+ if not async_to_sync(prayer_eligible)(user):
+ raise ValidationError(
+ f"You have reached the maximum number of prayers ({settings.ALLOWED_PRAYER_COUNT}) allowed in the last 24 hours."
+ )
+ return data
diff --git a/cl/favorites/api_views.py b/cl/favorites/api_views.py
index 36cc655f3b..981c1d3ebb 100644
--- a/cl/favorites/api_views.py
+++ b/cl/favorites/api_views.py
@@ -70,6 +70,8 @@ class PrayerViewSet(LoggingMixin, ModelViewSet):
ordering = "-date_created"
# Additional cursor ordering fields
cursor_ordering_fields = ["date_created"]
+ # Only allow these methods. Restricting PUT and PATCH.
+ http_method_names = ["get", "post", "delete", "head", "options"]
def get_queryset(self):
"""
diff --git a/cl/favorites/templates/top_prayers.html b/cl/favorites/templates/top_prayers.html
index 9afe9dafce..800f160d31 100644
--- a/cl/favorites/templates/top_prayers.html
+++ b/cl/favorites/templates/top_prayers.html
@@ -52,3 +52,9 @@
{% endblock %}
+
+{% block footer-scripts %}
+
+ {% include "includes/buy_pacer_modal.html" %}
+{% endblock %}
diff --git a/cl/favorites/tests.py b/cl/favorites/tests.py
index 9af49eb0c2..4fbb0d56a3 100644
--- a/cl/favorites/tests.py
+++ b/cl/favorites/tests.py
@@ -10,6 +10,7 @@
from django.template.defaultfilters import date as template_date
from django.test import AsyncClient, override_settings
from django.urls import reverse
+from django.utils import timezone
from django.utils.timezone import now
from selenium.webdriver.common.by import By
from timeout_decorator import timeout_decorator
@@ -17,7 +18,13 @@
from cl.custom_filters.templatetags.pacer import price
from cl.favorites.factories import NoteFactory, PrayerFactory
from cl.favorites.models import DocketTag, Note, Prayer, UserTag
-from cl.favorites.utils import create_prayer, get_top_prayers, prayer_eligible
+from cl.favorites.utils import (
+ create_prayer,
+ get_existing_prayers_in_bulk,
+ get_prayer_counts_in_bulk,
+ get_top_prayers,
+ prayer_eligible,
+)
from cl.lib.test_helpers import AudioTestCase, SimpleUserDataMixin
from cl.search.factories import RECAPDocumentFactory
from cl.search.views import get_homepage_stats
@@ -887,6 +894,26 @@ async def test_prayers_integration(self) -> None:
actual_top_prayers, expected_top_prayers, msg="Wrong top_prayers."
)
+ # Assert prayer_counts dict.
+ prayers_counts_dict = await get_prayer_counts_in_bulk(
+ [rd_6, self.rd_4]
+ )
+ self.assertEqual({rd_6.pk: 2, self.rd_4.pk: 1}, prayers_counts_dict)
+
+ # Assert existing_prayers dict for user
+ existing_prayers_dict = await get_existing_prayers_in_bulk(
+ self.user, [rd_6, self.rd_4]
+ )
+ self.assertEqual(
+ {rd_6.pk: True, self.rd_4.pk: True}, existing_prayers_dict
+ )
+
+ # Assert existing_prayers dict for user_2
+ existing_prayers_dict = await get_existing_prayers_in_bulk(
+ self.user_2, [rd_6, self.rd_4]
+ )
+ self.assertEqual({rd_6.pk: True}, existing_prayers_dict)
+
# rd_6 is granted.
rd_6.is_available = True
await rd_6.asave()
@@ -924,10 +951,13 @@ async def test_prayers_integration(self) -> None:
f"https://www.courtlistener.com{rd_6.get_absolute_url()}",
email_text_content,
)
- self.assertIn(
- f"You requested it on {template_date(prayer_1.date_created, 'M j, Y')}",
- email_text_content,
- )
+ with timezone.override("America/Los_Angeles"):
+ localized_date = timezone.localtime(prayer_1.date_created)
+ formatted_date = template_date(localized_date, "M j, Y")
+ self.assertIn(
+ f"You requested it on {formatted_date}",
+ email_text_content,
+ )
self.assertIn(
f"{len(actual_top_prayers)} people were also waiting for it.",
email_text_content,
@@ -945,10 +975,13 @@ async def test_prayers_integration(self) -> None:
f"{len(actual_top_prayers)} people were also waiting for it.",
html_content,
)
- self.assertIn(
- f"You requested it on {template_date(prayer_1.date_created, 'M j, Y')}",
- html_content,
- )
+ with timezone.override("America/Los_Angeles"):
+ localized_date = timezone.localtime(prayer_1.date_created)
+ formatted_date = template_date(localized_date, "M j, Y")
+ self.assertIn(
+ f"You requested it on {formatted_date}",
+ html_content,
+ )
self.assertIn(
f"Somebody paid ${price(rd_6)}",
html_content,
@@ -963,3 +996,189 @@ async def test_prayers_integration(self) -> None:
self.assertEqual(
top_prayers[0], self.rd_4, msg="The top prayer didn't match."
)
+
+
+class PrayerAPITests(APITestCase):
+ """Check that Prayer API operations works as expected."""
+
+ @classmethod
+ def setUpTestData(cls) -> None:
+ cls.user_1 = UserFactory()
+ cls.user_2 = UserFactory()
+
+ cls.rd_1 = RECAPDocumentFactory(
+ pacer_doc_id="98763421",
+ document_number="1",
+ is_available=True,
+ )
+ cls.rd_2 = RECAPDocumentFactory(
+ pacer_doc_id="98763422",
+ document_number="2",
+ is_available=False,
+ )
+ cls.rd_3 = RECAPDocumentFactory(
+ pacer_doc_id="98763423",
+ document_number="3",
+ is_available=False,
+ )
+
+ def setUp(self) -> None:
+ self.prayer_path = reverse("prayer-list", kwargs={"version": "v4"})
+ self.client = make_client(self.user_1.pk)
+ self.client_2 = make_client(self.user_2.pk)
+
+ async def make_a_prayer(
+ self,
+ client,
+ recap_doc_id,
+ ):
+ data = {
+ "recap_document": recap_doc_id,
+ }
+ return await client.post(self.prayer_path, data, format="json")
+
+ async def test_make_a_prayer(self) -> None:
+ """Can we make a prayer?"""
+
+ prayer = Prayer.objects.all()
+ response = await self.make_a_prayer(self.client, self.rd_1.pk)
+ prayer_first = await prayer.afirst()
+ self.assertIsNotNone(prayer_first)
+ self.assertEqual(await prayer.acount(), 1)
+ self.assertEqual(response.status_code, HTTPStatus.CREATED)
+
+ async def test_duplicate_prayer_fails(self) -> None:
+ """Ensure a user can't create multiple prayers for the same document
+ and user.
+ """
+ await self.make_a_prayer(self.client, self.rd_1.pk)
+ response = await self.make_a_prayer(self.client, self.rd_1.pk)
+ self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
+
+ async def test_list_users_prayers(self) -> None:
+ """Can we list user's own prayers?"""
+
+ # Make two prayers for user_1
+ await self.make_a_prayer(self.client, self.rd_1.pk)
+ await self.make_a_prayer(self.client, self.rd_3.id)
+
+ # Make one prayer for user_2
+ await self.make_a_prayer(self.client_2, self.rd_1.pk)
+
+ # Get the prayers for user_1, should be 2
+ response = await self.client.get(self.prayer_path)
+ self.assertEqual(response.status_code, HTTPStatus.OK)
+ self.assertEqual(len(response.json()["results"]), 2)
+
+ # Get the prayers for user_2, should be 1
+ response_2 = await self.client_2.get(self.prayer_path)
+ self.assertEqual(response_2.status_code, HTTPStatus.OK)
+ self.assertEqual(len(response_2.json()["results"]), 1)
+
+ async def test_delete_prayer(self) -> None:
+ """Can we delete a prayer?
+ Avoid users from deleting other users' prayers.
+ """
+
+ # Make two prayers for user_1
+ prayer_1 = await self.make_a_prayer(self.client, self.rd_1.pk)
+ prayer_2 = await self.make_a_prayer(self.client, self.rd_3.id)
+
+ prayer = Prayer.objects.all()
+ self.assertEqual(await prayer.acount(), 2)
+
+ prayer_1_path_detail = reverse(
+ "prayer-detail",
+ kwargs={"pk": prayer_1.json()["id"], "version": "v4"},
+ )
+
+ # Delete the prayer for user_1
+ response = await self.client.delete(prayer_1_path_detail)
+ self.assertEqual(response.status_code, HTTPStatus.NO_CONTENT)
+ self.assertEqual(await prayer.acount(), 1)
+
+ prayer_2_path_detail = reverse(
+ "prayer-detail",
+ kwargs={"pk": prayer_2.json()["id"], "version": "v3"},
+ )
+
+ # user_2 tries to delete a user_1 prayer, it should fail
+ response = await self.client_2.delete(prayer_2_path_detail)
+ self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND)
+ self.assertEqual(await prayer.acount(), 1)
+
+ async def test_prayer_detail(self) -> None:
+ """Can we get the detail for a prayer? Avoid users from getting other
+ users prayers.
+ """
+
+ # Make one prayer for user_1
+ prayer_1 = await self.make_a_prayer(self.client, self.rd_1.pk)
+ prayer = Prayer.objects.all()
+ self.assertEqual(await prayer.acount(), 1)
+ prayer_1_path_detail = reverse(
+ "prayer-detail",
+ kwargs={"pk": prayer_1.json()["id"], "version": "v3"},
+ )
+
+ # Get the prayer detail for user_1
+ response = await self.client.get(prayer_1_path_detail)
+ self.assertEqual(response.status_code, HTTPStatus.OK)
+
+ # user_2 tries to get user_1 prayer, it should fail
+ response = await self.client_2.get(prayer_1_path_detail)
+ self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND)
+
+ async def test_prayer_update_fails(self) -> None:
+ """PUT AND PATCH methods are restricted."""
+
+ # Make one prayer for user_1
+ prayer_1 = await self.make_a_prayer(self.client, self.rd_1.pk)
+ prayer_1_path_detail = reverse(
+ "prayer-detail",
+ kwargs={"pk": prayer_1.json()["id"], "version": "v3"},
+ )
+ # PATCH not allowed
+ data = {"status": 2}
+ response = await self.client.patch(
+ prayer_1_path_detail, data, format="json"
+ )
+ self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED)
+
+ # PUT not allowed
+ data = {"status": 2, "recap_document": self.rd_1.pk}
+ response = await self.client.put(
+ prayer_1_path_detail, data, format="json"
+ )
+ self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED)
+
+ @override_settings(ALLOWED_PRAYER_COUNT=2)
+ async def test_prayer_creation_eligibility(self):
+ """Test the prayer creation eligibility and limits in the API."""
+ current_time = timezone.now()
+ prayers = Prayer.objects.all()
+
+ with time_machine.travel(current_time, tick=False):
+ # First prayer succeed
+ response = await self.make_a_prayer(self.client, self.rd_1.pk)
+ self.assertEqual(response.status_code, HTTPStatus.CREATED)
+ self.assertEqual(await prayers.acount(), 1)
+
+ # Second prayer succeed
+ response = await self.make_a_prayer(self.client, self.rd_2.pk)
+ self.assertEqual(response.status_code, HTTPStatus.CREATED)
+ self.assertEqual(await prayers.acount(), 2)
+
+ # Third prayer fails due to limit
+ response = await self.make_a_prayer(self.client, self.rd_3.pk)
+ self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
+ self.assertIn("maximum number of prayers", str(response.data))
+ self.assertEqual(await prayers.acount(), 2)
+
+ # After more than 24 hours the user is eligible to create more prays.
+ with time_machine.travel(
+ current_time + timedelta(hours=25), tick=False
+ ):
+ response = await self.make_a_prayer(self.client, self.rd_3.pk)
+ self.assertEqual(response.status_code, HTTPStatus.CREATED)
+ self.assertEqual(await prayers.acount(), 3)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index 79307c6645..814585fbf3 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -35,18 +35,6 @@ async def prayer_eligible(user: User) -> bool:
return prayer_count < allowed_prayer_count
-async def prayer_exists(user: User, recap_document: RECAPDocument) -> bool:
- return await Prayer.objects.filter(
- user=user, recap_document=recap_document
- ).aexists()
-
-
-async def get_prayer_count(recap_document: RECAPDocument) -> int:
- return await Prayer.objects.filter(
- recap_document=recap_document, status=Prayer.WAITING
- ).acount()
-
-
async def create_prayer(
user: User, recap_document: RECAPDocument
) -> Prayer | None:
@@ -58,6 +46,45 @@ async def create_prayer(
return None
+async def get_prayer_counts_in_bulk(
+ recap_documents: list[RECAPDocument],
+) -> dict[str, int]:
+ """Retrieve the count of prayers with a status of "WAITING" for a list of recap documents.
+
+ :param recap_documents: A list of RECAPDocument instances to filter prayers.
+ :return: A dictionary where keys are RECAPDocument IDs and values are the
+ count of "WAITING" prayers for each document.
+ """
+
+ prayer_counts = (
+ Prayer.objects.filter(
+ recap_document__in=recap_documents, status=Prayer.WAITING
+ )
+ .values("recap_document")
+ .annotate(count=Count("id"))
+ )
+ return {
+ prayer_count["recap_document"]: prayer_count["count"]
+ async for prayer_count in prayer_counts
+ }
+
+
+async def get_existing_prayers_in_bulk(
+ user: User, recap_documents: list[RECAPDocument]
+) -> dict[int, bool]:
+ """Check if prayers exist for a user and a list of recap documents.
+
+ :param user: The user for whom to check prayer existence.
+ :param recap_documents: A list of RECAPDocument instances to check prayers.
+ :return: A dictionary where keys are RECAPDocument IDs and values are True
+ if a prayer exists for the user and RD.
+ """
+ existing_prayers = Prayer.objects.filter(
+ user=user, recap_document__in=recap_documents
+ ).values_list("recap_document_id", flat=True)
+ return {rd_id: True async for rd_id in existing_prayers}
+
+
async def get_top_prayers() -> list[RECAPDocument]:
# Calculate the age of each prayer
prayer_age = ExpressionWrapper(
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index 4c97d9d509..86913a4131 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -173,11 +173,11 @@
{% if request.user.is_authenticated %}
diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py
index 4828468232..7c527529dd 100644
--- a/cl/opinion_page/views.py
+++ b/cl/opinion_page/views.py
@@ -44,7 +44,11 @@
from cl.custom_filters.templatetags.text_filters import best_case_name
from cl.favorites.forms import NoteForm
from cl.favorites.models import Note
-from cl.favorites.utils import get_prayer_count, prayer_eligible, prayer_exists
+from cl.favorites.utils import (
+ get_existing_prayers_in_bulk,
+ get_prayer_counts_in_bulk,
+ prayer_eligible,
+)
from cl.lib.auth import group_required
from cl.lib.bot_detector import is_og_bot
from cl.lib.decorators import cache_page_ignore_params
@@ -379,20 +383,6 @@ async def view_docket(
"-recap_sequence_number", "-entry_number"
)
- for entry in await sync_to_async(list)(de_list):
- if await sync_to_async(entry.recap_documents.count)() > 0:
- for rd in await sync_to_async(list)(entry.recap_documents.all()):
- if rd.pacer_url and not (rd.is_free_on_pacer or rd.is_sealed):
- rd.prayer_count = await get_prayer_count(rd)
-
- if request.user.is_authenticated:
- rd.prayer_exists = await prayer_exists(
- request.user, rd
- )
- rd.prayer_eligible = await prayer_eligible(
- request.user
- )
-
page = request.GET.get("page", 1)
@sync_to_async
@@ -405,15 +395,40 @@ def paginate_docket_entries(docket_entries, docket_page):
except EmptyPage:
return paginator.page(paginator.num_pages)
+ paginated_entries = await paginate_docket_entries(de_list, page)
+
+ # Extract recap documents from the current page.
+ recap_documents = [
+ rd
+ for entry in await sync_to_async(list)(paginated_entries)
+ async for rd in entry.recap_documents.all()
+ ]
+ # Get prayer counts in bulk.
+ prayer_counts = await get_prayer_counts_in_bulk(recap_documents)
+ existing_prayers = {}
+ prayer_is_eligible = False
+ if request.user.is_authenticated:
+ # Check prayer existence in bulk.
+ existing_prayers = await get_existing_prayers_in_bulk(
+ request.user, recap_documents
+ )
+ prayer_is_eligible = await prayer_eligible(request.user)
+
+ # Merge counts and existing prayer status to RECAPDocuments.
+ for rd in recap_documents:
+ rd.prayer_count = prayer_counts.get(rd.id, 0)
+ rd.prayer_exists = existing_prayers.get(rd.id, False)
+
context.update(
{
"parties": await docket.parties.aexists(),
# Needed to show/hide parties tab.
"authorities": await docket.ahas_authorities(),
- "docket_entries": await paginate_docket_entries(de_list, page),
+ "docket_entries": paginated_entries,
"sort_order_asc": sort_order_asc,
"form": form,
"get_string": make_get_string(request),
+ "prayer_eligible": prayer_is_eligible,
}
)
return TemplateResponse(request, "docket.html", context)
From e4ebf01c29dfb19d6e4026680e46717b6a4a773f Mon Sep 17 00:00:00 2001
From: Alberto Islas
Date: Wed, 9 Oct 2024 17:00:51 -0600
Subject: [PATCH 37/74] fix(favorites): Linked pray button to modal-logged-out
---
cl/opinion_page/templates/includes/de_list.html | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index 86913a4131..fbdd7885d0 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -184,12 +184,14 @@
{{rd.prayer_count}} 🙏
{% else %}
-
{{rd.prayer_count}} 🙏
-
+
{% endif %}
{% endif %}
{% endif %}
From 47ee93f22c1c5b7f8dcd48fa774ecdb237e3a469 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Wed, 9 Oct 2024 22:54:59 -0400
Subject: [PATCH 38/74] delete prayer function
---
cl/favorites/utils.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index 814585fbf3..ad612b4765 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -46,6 +46,14 @@ async def create_prayer(
return None
+async def delete_prayer(
+ user: User, recap_document: RECAPDocument
+) -> bool:
+ await Prayer.objects.filter.adelete(user=user, recap_document=recap_document)
+
+ return await Prayer.objects.filter(user=user, recap_document=recap_document).aexists()
+
+
async def get_prayer_counts_in_bulk(
recap_documents: list[RECAPDocument],
) -> dict[str, int]:
From e005d829d2d794cfed7384d8f46b75ab9c6d5453 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Thu, 10 Oct 2024 02:55:39 +0000
Subject: [PATCH 39/74] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
cl/favorites/utils.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py
index ad612b4765..07a29b0dab 100644
--- a/cl/favorites/utils.py
+++ b/cl/favorites/utils.py
@@ -46,12 +46,14 @@ async def create_prayer(
return None
-async def delete_prayer(
- user: User, recap_document: RECAPDocument
-) -> bool:
- await Prayer.objects.filter.adelete(user=user, recap_document=recap_document)
+async def delete_prayer(user: User, recap_document: RECAPDocument) -> bool:
+ await Prayer.objects.filter.adelete(
+ user=user, recap_document=recap_document
+ )
- return await Prayer.objects.filter(user=user, recap_document=recap_document).aexists()
+ return await Prayer.objects.filter(
+ user=user, recap_document=recap_document
+ ).aexists()
async def get_prayer_counts_in_bulk(
From f806fb34eb546a709dc130e83cf53fdeb06f0bee Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Wed, 9 Oct 2024 23:14:36 -0400
Subject: [PATCH 40/74] waffle flag "pray-and-pay"
---
cl/opinion_page/templates/includes/de_list.html | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index fbdd7885d0..941d5202a6 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -1,6 +1,6 @@
{% load pacer %}
{% load tz %}
-
+{% load waffle_tags %}
@@ -171,7 +171,8 @@
target="_blank"
rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %}
- {% if request.user.is_authenticated %}
+ {% flag "pray-and-pay" %}
+ {% if request.user.is_authenticated %}
{% endif %}
+ {% endflag %}
{% endif %}
{% endif %}
{% endif %}
From f617d8582c8e4fb785cf6ed9fffb578b07985ab0 Mon Sep 17 00:00:00 2001
From: v_anne <69829523+v-anne@users.noreply.github.com>
Date: Thu, 10 Oct 2024 09:42:46 -0400
Subject: [PATCH 41/74] work on frontend
---
.../templates/includes/de_list.html | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html
index 941d5202a6..5c5a5dd7f0 100644
--- a/cl/opinion_page/templates/includes/de_list.html
+++ b/cl/opinion_page/templates/includes/de_list.html
@@ -173,17 +173,16 @@
{% flag "pray-and-pay" %}
{% if request.user.is_authenticated %}
-
+
+
+
{% else %}