diff --git a/.env.example b/.env.example index 25cd8994a9..7d111c1b3f 100644 --- a/.env.example +++ b/.env.example @@ -42,6 +42,3 @@ IA_ACCESS_KEY="" IA_SECRET_KEY="" FTM_KEY="" - -# CL API key for cloning data -CL_API_KEY="" diff --git a/cl/api/urls.py b/cl/api/urls.py index e407d4b94a..cf600790d9 100644 --- a/cl/api/urls.py +++ b/cl/api/urls.py @@ -96,9 +96,6 @@ 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/assets/static-global/css/override.css b/cl/assets/static-global/css/override.css index 3693518187..7a27e9f08f 100644 --- a/cl/assets/static-global/css/override.css +++ b/cl/assets/static-global/css/override.css @@ -1723,11 +1723,3 @@ rect.series-segment { opacity 150ms 150ms ease-in; transform: translate3d(0, 0, 0); } - -.prayer-button[data-gap-size="small"] { - margin-left: 8px; -} - -.prayer-button[data-gap-size="large"]{ - margin-left: 44px; -} diff --git a/cl/assets/templates/base.html b/cl/assets/templates/base.html index be91672e34..33181f52e1 100644 --- a/cl/assets/templates/base.html +++ b/cl/assets/templates/base.html @@ -231,22 +231,17 @@

You did not supply the "private" variable to your template.
  • Install RECAP
  • - {% flag "pray-and-pay" %} -
  • - Pray and Pay Project -
  • - {% endflag %}
  • - Get Case Alerts + Get Case Alerts
  • - About this Collection + About this Collection
  • - Bulk Data Service + Bulk Data Service
  • - API + API
  • diff --git a/cl/favorites/api_serializers.py b/cl/favorites/api_serializers.py index a12bb4c101..7f0ed014df 100644 --- a/cl/favorites/api_serializers.py +++ b/cl/favorites/api_serializers.py @@ -1,12 +1,8 @@ -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.favorites.models import DocketTag, UserTag from cl.search.models import Docket @@ -41,34 +37,3 @@ 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", - ) - - 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 981c1d3ebb..f53d5c4fb1 100644 --- a/cl/favorites/api_views.py +++ b/cl/favorites/api_views.py @@ -4,15 +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, - PrayerSerializer, - UserTagSerializer, -) -from cl.favorites.filters import DocketTagFilter, PrayerFilter, UserTagFilter -from cl.favorites.models import DocketTag, Prayer, UserTag +from cl.favorites.api_serializers import DocketTagSerializer, UserTagSerializer +from cl.favorites.filters import DocketTagFilter, UserTagFilter +from cl.favorites.models import DocketTag, UserTag class UserTagViewSet(ModelViewSet): @@ -56,29 +51,3 @@ 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"] - # Only allow these methods. Restricting PUT and PATCH. - http_method_names = ["get", "post", "delete", "head", "options"] - - 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") diff --git a/cl/favorites/filters.py b/cl/favorites/filters.py index cbd3c24a1f..e0e2e0e724 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, Prayer, UserTag +from cl.favorites.models import DocketTag, UserTag class UserTagFilter(NoEmptyFilterSet): @@ -21,19 +21,3 @@ 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"], - } diff --git a/cl/favorites/templates/top_prayers.html b/cl/favorites/templates/top_prayers.html index 980d6a76e8..a12a5edba3 100644 --- a/cl/favorites/templates/top_prayers.html +++ b/cl/favorites/templates/top_prayers.html @@ -2,17 +2,15 @@ {% load extras %} {% load text_filters %} {% load static %} -{% load pacer %} + {% block title %}RECAP Requests – CourtListener.com{% endblock %} {% block og_title %}RECAP Requests – CourtListener.com{% endblock %} -{% block description %}RECAP Requests on CourtListener.{% endblock %} -{% block og_description %}RECAP Requests on CourtListener.{% endblock %} - +{% block description %}Lorem Ipsum on CourtListener.{% endblock %} +{% block og_description %}Lorem Ipsum on CourtListener.{% endblock %} {% block content %} -
    @@ -23,7 +21,6 @@ - @@ -34,15 +31,6 @@ - {% empty %} @@ -54,9 +42,3 @@ {% endblock %} - -{% block footer-scripts %} - - {% include "includes/buy_pacer_modal.html" %} -{% endblock %} diff --git a/cl/favorites/tests.py b/cl/favorites/tests.py index e2aa34ab56..e60ff89fe0 100644 --- a/cl/favorites/tests.py +++ b/cl/favorites/tests.py @@ -10,7 +10,6 @@ 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 make_naive, now from selenium.webdriver.common.by import By from timeout_decorator import timeout_decorator @@ -18,14 +17,7 @@ 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, - delete_prayer, - get_existing_prayers_in_bulk, - get_prayer_counts_in_bulk, - get_top_prayers, - prayer_eligible, -) +from cl.favorites.utils import create_prayer, 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 @@ -679,15 +671,9 @@ def setUpTestData(cls) -> None: is_available=False, ) - cls.rd_6 = RECAPDocumentFactory( - pacer_doc_id="98763426", - document_number="6", - is_available=False, - ) - @override_settings(ALLOWED_PRAYER_COUNT=2) async def test_prayer_eligible(self) -> None: - """Does the prayer_eligible method work properly?""" + """Does the prayer_eligible method works properly?""" current_time = now() with time_machine.travel(current_time, tick=False): @@ -727,7 +713,7 @@ async def test_prayer_eligible(self) -> None: self.assertTrue(user_is_eligible) async def test_create_prayer(self) -> None: - """Does the create_prayer method work properly?""" + """Does the create_prayer method works properly?""" # Prayer is not created if the document is already available. prayer_created = await create_prayer(self.user, self.rd_1) @@ -741,29 +727,8 @@ async def test_create_prayer(self) -> None: same_prayer_created = await create_prayer(self.user, self.rd_2) self.assertIsNone(same_prayer_created) - async def test_delete_prayer(self) -> None: - """Does the delete_prayer method work properly?""" - - # Prayer is added, then deleted successfully - prayer_created = await create_prayer(self.user, self.rd_2) - prayer_deleted = await delete_prayer(self.user, self.rd_2) - self.assertTrue(prayer_deleted) - - # Prayer is created, then document is made available to check that a user can't delete a prayer that has been granted - prayer_created = await create_prayer(self.user, self.rd_6) - self.rd_6.is_available = True - await sync_to_async(self.rd_6.save)() - prayer_deleted = await delete_prayer(self.user, self.rd_6) - self.assertFalse(prayer_deleted) - - # Ensure that a user cannot delete the same prayer twice - prayer_created = await create_prayer(self.user, self.rd_2) - prayer_deleted = await delete_prayer(self.user, self.rd_2) - prayer_deleted = await delete_prayer(self.user, self.rd_2) - self.assertFalse(prayer_deleted) - async def test_get_top_prayers_by_number(self) -> None: - """Does the get_top_prayers method work properly?""" + """Does the get_top_prayers method works properly?""" # Test top documents based on prayers count. current_time = now() @@ -791,7 +756,7 @@ async def test_get_top_prayers_by_number(self) -> None: ) async def test_get_top_prayers_by_age(self) -> None: - """Does the get_top_prayers method work properly?""" + """Does the get_top_prayers method works properly?""" # Test top documents based on prayer age. current_time = now() @@ -822,7 +787,7 @@ async def test_get_top_prayers_by_age(self) -> None: ) async def test_get_top_prayers_by_number_and_age(self) -> None: - """Does the get_top_prayers method work properly?""" + """Does the get_top_prayers method works properly?""" # Create prayers with different counts and ages current_time = now() @@ -922,26 +887,6 @@ 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() @@ -1018,189 +963,3 @@ 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 work 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/urls.py b/cl/favorites/urls.py index a97cc9cc8e..65ef65544d 100644 --- a/cl/favorites/urls.py +++ b/cl/favorites/urls.py @@ -1,9 +1,7 @@ from django.urls import path from cl.favorites.views import ( - create_prayer_view, delete_note, - delete_prayer_view, open_prayers, save_or_update_note, view_tag, @@ -26,14 +24,4 @@ ), 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/delete//", - delete_prayer_view, - name="delete_prayer", - ), ] diff --git a/cl/favorites/utils.py b/cl/favorites/utils.py index bbe40309c3..dae437abad 100644 --- a/cl/favorites/utils.py +++ b/cl/favorites/utils.py @@ -46,53 +46,6 @@ async def create_prayer( return None -async def delete_prayer(user: User, recap_document: RECAPDocument) -> bool: - deleted, _ = await Prayer.objects.filter( - user=user, recap_document=recap_document, status=Prayer.WAITING - ).adelete() - - return deleted > 0 - - -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( @@ -116,7 +69,6 @@ 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", @@ -143,7 +95,6 @@ async def get_top_prayers() -> list[RECAPDocument]: ) .order_by("-geometric_mean")[:50] ) - return [doc async for doc in documents.aiterator()] @@ -197,33 +148,3 @@ def send_prayer_emails(instance: RECAPDocument) -> None: messages.append(msg) connection = get_connection() connection.send_messages(messages) - - -async def get_user_prayer_history(user: User) -> tuple[int, float]: - filtered_list = Prayer.objects.filter(user=user, status=Prayer.GRANTED) - - count = await filtered_list.acount() - - total_cost = 0 - async for prayer in filtered_list: - total_cost += float(price(prayer.recap_document)) - - return count, total_cost - - -async def get_lifetime_prayer_stats() -> tuple[int, int, float]: - - filtered_list = Prayer.objects.filter(status=Prayer.GRANTED) - - count = await filtered_list.acount() - - total_cost = 0 - distinct_documents = set() - - async for prayer in filtered_list: - distinct_documents.add(prayer.recap_document) - total_cost += float(await price(prayer.recap_document)) - - num_distinct_purchases = len(distinct_documents) - - return count, num_distinct_purchases, total_cost diff --git a/cl/favorites/views.py b/cl/favorites/views.py index 0b05a6eb72..1cd5b8ba15 100644 --- a/cl/favorites/views.py +++ b/cl/favorites/views.py @@ -17,16 +17,10 @@ from cl.favorites.forms import NoteForm from cl.favorites.models import DocketTag, Note, UserTag -from cl.favorites.utils import ( - create_prayer, - delete_prayer, - get_top_prayers, - prayer_eligible, -) +from cl.favorites.utils import 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: @@ -188,73 +182,11 @@ async def open_prayers(request: HttpRequest) -> HttpResponse: """Show the user top open prayer requests.""" top_prayers = await get_top_prayers() - - context = { - "top_prayers": top_prayers, - "private": False, - } - - return TemplateResponse(request, "top_prayers.html", context) - - -@login_required -async def create_prayer_view( - request: HttpRequest, recap_document: int -) -> HttpResponse: - user = request.user - is_htmx_request = request.META.get("HTTP_HX_REQUEST", False) - if not await prayer_eligible(request.user): - if is_htmx_request: - return TemplateResponse( - request, - "includes/pray_and_pay_htmx/pray_button.html", - { - "prayer_exists": False, - "document_id": recap_document, - "count": 0, - "daily_limit_reached": True, - }, - ) - return HttpResponseServerError( - "User have reached your daily request limit" - ) - - recap_document = await RECAPDocument.objects.aget(id=recap_document) - - # Call the create_prayer async function - await create_prayer(user, recap_document) - if is_htmx_request: - return TemplateResponse( - request, - "includes/pray_and_pay_htmx/pray_button.html", - { - "prayer_exists": True, - "document_id": recap_document.pk, - "count": 0, - "daily_limit_reached": False, - }, - ) - return HttpResponse("It worked.") - - -@login_required -async def delete_prayer_view( - request: HttpRequest, recap_document: int -) -> HttpResponse: - user = request.user - recap_document = await RECAPDocument.objects.aget(id=recap_document) - - # Call the delete_prayer async function - await delete_prayer(user, recap_document) - - if request.META.get("HTTP_HX_REQUEST"): - return TemplateResponse( - request, - "includes/pray_and_pay_htmx/pray_button.html", - { - "prayer_exists": False, - "document_id": recap_document.pk, - "count": 0, - }, - ) - return HttpResponse("It worked.") + return TemplateResponse( + request, + "top_prayers.html", + { + "top_prayers": top_prayers, + "private": True, # temporary to prevent Google indexing + }, + ) diff --git a/cl/opinion_page/static/js/pay_and_pray.js b/cl/opinion_page/static/js/pay_and_pray.js deleted file mode 100644 index aeab8195a2..0000000000 --- a/cl/opinion_page/static/js/pay_and_pray.js +++ /dev/null @@ -1,65 +0,0 @@ -function updatePrayerButton(button) { - // Get the document ID and prayer counter element from the button. - let documentId = button.dataset.documentId; - let prayerCounterSpan = document.querySelector(`#counter_${documentId}`); - - // Get the current prayer count. - let prayerCount = parseInt(prayerCounterSpan.innerText, 10); - - // Update the button's class and prayer count based on its current state. - if (button.classList.contains('btn-primary')) { - // If the button is primary (already prayed), change it to default and - // decrement the count. - button.classList.add('btn-default'); - button.classList.remove('btn-primary'); - prayerCount--; - } else { - // If the button is default (not yet prayed), change it to primary and - // increment the count. - button.classList.remove('btn-default'); - button.classList.add('btn-primary'); - prayerCount++; - } - // Update the prayer counter display. - prayerCounterSpan.innerText = prayerCount; -} - -document.addEventListener('htmx:beforeRequest', function (event) { - // Before sending the request, update the button's appearance and counter to - // provide instant feedback. - let form = event.detail.elt; - let button = form.querySelector('button'); - updatePrayerButton(button); -}); - -document.addEventListener('htmx:afterRequest', function (event) { - // If the request was successful, don't update the button as it will be - // updated by another HTMX event. - if (event.detail.successful) return; - - // If there was an error, revert the changes made to the button and counter. - let form = event.detail.elt; - let button = form.querySelector('button'); - updatePrayerButton(button); -}); - -document.addEventListener('htmx:oobBeforeSwap', function (event) { - // Before swapping the new content, update the prayer counter in the incoming - // fragment to avoid unnecessary server calculations. - let form = event.detail.elt; - let button = form.querySelector('button'); - // If the daily limit tooltip is present in the fragment, it means the user - // has reached their limit. Therefore, we should revert any changes made to - // the prayer button. - if (event.detail.fragment.querySelector('#daily_limit_tooltip')) { - updatePrayerButton(button); - } - let documentId = button.dataset.documentId; - let prayerCounterSpan = document.querySelector(`#counter_${documentId}`); - let prayerCount = parseInt(prayerCounterSpan.innerText, 10); - event.detail.fragment.getElementById(`counter_${documentId}`).innerText = prayerCount; -}); - -document.addEventListener('htmx:oobAfterSwap', function (event) { - $('[data-toggle="tooltip"]').tooltip(); -}); diff --git a/cl/opinion_page/templates/docket.html b/cl/opinion_page/templates/docket.html index 084bbba8c0..be857c1da5 100644 --- a/cl/opinion_page/templates/docket.html +++ b/cl/opinion_page/templates/docket.html @@ -22,16 +22,6 @@ href="{% url "docket_feed" docket.pk %}" /> {% endblock %} -{% block footer-scripts %} - {% if DEBUG %} - - - {% else %} - - {% endif %} - -{% endblock %} - {% block nav-de %}active{% endblock %} {% block tab-content %} {% if docket_entries.paginator.count %} diff --git a/cl/opinion_page/templates/includes/de_list.html b/cl/opinion_page/templates/includes/de_list.html index 5ab5f72e5c..0c0776ef9f 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,11 +171,6 @@ target="_blank" rel="nofollow">Buy on PACER {% if rd.page_count %}(${{ rd|price }}){% endif %} - {% flag "pray-and-pay" %} -
    - {% include "includes/pray_and_pay_htmx/pray_button.html" with prayer_exists=rd.prayer_exists document_id=rd.id count=rd.prayer_count%} -
    - {% endflag %} {% endif %} {% endif %} {% endif %} diff --git a/cl/opinion_page/templates/includes/pray_and_pay_htmx/pray_button.html b/cl/opinion_page/templates/includes/pray_and_pay_htmx/pray_button.html deleted file mode 100644 index 6b8c526a39..0000000000 --- a/cl/opinion_page/templates/includes/pray_and_pay_htmx/pray_button.html +++ /dev/null @@ -1,27 +0,0 @@ -{% if request.user.is_authenticated %} -
    - - {% if daily_limit_reached %} -   - - - - {% endif %} - -{% else %} - -{% endif %} diff --git a/cl/opinion_page/views.py b/cl/opinion_page/views.py index 95cbec270d..678de041d7 100644 --- a/cl/opinion_page/views.py +++ b/cl/opinion_page/views.py @@ -44,11 +44,6 @@ 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_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 @@ -395,45 +390,15 @@ 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) - - prayer_is_eligible = False - flag_for_prayers = await sync_to_async(waffle.flag_is_active)( - request, "pray-and-pay" - ) - if flag_for_prayers: - # 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 = {} - - 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": paginated_entries, + "docket_entries": await paginate_docket_entries(de_list, page), "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)
    Document Number PACER Doc ID Document CourtBuy on Pacer
    {{ prayer.document_number }} {{ prayer.pacer_doc_id }} {{ prayer.docket_entry.docket.court_id }}Buy on PACER {% if prayer.page_count %}(${{ prayer|price }}){% endif %}