Compare commits

..

No commits in common. "118612eceab9768937fedeb94bcbdf7b1bbae963" and "729e1d939b8a8580e554cbb3cb0acb8415a0d8a6" have entirely different histories.

6 changed files with 60 additions and 130 deletions

View File

@ -1,8 +1,3 @@
## Unreleased
## Improved
* game overview: improve how editions and purchases are displayed
## 1.5.1 / 2023-11-14 21:10+01:00 ## 1.5.1 / 2023-11-14 21:10+01:00
## Improved ## Improved

View File

@ -1,26 +0,0 @@
# Generated by Django 4.1.5 on 2023-11-14 21:19
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("games", "0028_purchase_name"),
]
operations = [
migrations.AlterField(
model_name="purchase",
name="related_purchase",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="related_purchases",
to="games.purchase",
),
),
]

View File

@ -124,12 +124,7 @@ class Purchase(models.Model):
max_length=255, default="Unknown Name", null=True, blank=True max_length=255, default="Unknown Name", null=True, blank=True
) )
related_purchase = models.ForeignKey( related_purchase = models.ForeignKey(
"Purchase", "Purchase", on_delete=models.SET_NULL, default=None, null=True, blank=True
on_delete=models.SET_NULL,
default=None,
null=True,
blank=True,
related_name="related_purchases",
) )
def __str__(self): def __str__(self):

View File

@ -1429,10 +1429,6 @@ th label {
padding-right: 1rem; padding-right: 1rem;
} }
.sm\:pl-12 {
padding-left: 3rem;
}
.sm\:pl-2 { .sm\:pl-2 {
padding-left: 0.5rem; padding-left: 0.5rem;
} }

View File

@ -13,12 +13,11 @@
{% include 'components/edit_button.html' with edit_url=edit_url %} {% include 'components/edit_button.html' with edit_url=edit_url %}
</h1> </h1>
<h2 class="text-lg my-2 ml-2"> <h2 class="text-lg my-2 ml-2">
{{ hours_sum }} <span class="dark:text-slate-500">total</span> {{ total_hours }} <span class="dark:text-slate-500">total</span>
{{ session_average }} <span class="dark:text-slate-500">avg</span> {{ session_average }} <span class="dark:text-slate-500">avg</span>
({{ playrange }}) </h2> ({{ playrange }}) </h2>
<hr class="border-slate-500"> <hr class="border-slate-500">
<h1 class="text-3xl mt-4 mb-1">Editions <span class="dark:text-slate-500">({{ edition_count }})</span> and Purchases <span class="dark:text-slate-500">({{ purchase_count }})</span></h1> <h1 class="text-3xl mt-4 mb-1">Editions <span class="dark:text-slate-500">({{ editions.count }})</span></h1>
<ul> <ul>
{% for edition in editions %} {% for edition in editions %}
<li class="sm:pl-2 flex items-center"> <li class="sm:pl-2 flex items-center">
@ -33,53 +32,32 @@
{% url 'edit_edition' edition.id as edit_url %} {% url 'edit_edition' edition.id as edit_url %}
{% include 'components/edit_button.html' with edit_url=edit_url %} {% include 'components/edit_button.html' with edit_url=edit_url %}
</li> </li>
{% endfor %}
</ul>
<h1 class="text-3xl mt-4 mb-1">Purchases <span class="dark:text-slate-500">({{ purchases.count }})</span></h1>
<ul> <ul>
{% for purchase in edition.game_purchases %} {% for purchase in purchases %}
<li class="sm:pl-6 flex items-center"> <li class="sm:pl-2 flex items-center">
{{ purchase.get_ownership_type_display }}, {{ purchase.date_purchased | date:"Y" }}, {{ purchase.price }} {{ purchase.price_currency}} {{ purchase.platform }}
({{ purchase.get_ownership_type_display }}, {{ purchase.date_purchased | date:"Y" }}, {{ purchase.price }} {{ purchase.price_currency}})
{% url 'edit_purchase' purchase.id as edit_url %} {% url 'edit_purchase' purchase.id as edit_url %}
{% include 'components/edit_button.html' with edit_url=edit_url %} {% include 'components/edit_button.html' with edit_url=edit_url %}
</li> {% if purchase.related_purchases %}
<li>
<ul> <ul>
{% for related_purchase in purchase.nongame_related_purchases_prefetch %} {% for related_purchase in purchase.related_purchases %}
<li class="sm:pl-12 flex items-center"> <li class="sm:pl-6 flex items-center">
{{ related_purchase.name }} ({{ related_purchase.get_type_display }}, {{ purchase.platform }}, {{ related_purchase.date_purchased | date:"Y" }}, {{ related_purchase.price }} {{ related_purchase.price_currency}}) {{ related_purchase.name}} ({{ related_purchase.get_type_display }}, {{ related_purchase.date_purchased | date:"Y" }}, {{ related_purchase.price }} {{ related_purchase.price_currency}})
{% url 'edit_purchase' related_purchase.id as edit_url %} {% url 'edit_purchase' related_purchase.id as edit_url %}
{% include 'components/edit_button.html' with edit_url=edit_url %} {% include 'components/edit_button.html' with edit_url=edit_url %}
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endfor %}
</ul>
{% endfor %}
</ul>
{% comment %} <ul>
{% for edition in editions %}
<!-- Edition details -->
{{ edition }} (E)
{% if edition.game_purchases %}
<ul>
{% for purchase in edition.game_purchases %}
<li>
<!-- Game purchase details -->
{{ purchase }} (P)
{% if purchase.dlc_related_purchases %}
<ul>
{% for dlc_purchase in purchase.dlc_related_purchases %}
<li>
{{ dlc_purchase }} (D)
</li> </li>
{% endfor %}
</ul>
{% endif %} {% endif %}
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %}
{% endfor %}
</ul> {% endcomment %}
<h1 class="text-3xl mt-4 mb-1 flex gap-2 items-center"> <h1 class="text-3xl mt-4 mb-1 flex gap-2 items-center">
Sessions Sessions
<span class="dark:text-slate-500"> <span class="dark:text-slate-500">

View File

@ -2,7 +2,7 @@ from common.time import format_duration, now as now_with_tz
from common.utils import safe_division from common.utils import safe_division
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.conf import settings from django.conf import settings
from django.db.models import Sum, F, Count, Prefetch from django.db.models import Sum, F, Count
from django.db.models.functions import TruncDate from django.db.models.functions import TruncDate
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
@ -136,52 +136,44 @@ def edit_game(request, game_id=None):
def view_game(request, game_id=None): def view_game(request, game_id=None):
context = {}
game = Game.objects.get(id=game_id) game = Game.objects.get(id=game_id)
nongame_related_purchases_prefetch = Prefetch( context["title"] = "View Game"
"related_purchases", context["game"] = game
queryset=Purchase.objects.exclude(type=Purchase.GAME), context["editions"] = Edition.objects.filter(game_id=game_id)
to_attr="nongame_related_purchases_prefetch", game_purchases = (
Purchase.objects.filter(edition__game_id=game_id)
.filter(type=Purchase.GAME)
.order_by("date_purchased")
) )
game_purchases_prefetch = Prefetch( for purchase in game_purchases:
"purchase_set", purchase.related_purchases = Purchase.objects.exclude(
queryset=Purchase.objects.filter(type=Purchase.GAME).prefetch_related( type=Purchase.GAME
nongame_related_purchases_prefetch ).filter(related_purchase=purchase.id)
),
to_attr="game_purchases", context["purchases"] = game_purchases
context["sessions"] = Session.objects.filter(
purchase__edition__game_id=game_id
).order_by("-timestamp_start")
context["total_hours"] = float(
format_duration(context["sessions"].total_duration_unformatted(), "%2.1H")
) )
editions = ( context["session_average"] = round(
Edition.objects.filter(game=game) (context["total_hours"]) / int(context["sessions"].count()), 1
.prefetch_related(game_purchases_prefetch)
.order_by("year_released")
) )
# here first and last is flipped
# because sessions are ordered from newest to oldest
# so the most recent are on top
playrange_start = context["sessions"].last().timestamp_start.strftime("%b %Y")
playrange_end = context["sessions"].first().timestamp_start.strftime("%b %Y")
sessions = Session.objects.filter(purchase__edition__game=game) context["playrange"] = (
session_count = sessions.count()
playrange_start = sessions.first().timestamp_start.strftime("%b %Y")
playrange_end = sessions.last().timestamp_start.strftime("%b %Y")
playrange = (
playrange_start playrange_start
if playrange_start == playrange_end if playrange_start == playrange_end
else f"{playrange_start}{playrange_end}" else f"{playrange_start}{playrange_end}"
) )
total_hours = float(format_duration(sessions.total_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": round(total_hours / int(session_count), 1),
"session_count": session_count,
"sessions_with_notes": sessions.exclude(note=""),
"sessions": sessions.order_by("-timestamp_start"),
"title": f"Game Overview - {game.name}",
"hours_sum": total_hours,
}
context["sessions_with_notes"] = context["sessions"].exclude(note="")
request.session["return_path"] = request.path request.session["return_path"] = request.path
return render(request, "view_game.html", context) return render(request, "view_game.html", context)