diff --git a/accounts/views.py b/accounts/views.py index 4a4f890..735db1d 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar +from typing import TYPE_CHECKING from django.contrib.auth import login from django.contrib.auth.decorators import login_required @@ -11,6 +11,7 @@ from django.views.generic import CreateView from accounts.forms import CustomUserCreationForm from accounts.models import User +from twitch.models import NotificationSubscription if TYPE_CHECKING: from django.forms import BaseModelForm @@ -36,7 +37,7 @@ class CustomLogoutView(LogoutView): """Custom logout view.""" next_page = reverse_lazy("twitch:dashboard") - http_method_names: ClassVar[list[str]] = ["get", "post", "options"] # pyright: ignore[reportIncompatibleVariableOverride] + http_method_names = ["get", "post", "options"] def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: """Allow GET requests for logout. @@ -84,4 +85,12 @@ def profile_view(request: HttpRequest) -> HttpResponse: Returns: HttpResponse: Rendered profile template. """ - return render(request, "accounts/profile.html", {"user": request.user}) + subscriptions = NotificationSubscription.objects.filter(user=request.user) + return render( + request, + "accounts/profile.html", + { + "user": request.user, + "subscriptions": subscriptions, + }, + ) diff --git a/pyproject.toml b/pyproject.toml index 297126e..50520e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,8 @@ lint.pydocstyle.convention = "google" lint.isort.required-imports = ["from __future__ import annotations"] lint.ignore = [ + "ANN002", # Checks that function *args arguments have type annotations. + "ANN003", # Checks that function **kwargs arguments have type annotations. "CPY001", # Checks for the absence of copyright notices within Python files. "D100", # Checks for undocumented public module definitions. "D104", # Checks for undocumented public package definitions. @@ -45,8 +47,7 @@ lint.ignore = [ "ERA001", # Checks for commented-out Python code. "FIX002", # Checks for "TODO" comments. "PLR6301", # Checks for the presence of unused self parameter in methods definitions. - "ANN002", # Checks that function *args arguments have type annotations. - "ANN003", # Checks that function **kwargs arguments have type annotations. + "RUF012", # Checks for mutable default values in class attributes. # Conflicting lint rules when using Ruff's formatter # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules diff --git a/templates/accounts/profile.html b/templates/accounts/profile.html index 1bce3ed..c6dc6be 100644 --- a/templates/accounts/profile.html +++ b/templates/accounts/profile.html @@ -26,4 +26,19 @@ Logout +

Will get notifications to:

+ {% endblock content %} diff --git a/templates/twitch/campaign_detail.html b/templates/twitch/campaign_detail.html index 9952918..aa79fde 100644 --- a/templates/twitch/campaign_detail.html +++ b/templates/twitch/campaign_detail.html @@ -9,7 +9,7 @@

{# TODO: Link to organization #} - {{ campaign.owner.name }} + {{ campaign.owner.name }}

{% if campaign.image_url %} {{ game.display_name }} + {% if owner %} + {{ owner.name }} + {% endif %} {% if user.is_authenticated %}
diff --git a/templates/twitch/org_list.html b/templates/twitch/org_list.html index 44882d9..bc53a35 100644 --- a/templates/twitch/org_list.html +++ b/templates/twitch/org_list.html @@ -8,7 +8,7 @@ diff --git a/templates/twitch/organization_detail.html b/templates/twitch/organization_detail.html index 968d5da..cc7723f 100644 --- a/templates/twitch/organization_detail.html +++ b/templates/twitch/organization_detail.html @@ -13,14 +13,14 @@ id="found" name="notify_found" {% if subscription and subscription.notify_found %}checked{% endif %} /> - +
- +
diff --git a/twitch/models.py b/twitch/models.py index 86a75da..404b63f 100644 --- a/twitch/models.py +++ b/twitch/models.py @@ -216,4 +216,8 @@ class NotificationSubscription(models.Model): ] def __str__(self) -> str: - return f"{self.user} subscription to {Game.display_name}" + if self.game: + return f"{self.user} subscription to game: {self.game.display_name}" + if self.organization: + return f"{self.user} subscription to organization: {self.organization.name}" + return f"{self.user} subscription" diff --git a/twitch/urls.py b/twitch/urls.py index 14e392f..35fa48b 100644 --- a/twitch/urls.py +++ b/twitch/urls.py @@ -14,6 +14,6 @@ urlpatterns = [ path("games//", views.GameDetailView.as_view(), name="game_detail"), path("games//subscribe/", views.subscribe_game_notifications, name="subscribe_notifications"), path("organizations/", views.OrgListView.as_view(), name="org_list"), - path("organizations//", views.OrgDetailView.as_view(), name="org_detail"), + path("organizations//", views.OrgDetailView.as_view(), name="organization_detail"), path("organizations//subscribe/", views.subscribe_org_notifications, name="subscribe_org_notifications"), ] diff --git a/twitch/views.py b/twitch/views.py index 8c8e05f..e168bb2 100644 --- a/twitch/views.py +++ b/twitch/views.py @@ -49,10 +49,21 @@ class OrgDetailView(DetailView): Returns: dict: Context data. """ - organization: Organization = self.object context = super().get_context_data(**kwargs) - games = Game.objects.filter(drop_campaigns__owner=organization).distinct() - context["games"] = games + organization: Organization = self.object + + user = self.request.user + if not user.is_authenticated: + subscription: NotificationSubscription | None = None + else: + subscription = NotificationSubscription.objects.filter(user=user, organization=organization).first() + + games: QuerySet[Game, Game] = Game.objects.filter(drop_campaigns__owner=organization).distinct() + context.update({ + "subscription": subscription, + "games": games, + }) + return context @@ -290,6 +301,7 @@ class GameDetailView(DetailView): "upcoming_campaigns": upcoming_campaigns, "expired_campaigns": expired_campaigns, "subscription": subscription, + "owner": active_campaigns[0].owner if active_campaigns else None, "now": now, }) @@ -430,7 +442,7 @@ def subscribe_org_notifications(request: HttpRequest, org_id: str) -> HttpRespon message = "" messages.success(request, message) - return redirect("organization_detail", org_id=organization.id) + return redirect("twitch:organization_detail", pk=organization.id) messages.warning(request, "Only POST is available for this view.") - return redirect("organization_detail", org_id=organization.id) + return redirect("twitch:organization_detail", pk=organization.id)