Major redesign #73
|
@ -87,3 +87,16 @@ def delete_device(request: HttpRequest, device_id: int) -> HttpResponse:
|
||||||
device = get_object_or_404(Device, id=device_id)
|
device = get_object_or_404(Device, id=device_id)
|
||||||
device.delete()
|
device.delete()
|
||||||
return redirect("list_sessions")
|
return redirect("list_sessions")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_device(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[str, Any] = {}
|
||||||
|
form = DeviceForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("index")
|
||||||
|
|
||||||
|
context["form"] = form
|
||||||
|
context["title"] = "Add New Device"
|
||||||
|
return render(request, "add.html", context)
|
||||||
|
|
|
@ -2,14 +2,14 @@ from typing import Any
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from common.utils import truncate_with_popover
|
from common.utils import truncate_with_popover
|
||||||
from games.forms import EditionForm
|
from games.forms import EditionForm
|
||||||
from games.models import Edition
|
from games.models import Edition, Game
|
||||||
from games.views import dateformat
|
from games.views import dateformat
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ def list_editions(request: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def edit_device(request: HttpRequest, edition_id: int = 0) -> HttpResponse:
|
def edit_edition(request: HttpRequest, edition_id: int = 0) -> HttpResponse:
|
||||||
edition = get_object_or_404(Edition, id=edition_id)
|
edition = get_object_or_404(Edition, id=edition_id)
|
||||||
form = EditionForm(request.POST or None, instance=edition)
|
form = EditionForm(request.POST or None, instance=edition)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
@ -107,3 +107,38 @@ def delete_edition(request: HttpRequest, edition_id: int) -> HttpResponse:
|
||||||
edition = get_object_or_404(Edition, id=edition_id)
|
edition = get_object_or_404(Edition, id=edition_id)
|
||||||
edition.delete()
|
edition.delete()
|
||||||
return redirect("list_editions")
|
return redirect("list_editions")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_edition(request: HttpRequest, game_id: int = 0) -> HttpResponse:
|
||||||
|
context: dict[str, Any] = {}
|
||||||
|
if request.method == "POST":
|
||||||
|
form = EditionForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
edition = form.save()
|
||||||
|
if "submit_and_redirect" in request.POST:
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse(
|
||||||
|
"add_purchase_for_edition", kwargs={"edition_id": edition.id}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return redirect("index")
|
||||||
|
else:
|
||||||
|
if game_id:
|
||||||
|
game = get_object_or_404(Game, id=game_id)
|
||||||
|
form = EditionForm(
|
||||||
|
initial={
|
||||||
|
"game": game,
|
||||||
|
"name": game.name,
|
||||||
|
"sort_name": game.sort_name,
|
||||||
|
"year_released": game.year_released,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
form = EditionForm()
|
||||||
|
|
||||||
|
context["form"] = form
|
||||||
|
context["title"] = "Add New Edition"
|
||||||
|
context["script_name"] = "add_edition.js"
|
||||||
|
return render(request, "add_edition.html", context)
|
||||||
|
|
|
@ -2,14 +2,16 @@ from typing import Any
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from common.utils import truncate_with_popover
|
from common.time import format_duration
|
||||||
from games.models import Game
|
from common.utils import safe_division, safe_getattr, truncate_with_popover
|
||||||
from games.views import dateformat
|
from games.forms import GameForm
|
||||||
|
from games.models import Game, Purchase, Session
|
||||||
|
from games.views import dateformat, use_custom_redirect
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -76,3 +78,116 @@ def list_games(request: HttpRequest) -> HttpResponse:
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return render(request, "list_purchases.html", context)
|
return render(request, "list_purchases.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_game(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[str, Any] = {}
|
||||||
|
form = GameForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
game = form.save()
|
||||||
|
if "submit_and_redirect" in request.POST:
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse("add_edition_for_game", kwargs={"game_id": game.id})
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return redirect("list_games")
|
||||||
|
|
||||||
|
context["form"] = form
|
||||||
|
context["title"] = "Add New Game"
|
||||||
|
context["script_name"] = "add_game.js"
|
||||||
|
return render(request, "add_game.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
||||||
|
game = get_object_or_404(Game, id=game_id)
|
||||||
|
game.delete()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@use_custom_redirect
|
||||||
|
def edit_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
||||||
|
context = {}
|
||||||
|
purchase = get_object_or_404(Game, id=game_id)
|
||||||
|
form = GameForm(request.POST or None, instance=purchase)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
context["title"] = "Edit Game"
|
||||||
|
context["form"] = form
|
||||||
|
return render(request, "add.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def view_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
||||||
|
game = Game.objects.get(id=game_id)
|
||||||
|
nongame_related_purchases_prefetch: Prefetch[Purchase] = Prefetch(
|
||||||
|
"related_purchases",
|
||||||
|
queryset=Purchase.objects.exclude(type=Purchase.GAME).order_by(
|
||||||
|
"date_purchased"
|
||||||
|
),
|
||||||
|
to_attr="nongame_related_purchases",
|
||||||
|
)
|
||||||
|
game_purchases_prefetch: Prefetch[Purchase] = Prefetch(
|
||||||
|
"purchase_set",
|
||||||
|
queryset=Purchase.objects.filter(type=Purchase.GAME).prefetch_related(
|
||||||
|
nongame_related_purchases_prefetch
|
||||||
|
),
|
||||||
|
to_attr="game_purchases",
|
||||||
|
)
|
||||||
|
editions = (
|
||||||
|
Edition.objects.filter(game=game)
|
||||||
|
.prefetch_related(game_purchases_prefetch)
|
||||||
|
.order_by("year_released")
|
||||||
|
)
|
||||||
|
|
||||||
|
sessions = Session.objects.prefetch_related("device").filter(
|
||||||
|
purchase__edition__game=game
|
||||||
|
)
|
||||||
|
session_count = sessions.count()
|
||||||
|
session_count_without_manual = (
|
||||||
|
Session.objects.without_manual().filter(purchase__edition__game=game).count()
|
||||||
|
)
|
||||||
|
|
||||||
|
if sessions:
|
||||||
|
playrange_start = sessions.earliest().timestamp_start.strftime("%b %Y")
|
||||||
|
latest_session = sessions.latest()
|
||||||
|
playrange_end = latest_session.timestamp_start.strftime("%b %Y")
|
||||||
|
|
||||||
|
playrange = (
|
||||||
|
playrange_start
|
||||||
|
if playrange_start == playrange_end
|
||||||
|
else f"{playrange_start} — {playrange_end}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
playrange = "N/A"
|
||||||
|
latest_session = None
|
||||||
|
|
||||||
|
total_hours = float(format_duration(sessions.total_duration_unformatted(), "%2.1H"))
|
||||||
|
total_hours_without_manual = float(
|
||||||
|
format_duration(sessions.calculated_duration_unformatted(), "%2.1H")
|
||||||
|
)
|
||||||
|
context = {
|
||||||
|
"edition_count": editions.count(),
|
||||||
|
"editions": editions,
|
||||||
|
"game": game,
|
||||||
|
"playrange": playrange,
|
||||||
|
"purchase_count": Purchase.objects.filter(edition__game=game).count(),
|
||||||
|
"session_average_without_manual": round(
|
||||||
|
safe_division(
|
||||||
|
total_hours_without_manual, int(session_count_without_manual)
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
"session_count": session_count,
|
||||||
|
"sessions_with_notes_count": sessions.exclude(note="").count(),
|
||||||
|
"sessions": sessions.order_by("-timestamp_start"),
|
||||||
|
"title": f"Game Overview - {game.name}",
|
||||||
|
"hours_sum": total_hours,
|
||||||
|
"latest_session_id": safe_getattr(latest_session, "pk"),
|
||||||
|
}
|
||||||
|
|
||||||
|
request.session["return_path"] = request.path
|
||||||
|
return render(request, "view_game.html", context)
|
||||||
|
|
|
@ -7,8 +7,9 @@ from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from games.forms import PlatformForm
|
||||||
from games.models import Platform
|
from games.models import Platform
|
||||||
from games.views import dateformat
|
from games.views import dateformat, use_custom_redirect
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -78,3 +79,30 @@ def delete_platform(request: HttpRequest, platform_id: int) -> HttpResponse:
|
||||||
platform = get_object_or_404(Platform, id=platform_id)
|
platform = get_object_or_404(Platform, id=platform_id)
|
||||||
platform.delete()
|
platform.delete()
|
||||||
return redirect("list_platforms")
|
return redirect("list_platforms")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@use_custom_redirect
|
||||||
|
def edit_platform(request: HttpRequest, platform_id: int) -> HttpResponse:
|
||||||
|
context = {}
|
||||||
|
platform = get_object_or_404(Platform, id=platform_id)
|
||||||
|
form = PlatformForm(request.POST or None, instance=platform)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("list_platforms")
|
||||||
|
context["title"] = "Edit Platform"
|
||||||
|
context["form"] = form
|
||||||
|
return render(request, "add.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_platform(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[str, Any] = {}
|
||||||
|
form = PlatformForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("index")
|
||||||
|
|
||||||
|
context["form"] = form
|
||||||
|
context["title"] = "Add New Platform"
|
||||||
|
return render(request, "add.html", context)
|
||||||
|
|
|
@ -2,14 +2,21 @@ from typing import Any
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import (
|
||||||
from django.shortcuts import render
|
HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
HttpResponseBadRequest,
|
||||||
|
HttpResponseRedirect,
|
||||||
|
)
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from common.utils import truncate_with_popover
|
from common.utils import truncate_with_popover
|
||||||
from games.models import Purchase
|
from games.forms import PurchaseForm
|
||||||
from games.views import dateformat
|
from games.models import Edition, Purchase
|
||||||
|
from games.views import dateformat, use_custom_redirect
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -98,3 +105,73 @@ def list_purchases(request: HttpRequest) -> HttpResponse:
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return render(request, "list_purchases.html", context)
|
return render(request, "list_purchases.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_purchase(request: HttpRequest, edition_id: int = 0) -> HttpResponse:
|
||||||
|
context: dict[str, Any] = {}
|
||||||
|
initial = {"date_purchased": timezone.now()}
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = PurchaseForm(request.POST or None, initial=initial)
|
||||||
|
if form.is_valid():
|
||||||
|
purchase = form.save()
|
||||||
|
if "submit_and_redirect" in request.POST:
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse(
|
||||||
|
"add_session_for_purchase", kwargs={"purchase_id": purchase.id}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return redirect("list_purchases")
|
||||||
|
else:
|
||||||
|
if edition_id:
|
||||||
|
edition = Edition.objects.get(id=edition_id)
|
||||||
|
form = PurchaseForm(
|
||||||
|
initial={
|
||||||
|
**initial,
|
||||||
|
"edition": edition,
|
||||||
|
"platform": edition.platform,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
form = PurchaseForm(initial=initial)
|
||||||
|
|
||||||
|
context["form"] = form
|
||||||
|
context["title"] = "Add New Purchase"
|
||||||
|
context["script_name"] = "add_purchase.js"
|
||||||
|
return render(request, "add_purchase.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@use_custom_redirect
|
||||||
|
def edit_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
|
||||||
|
context = {}
|
||||||
|
purchase = get_object_or_404(Purchase, id=purchase_id)
|
||||||
|
form = PurchaseForm(request.POST or None, instance=purchase)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
context["title"] = "Edit Purchase"
|
||||||
|
context["form"] = form
|
||||||
|
context["purchase_id"] = str(purchase_id)
|
||||||
|
context["script_name"] = "add_purchase.js"
|
||||||
|
return render(request, "add_purchase.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
|
||||||
|
purchase = get_object_or_404(Purchase, id=purchase_id)
|
||||||
|
purchase.delete()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
|
||||||
|
|
||||||
|
def related_purchase_by_edition(request: HttpRequest) -> HttpResponse:
|
||||||
|
edition_id = request.GET.get("edition")
|
||||||
|
if not edition_id:
|
||||||
|
return HttpResponseBadRequest("Invalid edition_id")
|
||||||
|
form = PurchaseForm()
|
||||||
|
form.fields["related_purchase"].queryset = Purchase.objects.filter(
|
||||||
|
edition_id=edition_id, type=Purchase.GAME
|
||||||
|
).order_by("edition__sort_name")
|
||||||
|
return render(request, "partials/related_purchase_field.html", {"form": form})
|
||||||
|
|
|
@ -3,19 +3,22 @@ from typing import Any
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from common.time import format_duration
|
from common.time import format_duration
|
||||||
from common.utils import truncate_with_popover
|
from common.utils import truncate_with_popover
|
||||||
from games.models import Session
|
from games.forms import SessionForm
|
||||||
|
from games.models import Purchase, Session
|
||||||
from games.views import (
|
from games.views import (
|
||||||
dateformat,
|
dateformat,
|
||||||
datetimeformat,
|
datetimeformat,
|
||||||
durationformat,
|
durationformat,
|
||||||
durationformat_manual,
|
durationformat_manual,
|
||||||
timeformat,
|
timeformat,
|
||||||
|
use_custom_redirect,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,3 +94,98 @@ def list_sessions(request: HttpRequest) -> HttpResponse:
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return render(request, "list_purchases.html", context)
|
return render(request, "list_purchases.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_session(request: HttpRequest, purchase_id: int = 0) -> HttpResponse:
|
||||||
|
context = {}
|
||||||
|
initial: dict[str, Any] = {"timestamp_start": timezone.now()}
|
||||||
|
|
||||||
|
last = Session.objects.last()
|
||||||
|
if last != None:
|
||||||
|
initial["purchase"] = last.purchase
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = SessionForm(request.POST or None, initial=initial)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
else:
|
||||||
|
if purchase_id:
|
||||||
|
purchase = Purchase.objects.get(id=purchase_id)
|
||||||
|
form = SessionForm(
|
||||||
|
initial={
|
||||||
|
**initial,
|
||||||
|
"purchase": purchase,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
form = SessionForm(initial=initial)
|
||||||
|
|
||||||
|
context["title"] = "Add New Session"
|
||||||
|
context["form"] = form
|
||||||
|
return render(request, "add_session.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@use_custom_redirect
|
||||||
|
def edit_session(request: HttpRequest, session_id: int) -> HttpResponse:
|
||||||
|
context = {}
|
||||||
|
session = get_object_or_404(Session, id=session_id)
|
||||||
|
form = SessionForm(request.POST or None, instance=session)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
context["title"] = "Edit Session"
|
||||||
|
context["form"] = form
|
||||||
|
return render(request, "add_session.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def clone_session_by_id(session_id: int) -> Session:
|
||||||
|
session = get_object_or_404(Session, id=session_id)
|
||||||
|
clone = session
|
||||||
|
clone.pk = None
|
||||||
|
clone.timestamp_start = timezone.now()
|
||||||
|
clone.timestamp_end = None
|
||||||
|
clone.note = ""
|
||||||
|
clone.save()
|
||||||
|
return clone
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@use_custom_redirect
|
||||||
|
def new_session_from_existing_session(
|
||||||
|
request: HttpRequest, session_id: int, template: str = ""
|
||||||
|
) -> HttpResponse:
|
||||||
|
session = clone_session_by_id(session_id)
|
||||||
|
if request.htmx:
|
||||||
|
context = {
|
||||||
|
"session": session,
|
||||||
|
"session_count": int(request.GET.get("session_count", 0)) + 1,
|
||||||
|
}
|
||||||
|
return render(request, template, context)
|
||||||
|
return redirect("list_sessions")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@use_custom_redirect
|
||||||
|
def end_session(
|
||||||
|
request: HttpRequest, session_id: int, template: str = ""
|
||||||
|
) -> HttpResponse:
|
||||||
|
session = get_object_or_404(Session, id=session_id)
|
||||||
|
session.timestamp_end = timezone.now()
|
||||||
|
session.save()
|
||||||
|
if request.htmx:
|
||||||
|
context = {
|
||||||
|
"session": session,
|
||||||
|
"session_count": request.GET.get("session_count", 0),
|
||||||
|
}
|
||||||
|
return render(request, template, context)
|
||||||
|
return redirect("list_sessions")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete_session(request: HttpRequest, session_id: int = 0) -> HttpResponse:
|
||||||
|
session = get_object_or_404(Session, id=session_id)
|
||||||
|
session.delete()
|
||||||
|
return redirect("list_sessions")
|
||||||
|
|
|
@ -12,43 +12,53 @@ from games import (
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
path("device/add", views.add_device, name="add_device"),
|
path("device/add", deviceviews.add_device, name="add_device"),
|
||||||
path(
|
path(
|
||||||
"device/delete/<int:device_id>", deviceviews.delete_device, name="delete_device"
|
"device/delete/<int:device_id>", deviceviews.delete_device, name="delete_device"
|
||||||
),
|
),
|
||||||
path("device/edit/<int:device_id>", deviceviews.edit_device, name="edit_device"),
|
path("device/edit/<int:device_id>", deviceviews.edit_device, name="edit_device"),
|
||||||
path("device/list", deviceviews.list_devices, name="list_devices"),
|
path("device/list", deviceviews.list_devices, name="list_devices"),
|
||||||
path("edition/add", views.add_edition, name="add_edition"),
|
path("edition/add", editionviews.add_edition, name="add_edition"),
|
||||||
path(
|
path(
|
||||||
"edition/add/for-game/<int:game_id>",
|
"edition/add/for-game/<int:game_id>",
|
||||||
views.add_edition,
|
editionviews.add_edition,
|
||||||
name="add_edition_for_game",
|
name="add_edition_for_game",
|
||||||
),
|
),
|
||||||
path("edition/<int:edition_id>/edit", views.edit_edition, name="edit_edition"),
|
path(
|
||||||
|
"edition/<int:edition_id>/edit", editionviews.edit_edition, name="edit_edition"
|
||||||
|
),
|
||||||
path("edition/list", editionviews.list_editions, name="list_editions"),
|
path("edition/list", editionviews.list_editions, name="list_editions"),
|
||||||
path(
|
path(
|
||||||
"edition/<int:edition_id>/delete",
|
"edition/<int:edition_id>/delete",
|
||||||
editionviews.delete_edition,
|
editionviews.delete_edition,
|
||||||
name="delete_edition",
|
name="delete_edition",
|
||||||
),
|
),
|
||||||
path("game/add", views.add_game, name="add_game"),
|
path("game/add", gameviews.add_game, name="add_game"),
|
||||||
path("game/<int:game_id>/edit", views.edit_game, name="edit_game"),
|
path("game/<int:game_id>/edit", gameviews.edit_game, name="edit_game"),
|
||||||
path("game/<int:game_id>/view", views.view_game, name="view_game"),
|
path("game/<int:game_id>/view", gameviews.view_game, name="view_game"),
|
||||||
path("game/<int:game_id>/delete", views.delete_game, name="delete_game"),
|
path("game/<int:game_id>/delete", gameviews.delete_game, name="delete_game"),
|
||||||
path("game/list", gameviews.list_games, name="list_games"),
|
path("game/list", gameviews.list_games, name="list_games"),
|
||||||
path("platform/add", views.add_platform, name="add_platform"),
|
path("platform/add", platformviews.add_platform, name="add_platform"),
|
||||||
path("platform/<int:platform_id>/edit", views.edit_platform, name="edit_platform"),
|
path(
|
||||||
|
"platform/<int:platform_id>/edit",
|
||||||
|
platformviews.edit_platform,
|
||||||
|
name="edit_platform",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"platform/<int:platform_id>/delete",
|
"platform/<int:platform_id>/delete",
|
||||||
platformviews.delete_platform,
|
platformviews.delete_platform,
|
||||||
name="delete_platform",
|
name="delete_platform",
|
||||||
),
|
),
|
||||||
path("platform/list", platformviews.list_platforms, name="list_platforms"),
|
path("platform/list", platformviews.list_platforms, name="list_platforms"),
|
||||||
path("purchase/add", views.add_purchase, name="add_purchase"),
|
path("purchase/add", purchaseviews.add_purchase, name="add_purchase"),
|
||||||
path("purchase/<int:purchase_id>/edit", views.edit_purchase, name="edit_purchase"),
|
path(
|
||||||
|
"purchase/<int:purchase_id>/edit",
|
||||||
|
purchaseviews.edit_purchase,
|
||||||
|
name="edit_purchase",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"purchase/<int:purchase_id>/delete",
|
"purchase/<int:purchase_id>/delete",
|
||||||
views.delete_purchase,
|
purchaseviews.delete_purchase,
|
||||||
name="delete_purchase",
|
name="delete_purchase",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
|
@ -58,78 +68,80 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"purchase/related-purchase-by-edition",
|
"purchase/related-purchase-by-edition",
|
||||||
views.related_purchase_by_edition,
|
purchaseviews.related_purchase_by_edition,
|
||||||
name="related_purchase_by_edition",
|
name="related_purchase_by_edition",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"purchase/add/for-edition/<int:edition_id>",
|
"purchase/add/for-edition/<int:edition_id>",
|
||||||
views.add_purchase,
|
purchaseviews.add_purchase,
|
||||||
name="add_purchase_for_edition",
|
name="add_purchase_for_edition",
|
||||||
),
|
),
|
||||||
path("session/add", views.add_session, name="add_session"),
|
path("session/add", sessionviews.add_session, name="add_session"),
|
||||||
path(
|
path(
|
||||||
"session/add/for-purchase/<int:purchase_id>",
|
"session/add/for-purchase/<int:purchase_id>",
|
||||||
views.add_session,
|
sessionviews.add_session,
|
||||||
name="add_session_for_purchase",
|
name="add_session_for_purchase",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/add/from-game/<int:session_id>",
|
"session/add/from-game/<int:session_id>",
|
||||||
views.new_session_from_existing_session,
|
sessionviews.new_session_from_existing_session,
|
||||||
{"template": "view_game.html#session-info"},
|
{"template": "view_game.html#session-info"},
|
||||||
name="view_game_start_session_from_session",
|
name="view_game_start_session_from_session",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/add/from-list/<int:session_id>",
|
"session/add/from-list/<int:session_id>",
|
||||||
views.new_session_from_existing_session,
|
sessionviews.new_session_from_existing_session,
|
||||||
{"template": "list_sessions.html#session-row"},
|
{"template": "list_sessions.html#session-row"},
|
||||||
name="list_sessions_start_session_from_session",
|
name="list_sessions_start_session_from_session",
|
||||||
),
|
),
|
||||||
path("session/<int:session_id>/edit", views.edit_session, name="edit_session"),
|
path(
|
||||||
|
"session/<int:session_id>/edit", sessionviews.edit_session, name="edit_session"
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"session/<int:session_id>/delete",
|
"session/<int:session_id>/delete",
|
||||||
views.delete_session,
|
sessionviews.delete_session,
|
||||||
name="delete_session",
|
name="delete_session",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/end/from-game/<int:session_id>",
|
"session/end/from-game/<int:session_id>",
|
||||||
views.end_session,
|
sessionviews.end_session,
|
||||||
{"template": "view_game.html#session-info"},
|
{"template": "view_game.html#session-info"},
|
||||||
name="view_game_end_session",
|
name="view_game_end_session",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/end/from-list/<int:session_id>",
|
"session/end/from-list/<int:session_id>",
|
||||||
views.end_session,
|
sessionviews.end_session,
|
||||||
{"template": "list_sessions.html#session-row"},
|
{"template": "list_sessions.html#session-row"},
|
||||||
name="list_sessions_end_session",
|
name="list_sessions_end_session",
|
||||||
),
|
),
|
||||||
path("session/list", sessionviews.list_sessions, name="list_sessions"),
|
path("session/list", sessionviews.list_sessions, name="list_sessions"),
|
||||||
path(
|
path(
|
||||||
"session/list/by-purchase/<int:purchase_id>",
|
"session/list/by-purchase/<int:purchase_id>",
|
||||||
views.list_sessions,
|
sessionviews.list_sessions,
|
||||||
{"filter": "purchase"},
|
{"filter": "purchase"},
|
||||||
name="list_sessions_by_purchase",
|
name="list_sessions_by_purchase",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/list/by-platform/<int:platform_id>",
|
"session/list/by-platform/<int:platform_id>",
|
||||||
views.list_sessions,
|
sessionviews.list_sessions,
|
||||||
{"filter": "platform"},
|
{"filter": "platform"},
|
||||||
name="list_sessions_by_platform",
|
name="list_sessions_by_platform",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/list/by-game/<int:game_id>",
|
"session/list/by-game/<int:game_id>",
|
||||||
views.list_sessions,
|
sessionviews.list_sessions,
|
||||||
{"filter": "game"},
|
{"filter": "game"},
|
||||||
name="list_sessions_by_game",
|
name="list_sessions_by_game",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/list/by-edition/<int:edition_id>",
|
"session/list/by-edition/<int:edition_id>",
|
||||||
views.list_sessions,
|
sessionviews.list_sessions,
|
||||||
{"filter": "edition"},
|
{"filter": "edition"},
|
||||||
name="list_sessions_by_edition",
|
name="list_sessions_by_edition",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"session/list/by-ownership/<str:ownership_type>",
|
"session/list/by-ownership/<str:ownership_type>",
|
||||||
views.list_sessions,
|
sessionviews.list_sessions,
|
||||||
{"filter": "ownership_type"},
|
{"filter": "ownership_type"},
|
||||||
name="list_sessions_by_ownership_type",
|
name="list_sessions_by_ownership_type",
|
||||||
),
|
),
|
||||||
|
|
434
games/views.py
434
games/views.py
|
@ -1,30 +1,17 @@
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.db.models import Avg, Count, ExpressionWrapper, F, Prefetch, Q, Sum, fields
|
from django.db.models import Avg, Count, ExpressionWrapper, F, Q, Sum, fields
|
||||||
from django.db.models.functions import TruncDate, TruncMonth
|
from django.db.models.functions import TruncDate, TruncMonth
|
||||||
from django.db.models.manager import BaseManager
|
from django.db.models.manager import BaseManager
|
||||||
from django.http import (
|
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||||
HttpRequest,
|
from django.shortcuts import redirect, render
|
||||||
HttpResponse,
|
|
||||||
HttpResponseBadRequest,
|
|
||||||
HttpResponseRedirect,
|
|
||||||
)
|
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from common.time import format_duration
|
from common.time import format_duration
|
||||||
from common.utils import safe_division, safe_getattr
|
from common.utils import safe_division
|
||||||
|
|
||||||
from .forms import (
|
|
||||||
DeviceForm,
|
|
||||||
EditionForm,
|
|
||||||
GameForm,
|
|
||||||
PlatformForm,
|
|
||||||
PurchaseForm,
|
|
||||||
SessionForm,
|
|
||||||
)
|
|
||||||
from .models import Edition, Game, Platform, Purchase, Session
|
from .models import Edition, Game, Platform, Purchase, Session
|
||||||
|
|
||||||
dateformat: str = "%d/%m/%Y"
|
dateformat: str = "%d/%m/%Y"
|
||||||
|
@ -49,37 +36,6 @@ def stats_dropdown_year_range(request: HttpRequest) -> dict[str, range]:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_session(request: HttpRequest, purchase_id: int = 0) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
initial: dict[str, Any] = {"timestamp_start": timezone.now()}
|
|
||||||
|
|
||||||
last = Session.objects.last()
|
|
||||||
if last != None:
|
|
||||||
initial["purchase"] = last.purchase
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = SessionForm(request.POST or None, initial=initial)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
else:
|
|
||||||
if purchase_id:
|
|
||||||
purchase = Purchase.objects.get(id=purchase_id)
|
|
||||||
form = SessionForm(
|
|
||||||
initial={
|
|
||||||
**initial,
|
|
||||||
"purchase": purchase,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
form = SessionForm(initial=initial)
|
|
||||||
|
|
||||||
context["title"] = "Add New Session"
|
|
||||||
context["form"] = form
|
|
||||||
return render(request, "add_session.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
def use_custom_redirect(
|
def use_custom_redirect(
|
||||||
func: Callable[..., HttpResponse],
|
func: Callable[..., HttpResponse],
|
||||||
) -> Callable[..., HttpResponse]:
|
) -> Callable[..., HttpResponse]:
|
||||||
|
@ -98,265 +54,6 @@ def use_custom_redirect(
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def edit_session(request: HttpRequest, session_id: int) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
session = get_object_or_404(Session, id=session_id)
|
|
||||||
form = SessionForm(request.POST or None, instance=session)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
context["title"] = "Edit Session"
|
|
||||||
context["form"] = form
|
|
||||||
return render(request, "add_session.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def edit_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
purchase = get_object_or_404(Purchase, id=purchase_id)
|
|
||||||
form = PurchaseForm(request.POST or None, instance=purchase)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
context["title"] = "Edit Purchase"
|
|
||||||
context["form"] = form
|
|
||||||
context["purchase_id"] = str(purchase_id)
|
|
||||||
context["script_name"] = "add_purchase.js"
|
|
||||||
return render(request, "add_purchase.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def edit_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
purchase = get_object_or_404(Game, id=game_id)
|
|
||||||
form = GameForm(request.POST or None, instance=purchase)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
context["title"] = "Edit Game"
|
|
||||||
context["form"] = form
|
|
||||||
return render(request, "add.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def delete_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
|
||||||
game = get_object_or_404(Game, id=game_id)
|
|
||||||
game.delete()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def view_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
|
||||||
game = Game.objects.get(id=game_id)
|
|
||||||
nongame_related_purchases_prefetch: Prefetch[Purchase] = Prefetch(
|
|
||||||
"related_purchases",
|
|
||||||
queryset=Purchase.objects.exclude(type=Purchase.GAME).order_by(
|
|
||||||
"date_purchased"
|
|
||||||
),
|
|
||||||
to_attr="nongame_related_purchases",
|
|
||||||
)
|
|
||||||
game_purchases_prefetch: Prefetch[Purchase] = Prefetch(
|
|
||||||
"purchase_set",
|
|
||||||
queryset=Purchase.objects.filter(type=Purchase.GAME).prefetch_related(
|
|
||||||
nongame_related_purchases_prefetch
|
|
||||||
),
|
|
||||||
to_attr="game_purchases",
|
|
||||||
)
|
|
||||||
editions = (
|
|
||||||
Edition.objects.filter(game=game)
|
|
||||||
.prefetch_related(game_purchases_prefetch)
|
|
||||||
.order_by("year_released")
|
|
||||||
)
|
|
||||||
|
|
||||||
sessions = Session.objects.prefetch_related("device").filter(
|
|
||||||
purchase__edition__game=game
|
|
||||||
)
|
|
||||||
session_count = sessions.count()
|
|
||||||
session_count_without_manual = (
|
|
||||||
Session.objects.without_manual().filter(purchase__edition__game=game).count()
|
|
||||||
)
|
|
||||||
|
|
||||||
if sessions:
|
|
||||||
playrange_start = sessions.earliest().timestamp_start.strftime("%b %Y")
|
|
||||||
latest_session = sessions.latest()
|
|
||||||
playrange_end = latest_session.timestamp_start.strftime("%b %Y")
|
|
||||||
|
|
||||||
playrange = (
|
|
||||||
playrange_start
|
|
||||||
if playrange_start == playrange_end
|
|
||||||
else f"{playrange_start} — {playrange_end}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
playrange = "N/A"
|
|
||||||
latest_session = None
|
|
||||||
|
|
||||||
total_hours = float(format_duration(sessions.total_duration_unformatted(), "%2.1H"))
|
|
||||||
total_hours_without_manual = float(
|
|
||||||
format_duration(sessions.calculated_duration_unformatted(), "%2.1H")
|
|
||||||
)
|
|
||||||
context = {
|
|
||||||
"edition_count": editions.count(),
|
|
||||||
"editions": editions,
|
|
||||||
"game": game,
|
|
||||||
"playrange": playrange,
|
|
||||||
"purchase_count": Purchase.objects.filter(edition__game=game).count(),
|
|
||||||
"session_average_without_manual": round(
|
|
||||||
safe_division(
|
|
||||||
total_hours_without_manual, int(session_count_without_manual)
|
|
||||||
),
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
"session_count": session_count,
|
|
||||||
"sessions_with_notes_count": sessions.exclude(note="").count(),
|
|
||||||
"sessions": sessions.order_by("-timestamp_start"),
|
|
||||||
"title": f"Game Overview - {game.name}",
|
|
||||||
"hours_sum": total_hours,
|
|
||||||
"latest_session_id": safe_getattr(latest_session, "pk"),
|
|
||||||
}
|
|
||||||
|
|
||||||
request.session["return_path"] = request.path
|
|
||||||
return render(request, "view_game.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def edit_platform(request: HttpRequest, platform_id: int) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
platform = get_object_or_404(Platform, id=platform_id)
|
|
||||||
form = PlatformForm(request.POST or None, instance=platform)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("list_platforms")
|
|
||||||
context["title"] = "Edit Platform"
|
|
||||||
context["form"] = form
|
|
||||||
return render(request, "add.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def edit_edition(request: HttpRequest, edition_id: int) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
edition = get_object_or_404(Edition, id=edition_id)
|
|
||||||
form = EditionForm(request.POST or None, instance=edition)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
context["title"] = "Edit Edition"
|
|
||||||
context["form"] = form
|
|
||||||
return render(request, "add.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
def related_purchase_by_edition(request: HttpRequest) -> HttpResponse:
|
|
||||||
edition_id = request.GET.get("edition")
|
|
||||||
if not edition_id:
|
|
||||||
return HttpResponseBadRequest("Invalid edition_id")
|
|
||||||
form = PurchaseForm()
|
|
||||||
form.fields["related_purchase"].queryset = Purchase.objects.filter(
|
|
||||||
edition_id=edition_id, type=Purchase.GAME
|
|
||||||
).order_by("edition__sort_name")
|
|
||||||
return render(request, "partials/related_purchase_field.html", {"form": form})
|
|
||||||
|
|
||||||
|
|
||||||
def clone_session_by_id(session_id: int) -> Session:
|
|
||||||
session = get_object_or_404(Session, id=session_id)
|
|
||||||
clone = session
|
|
||||||
clone.pk = None
|
|
||||||
clone.timestamp_start = timezone.now()
|
|
||||||
clone.timestamp_end = None
|
|
||||||
clone.note = ""
|
|
||||||
clone.save()
|
|
||||||
return clone
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def new_session_from_existing_session(
|
|
||||||
request: HttpRequest, session_id: int, template: str = ""
|
|
||||||
) -> HttpResponse:
|
|
||||||
session = clone_session_by_id(session_id)
|
|
||||||
if request.htmx:
|
|
||||||
context = {
|
|
||||||
"session": session,
|
|
||||||
"session_count": int(request.GET.get("session_count", 0)) + 1,
|
|
||||||
}
|
|
||||||
return render(request, template, context)
|
|
||||||
return redirect("list_sessions")
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@use_custom_redirect
|
|
||||||
def end_session(
|
|
||||||
request: HttpRequest, session_id: int, template: str = ""
|
|
||||||
) -> HttpResponse:
|
|
||||||
session = get_object_or_404(Session, id=session_id)
|
|
||||||
session.timestamp_end = timezone.now()
|
|
||||||
session.save()
|
|
||||||
if request.htmx:
|
|
||||||
context = {
|
|
||||||
"session": session,
|
|
||||||
"session_count": request.GET.get("session_count", 0),
|
|
||||||
}
|
|
||||||
return render(request, template, context)
|
|
||||||
return redirect("list_sessions")
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def delete_session(request: HttpRequest, session_id: int = 0) -> HttpResponse:
|
|
||||||
session = get_object_or_404(Session, id=session_id)
|
|
||||||
session.delete()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def list_sessions(
|
|
||||||
request: HttpRequest,
|
|
||||||
filter: str = "",
|
|
||||||
purchase_id: int = 0,
|
|
||||||
platform_id: int = 0,
|
|
||||||
game_id: int = 0,
|
|
||||||
edition_id: int = 0,
|
|
||||||
ownership_type: str = "",
|
|
||||||
) -> HttpResponse:
|
|
||||||
context = {}
|
|
||||||
context["title"] = "Sessions"
|
|
||||||
|
|
||||||
all_sessions = Session.objects.prefetch_related(
|
|
||||||
"purchase", "purchase__edition", "purchase__edition__game"
|
|
||||||
).order_by("-timestamp_start")
|
|
||||||
|
|
||||||
if filter == "purchase":
|
|
||||||
dataset = all_sessions.filter(purchase=purchase_id)
|
|
||||||
context["purchase"] = Purchase.objects.get(id=purchase_id)
|
|
||||||
elif filter == "platform":
|
|
||||||
dataset = all_sessions.filter(purchase__platform=platform_id)
|
|
||||||
context["platform"] = Platform.objects.get(id=platform_id)
|
|
||||||
elif filter == "edition":
|
|
||||||
dataset = all_sessions.filter(purchase__edition=edition_id)
|
|
||||||
context["edition"] = Edition.objects.get(id=edition_id)
|
|
||||||
elif filter == "game":
|
|
||||||
dataset = all_sessions.filter(purchase__edition__game=game_id)
|
|
||||||
context["game"] = Game.objects.get(id=game_id)
|
|
||||||
elif filter == "ownership_type":
|
|
||||||
dataset = all_sessions.filter(purchase__ownership_type=ownership_type)
|
|
||||||
context["ownership_type"] = dict(Purchase.OWNERSHIP_TYPES)[ownership_type]
|
|
||||||
context["title"] = "This year"
|
|
||||||
else:
|
|
||||||
dataset = all_sessions
|
|
||||||
|
|
||||||
context = {
|
|
||||||
**context,
|
|
||||||
"dataset": dataset,
|
|
||||||
"dataset_count": dataset.count(),
|
|
||||||
"last": Session.objects.prefetch_related("purchase__platform").latest(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return render(request, "list_sessions.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def stats_alltime(request: HttpRequest) -> HttpResponse:
|
def stats_alltime(request: HttpRequest) -> HttpResponse:
|
||||||
year = "Alltime"
|
year = "Alltime"
|
||||||
|
@ -815,129 +512,6 @@ def stats(request: HttpRequest, year: int = 0) -> HttpResponse:
|
||||||
return render(request, "stats.html", context)
|
return render(request, "stats.html", context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def delete_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
|
|
||||||
purchase = get_object_or_404(Purchase, id=purchase_id)
|
|
||||||
purchase.delete()
|
|
||||||
return redirect("list_sessions")
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_purchase(request: HttpRequest, edition_id: int = 0) -> HttpResponse:
|
|
||||||
context: dict[str, Any] = {}
|
|
||||||
initial = {"date_purchased": timezone.now()}
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = PurchaseForm(request.POST or None, initial=initial)
|
|
||||||
if form.is_valid():
|
|
||||||
purchase = form.save()
|
|
||||||
if "submit_and_redirect" in request.POST:
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse(
|
|
||||||
"add_session_for_purchase", kwargs={"purchase_id": purchase.id}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return redirect("index")
|
|
||||||
else:
|
|
||||||
if edition_id:
|
|
||||||
edition = Edition.objects.get(id=edition_id)
|
|
||||||
form = PurchaseForm(
|
|
||||||
initial={
|
|
||||||
**initial,
|
|
||||||
"edition": edition,
|
|
||||||
"platform": edition.platform,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
form = PurchaseForm(initial=initial)
|
|
||||||
|
|
||||||
context["form"] = form
|
|
||||||
context["title"] = "Add New Purchase"
|
|
||||||
context["script_name"] = "add_purchase.js"
|
|
||||||
return render(request, "add_purchase.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_game(request: HttpRequest) -> HttpResponse:
|
|
||||||
context: dict[str, Any] = {}
|
|
||||||
form = GameForm(request.POST or None)
|
|
||||||
if form.is_valid():
|
|
||||||
game = form.save()
|
|
||||||
if "submit_and_redirect" in request.POST:
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse("add_edition_for_game", kwargs={"game_id": game.id})
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return redirect("index")
|
|
||||||
|
|
||||||
context["form"] = form
|
|
||||||
context["title"] = "Add New Game"
|
|
||||||
context["script_name"] = "add_game.js"
|
|
||||||
return render(request, "add_game.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_edition(request: HttpRequest, game_id: int = 0) -> HttpResponse:
|
|
||||||
context: dict[str, Any] = {}
|
|
||||||
if request.method == "POST":
|
|
||||||
form = EditionForm(request.POST or None)
|
|
||||||
if form.is_valid():
|
|
||||||
edition = form.save()
|
|
||||||
if "submit_and_redirect" in request.POST:
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse(
|
|
||||||
"add_purchase_for_edition", kwargs={"edition_id": edition.id}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return redirect("index")
|
|
||||||
else:
|
|
||||||
if game_id:
|
|
||||||
game = get_object_or_404(Game, id=game_id)
|
|
||||||
form = EditionForm(
|
|
||||||
initial={
|
|
||||||
"game": game,
|
|
||||||
"name": game.name,
|
|
||||||
"sort_name": game.sort_name,
|
|
||||||
"year_released": game.year_released,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
form = EditionForm()
|
|
||||||
|
|
||||||
context["form"] = form
|
|
||||||
context["title"] = "Add New Edition"
|
|
||||||
context["script_name"] = "add_edition.js"
|
|
||||||
return render(request, "add_edition.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_platform(request: HttpRequest) -> HttpResponse:
|
|
||||||
context: dict[str, Any] = {}
|
|
||||||
form = PlatformForm(request.POST or None)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("index")
|
|
||||||
|
|
||||||
context["form"] = form
|
|
||||||
context["title"] = "Add New Platform"
|
|
||||||
return render(request, "add.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_device(request: HttpRequest) -> HttpResponse:
|
|
||||||
context: dict[str, Any] = {}
|
|
||||||
form = DeviceForm(request.POST or None)
|
|
||||||
if form.is_valid():
|
|
||||||
form.save()
|
|
||||||
return redirect("index")
|
|
||||||
|
|
||||||
context["form"] = form
|
|
||||||
context["title"] = "Add New Device"
|
|
||||||
return render(request, "add.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def index(request: HttpRequest) -> HttpResponse:
|
def index(request: HttpRequest) -> HttpResponse:
|
||||||
return redirect("list_sessions")
|
return redirect("list_sessions")
|
||||||
|
|
Loading…
Reference in New Issue