Improve HTML on profile and game details
This commit is contained in:
parent
4af2b02a01
commit
2ff314ecc8
10 changed files with 60 additions and 16 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
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 import login
|
||||||
from django.contrib.auth.decorators import login_required
|
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.forms import CustomUserCreationForm
|
||||||
from accounts.models import User
|
from accounts.models import User
|
||||||
|
from twitch.models import NotificationSubscription
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.forms import BaseModelForm
|
from django.forms import BaseModelForm
|
||||||
|
|
@ -36,7 +37,7 @@ class CustomLogoutView(LogoutView):
|
||||||
"""Custom logout view."""
|
"""Custom logout view."""
|
||||||
|
|
||||||
next_page = reverse_lazy("twitch:dashboard")
|
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:
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
"""Allow GET requests for logout.
|
"""Allow GET requests for logout.
|
||||||
|
|
@ -84,4 +85,12 @@ def profile_view(request: HttpRequest) -> HttpResponse:
|
||||||
Returns:
|
Returns:
|
||||||
HttpResponse: Rendered profile template.
|
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,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ lint.pydocstyle.convention = "google"
|
||||||
lint.isort.required-imports = ["from __future__ import annotations"]
|
lint.isort.required-imports = ["from __future__ import annotations"]
|
||||||
|
|
||||||
lint.ignore = [
|
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.
|
"CPY001", # Checks for the absence of copyright notices within Python files.
|
||||||
"D100", # Checks for undocumented public module definitions.
|
"D100", # Checks for undocumented public module definitions.
|
||||||
"D104", # Checks for undocumented public package definitions.
|
"D104", # Checks for undocumented public package definitions.
|
||||||
|
|
@ -45,8 +47,7 @@ lint.ignore = [
|
||||||
"ERA001", # Checks for commented-out Python code.
|
"ERA001", # Checks for commented-out Python code.
|
||||||
"FIX002", # Checks for "TODO" comments.
|
"FIX002", # Checks for "TODO" comments.
|
||||||
"PLR6301", # Checks for the presence of unused self parameter in methods definitions.
|
"PLR6301", # Checks for the presence of unused self parameter in methods definitions.
|
||||||
"ANN002", # Checks that function *args arguments have type annotations.
|
"RUF012", # Checks for mutable default values in class attributes.
|
||||||
"ANN003", # Checks that function **kwargs arguments have type annotations.
|
|
||||||
|
|
||||||
# Conflicting lint rules when using Ruff's formatter
|
# Conflicting lint rules when using Ruff's formatter
|
||||||
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,19 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<a href="{% url 'accounts:logout' %}">Logout</a>
|
<a href="{% url 'accounts:logout' %}">Logout</a>
|
||||||
|
<h2>Will get notifications to:</h2>
|
||||||
|
<ul>
|
||||||
|
{% for subscription in subscriptions %}
|
||||||
|
<li>
|
||||||
|
{% if subscription.game_id %}
|
||||||
|
<a href="{% url 'twitch:game_detail' subscription.game_id %}">{{ subscription.game.display_name }}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if subscription.organization_id %}
|
||||||
|
<a href="{% url 'twitch:organization_detail' subscription.organization_id %}">{{ subscription.organization.name }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% empty %}
|
||||||
|
<li>You have no subscriptions yet.</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
{# TODO: Link to organization #}
|
{# TODO: Link to organization #}
|
||||||
<a href="{% url 'twitch:org_detail' campaign.owner.id %}">{{ campaign.owner.name }}</a>
|
<a href="{% url 'twitch:organization_detail' campaign.owner.id %}">{{ campaign.owner.name }}</a>
|
||||||
</p>
|
</p>
|
||||||
{% if campaign.image_url %}
|
{% if campaign.image_url %}
|
||||||
<img height="70"
|
<img height="70"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
{% endblock title %}
|
{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{{ game.display_name }}</h1>
|
<h1>{{ game.display_name }}</h1>
|
||||||
|
{% if owner %}
|
||||||
|
<small><a href="{% url 'twitch:organization_detail' owner.id %}">{{ owner.name }}</a></small>
|
||||||
|
{% endif %}
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<form method="post"
|
<form method="post"
|
||||||
action="{% url 'twitch:subscribe_notifications' game_id=game.id %}">
|
action="{% url 'twitch:subscribe_notifications' game_id=game.id %}">
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{% for organization in orgs %}
|
{% for organization in orgs %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'twitch:org_detail' organization.id %}">{{ organization.name }}</a>
|
<a href="{% url 'twitch:organization_detail' organization.id %}">{{ organization.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@
|
||||||
id="found"
|
id="found"
|
||||||
name="notify_found"
|
name="notify_found"
|
||||||
{% if subscription and subscription.notify_found %}checked{% endif %} />
|
{% if subscription and subscription.notify_found %}checked{% endif %} />
|
||||||
<label for="found">🔔 Notify me when a drop for {{ organization.name }} appears on Twitch.</label>
|
<label for="found">🔔 Get notified as soon as a drop for {{ organization.name }} appears on Twitch.</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
id="live"
|
id="live"
|
||||||
name="notify_live"
|
name="notify_live"
|
||||||
{% if subscription and subscription.notify_live %}checked{% endif %} />
|
{% if subscription and subscription.notify_live %}checked{% endif %} />
|
||||||
<label for="live">🎮 Notify me when the drop is live and ready to be farmed.</label>
|
<label for="live">🎮 Get notified when the drop is live and ready to be farmed.</label>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Save preferences</button>
|
<button type="submit">Save preferences</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -216,4 +216,8 @@ class NotificationSubscription(models.Model):
|
||||||
]
|
]
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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"
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,6 @@ urlpatterns = [
|
||||||
path("games/<str:pk>/", views.GameDetailView.as_view(), name="game_detail"),
|
path("games/<str:pk>/", views.GameDetailView.as_view(), name="game_detail"),
|
||||||
path("games/<str:game_id>/subscribe/", views.subscribe_game_notifications, name="subscribe_notifications"),
|
path("games/<str:game_id>/subscribe/", views.subscribe_game_notifications, name="subscribe_notifications"),
|
||||||
path("organizations/", views.OrgListView.as_view(), name="org_list"),
|
path("organizations/", views.OrgListView.as_view(), name="org_list"),
|
||||||
path("organizations/<str:pk>/", views.OrgDetailView.as_view(), name="org_detail"),
|
path("organizations/<str:pk>/", views.OrgDetailView.as_view(), name="organization_detail"),
|
||||||
path("organizations/<str:org_id>/subscribe/", views.subscribe_org_notifications, name="subscribe_org_notifications"),
|
path("organizations/<str:org_id>/subscribe/", views.subscribe_org_notifications, name="subscribe_org_notifications"),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,21 @@ class OrgDetailView(DetailView):
|
||||||
Returns:
|
Returns:
|
||||||
dict: Context data.
|
dict: Context data.
|
||||||
"""
|
"""
|
||||||
organization: Organization = self.object
|
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
games = Game.objects.filter(drop_campaigns__owner=organization).distinct()
|
organization: Organization = self.object
|
||||||
context["games"] = games
|
|
||||||
|
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
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -290,6 +301,7 @@ class GameDetailView(DetailView):
|
||||||
"upcoming_campaigns": upcoming_campaigns,
|
"upcoming_campaigns": upcoming_campaigns,
|
||||||
"expired_campaigns": expired_campaigns,
|
"expired_campaigns": expired_campaigns,
|
||||||
"subscription": subscription,
|
"subscription": subscription,
|
||||||
|
"owner": active_campaigns[0].owner if active_campaigns else None,
|
||||||
"now": now,
|
"now": now,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -430,7 +442,7 @@ def subscribe_org_notifications(request: HttpRequest, org_id: str) -> HttpRespon
|
||||||
message = ""
|
message = ""
|
||||||
|
|
||||||
messages.success(request, 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.")
|
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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue