Compare commits
7 Commits
fda4913c97
...
b28c42d945
Author | SHA1 | Date |
---|---|---|
Lukáš Kucharczyk | b28c42d945 | |
Lukáš Kucharczyk | 3099f02145 | |
Lukáš Kucharczyk | 74b9d0421c | |
Lukáš Kucharczyk | c61adad180 | |
Lukáš Kucharczyk | 298ecb4092 | |
Lukáš Kucharczyk | 020e12e20b | |
Lukáš Kucharczyk | 6ef56bfed5 |
|
@ -1,8 +1,11 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
# disable due to incomaptible formatting between
|
||||||
rev: 24.8.0
|
# black and ruff
|
||||||
hooks:
|
# TODO: replace with ruff when it works on NixOS
|
||||||
- id: black
|
# - repo: https://github.com/psf/black
|
||||||
|
# rev: 24.8.0
|
||||||
|
# hooks:
|
||||||
|
# - id: black
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
rev: 5.13.2
|
rev: 5.13.2
|
||||||
hooks:
|
hooks:
|
||||||
|
|
|
@ -1,5 +1,31 @@
|
||||||
|
from random import choices
|
||||||
|
from string import ascii_lowercase
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
|
||||||
|
def Popover(
|
||||||
|
wrapped_content: str,
|
||||||
|
popover_content: str = "",
|
||||||
|
) -> str:
|
||||||
|
id = randomid()
|
||||||
|
if popover_content == "":
|
||||||
|
popover_content = wrapped_content
|
||||||
|
content = f"<span data-popover-target={id}>{wrapped_content}</span>"
|
||||||
|
result = mark_safe(
|
||||||
|
str(content)
|
||||||
|
+ render_to_string(
|
||||||
|
"components/popover.html",
|
||||||
|
{
|
||||||
|
"id": id,
|
||||||
|
"children": popover_content,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def safe_division(numerator: int | float, denominator: int | float) -> int | float:
|
def safe_division(numerator: int | float, denominator: int | float) -> int | float:
|
||||||
"""
|
"""
|
||||||
|
@ -31,3 +57,24 @@ def safe_getattr(obj: object, attr_chain: str, default: Any | None = None) -> ob
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return default
|
return default
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def truncate(input_string: str, length: int = 30, ellipsis: str = "…") -> str:
|
||||||
|
return (
|
||||||
|
(f"{input_string[:length-len(ellipsis)]}{ellipsis}")
|
||||||
|
if len(input_string) > 30
|
||||||
|
else input_string
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def truncate_with_popover(input_string: str) -> str:
|
||||||
|
if (truncated := truncate(input_string)) != input_string:
|
||||||
|
print(f"Not the same after: {truncated=}")
|
||||||
|
return Popover(wrapped_content=truncated, popover_content=input_string)
|
||||||
|
else:
|
||||||
|
print("Strings are the same!")
|
||||||
|
return input_string
|
||||||
|
|
||||||
|
|
||||||
|
def randomid(seed: str = "", length: int = 10) -> str:
|
||||||
|
return seed + "".join(choices(ascii_lowercase, k=length))
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from games.forms import DeviceForm
|
||||||
|
from games.models import Device
|
||||||
|
from games.views import dateformat
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def list_devices(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[Any, Any] = {}
|
||||||
|
page_number = request.GET.get("page", 1)
|
||||||
|
limit = request.GET.get("limit", 10)
|
||||||
|
devices = Device.objects.order_by("-created_at")
|
||||||
|
page_obj = None
|
||||||
|
if int(limit) != 0:
|
||||||
|
paginator = Paginator(devices, limit)
|
||||||
|
page_obj = paginator.get_page(page_number)
|
||||||
|
devices = page_obj.object_list
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "Manage devices",
|
||||||
|
"page_obj": page_obj or None,
|
||||||
|
"elided_page_range": (
|
||||||
|
page_obj.paginator.get_elided_page_range(
|
||||||
|
page_number, on_each_side=1, on_ends=1
|
||||||
|
)
|
||||||
|
if page_obj
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"data": {
|
||||||
|
"columns": [
|
||||||
|
"Name",
|
||||||
|
"Type",
|
||||||
|
"Created",
|
||||||
|
"Actions",
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
device.name,
|
||||||
|
device.get_type_display(),
|
||||||
|
device.created_at.strftime(dateformat),
|
||||||
|
render_to_string(
|
||||||
|
"components/button_group_sm.html",
|
||||||
|
{
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"href": reverse("edit_device", args=[device.pk]),
|
||||||
|
"text": "Edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": reverse("delete_device", args=[device.pk]),
|
||||||
|
"text": "Delete",
|
||||||
|
"color": "red",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for device in devices
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return render(request, "list_purchases.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def edit_device(request: HttpRequest, device_id: int = 0) -> HttpResponse:
|
||||||
|
device = get_object_or_404(Device, id=device_id)
|
||||||
|
form = DeviceForm(request.POST or None, instance=device)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("list_devices")
|
||||||
|
|
||||||
|
context: dict[str, Any] = {"form": form, "title": "Edit device"}
|
||||||
|
return render(request, "add.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete_device(request: HttpRequest, device_id: int) -> HttpResponse:
|
||||||
|
device = get_object_or_404(Device, id=device_id)
|
||||||
|
device.delete()
|
||||||
|
return redirect("list_sessions")
|
|
@ -0,0 +1,109 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from common.utils import truncate_with_popover
|
||||||
|
from games.forms import EditionForm
|
||||||
|
from games.models import Edition
|
||||||
|
from games.views import dateformat
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def list_editions(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[Any, Any] = {}
|
||||||
|
page_number = request.GET.get("page", 1)
|
||||||
|
limit = request.GET.get("limit", 10)
|
||||||
|
editions = Edition.objects.order_by("-created_at")
|
||||||
|
page_obj = None
|
||||||
|
if int(limit) != 0:
|
||||||
|
paginator = Paginator(editions, limit)
|
||||||
|
page_obj = paginator.get_page(page_number)
|
||||||
|
editions = page_obj.object_list
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "Manage editions",
|
||||||
|
"page_obj": page_obj or None,
|
||||||
|
"elided_page_range": (
|
||||||
|
page_obj.paginator.get_elided_page_range(
|
||||||
|
page_number, on_each_side=1, on_ends=1
|
||||||
|
)
|
||||||
|
if page_obj
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"data": {
|
||||||
|
"columns": [
|
||||||
|
"Game",
|
||||||
|
"Name",
|
||||||
|
"Sort Name",
|
||||||
|
"Platform",
|
||||||
|
"Year",
|
||||||
|
"Wikidata",
|
||||||
|
"Created",
|
||||||
|
"Actions",
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
truncate_with_popover(edition.game.name),
|
||||||
|
truncate_with_popover(
|
||||||
|
edition.name
|
||||||
|
if edition.game.name != edition.name
|
||||||
|
else "(identical)"
|
||||||
|
),
|
||||||
|
truncate_with_popover(
|
||||||
|
edition.sort_name
|
||||||
|
if edition.sort_name is not None
|
||||||
|
and edition.game.name != edition.sort_name
|
||||||
|
else "(identical)"
|
||||||
|
),
|
||||||
|
truncate_with_popover(str(edition.platform)),
|
||||||
|
edition.year_released,
|
||||||
|
edition.wikidata,
|
||||||
|
edition.created_at.strftime(dateformat),
|
||||||
|
render_to_string(
|
||||||
|
"components/button_group_sm.html",
|
||||||
|
{
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"href": reverse("edit_edition", args=[edition.pk]),
|
||||||
|
"text": "Edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": reverse(
|
||||||
|
"delete_edition", args=[edition.pk]
|
||||||
|
),
|
||||||
|
"text": "Delete",
|
||||||
|
"color": "red",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for edition in editions
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return render(request, "list_purchases.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def edit_device(request: HttpRequest, edition_id: int = 0) -> HttpResponse:
|
||||||
|
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_editions")
|
||||||
|
|
||||||
|
context: dict[str, Any] = {"form": form, "title": "Edit edition"}
|
||||||
|
return render(request, "add.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete_edition(request: HttpRequest, edition_id: int) -> HttpResponse:
|
||||||
|
edition = get_object_or_404(Edition, id=edition_id)
|
||||||
|
edition.delete()
|
||||||
|
return redirect("list_editions")
|
|
@ -0,0 +1,73 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from games.models import Game
|
||||||
|
from games.views import dateformat
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def list_games(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[Any, Any] = {}
|
||||||
|
page_number = request.GET.get("page", 1)
|
||||||
|
limit = request.GET.get("limit", 10)
|
||||||
|
games = Game.objects.order_by("-created_at")
|
||||||
|
page_obj = None
|
||||||
|
if int(limit) != 0:
|
||||||
|
paginator = Paginator(games, limit)
|
||||||
|
page_obj = paginator.get_page(page_number)
|
||||||
|
games = page_obj.object_list
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "Manage games",
|
||||||
|
"page_obj": page_obj or None,
|
||||||
|
"elided_page_range": (
|
||||||
|
page_obj.paginator.get_elided_page_range(
|
||||||
|
page_number, on_each_side=1, on_ends=1
|
||||||
|
)
|
||||||
|
if page_obj
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"data": {
|
||||||
|
"columns": [
|
||||||
|
"Name",
|
||||||
|
"Sort Name",
|
||||||
|
"Year",
|
||||||
|
"Wikidata",
|
||||||
|
"Created",
|
||||||
|
"Actions",
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
game.name,
|
||||||
|
game.sort_name,
|
||||||
|
game.year_released,
|
||||||
|
game.wikidata,
|
||||||
|
game.created_at.strftime(dateformat),
|
||||||
|
render_to_string(
|
||||||
|
"components/button_group_sm.html",
|
||||||
|
{
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"href": reverse("edit_game", args=[game.pk]),
|
||||||
|
"text": "Edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": reverse("delete_game", args=[game.pk]),
|
||||||
|
"text": "Delete",
|
||||||
|
"color": "red",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for game in games
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return render(request, "list_purchases.html", context)
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 5.1 on 2024-08-11 15:50
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("games", "0034_purchase_date_dropped_purchase_infinite"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="session",
|
||||||
|
name="device",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_DEFAULT,
|
||||||
|
to="games.device",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 5.1 on 2024-08-11 16:48
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('games', '0035_alter_session_device'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='edition',
|
||||||
|
name='platform',
|
||||||
|
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='games.platform'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -39,7 +39,7 @@ class Edition(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
sort_name = models.CharField(max_length=255, null=True, blank=True, default=None)
|
sort_name = models.CharField(max_length=255, null=True, blank=True, default=None)
|
||||||
platform = models.ForeignKey(
|
platform = models.ForeignKey(
|
||||||
Platform, on_delete=models.CASCADE, null=True, blank=True, default=None
|
Platform, on_delete=models.SET_DEFAULT, null=True, blank=True, default=None
|
||||||
)
|
)
|
||||||
year_released = models.IntegerField(null=True, blank=True, default=None)
|
year_released = models.IntegerField(null=True, blank=True, default=None)
|
||||||
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
||||||
|
@ -182,7 +182,7 @@ class Session(models.Model):
|
||||||
duration_calculated = models.DurationField(blank=True, null=True)
|
duration_calculated = models.DurationField(blank=True, null=True)
|
||||||
device = models.ForeignKey(
|
device = models.ForeignKey(
|
||||||
"Device",
|
"Device",
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.SET_DEFAULT,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
default=None,
|
default=None,
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from games.models import Platform
|
||||||
|
from games.views import dateformat
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def list_platforms(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[Any, Any] = {}
|
||||||
|
page_number = request.GET.get("page", 1)
|
||||||
|
limit = request.GET.get("limit", 10)
|
||||||
|
platforms = Platform.objects.order_by("-created_at")
|
||||||
|
page_obj = None
|
||||||
|
if int(limit) != 0:
|
||||||
|
paginator = Paginator(platforms, limit)
|
||||||
|
page_obj = paginator.get_page(page_number)
|
||||||
|
platforms = page_obj.object_list
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "Manage platforms",
|
||||||
|
"page_obj": page_obj or None,
|
||||||
|
"elided_page_range": (
|
||||||
|
page_obj.paginator.get_elided_page_range(
|
||||||
|
page_number, on_each_side=1, on_ends=1
|
||||||
|
)
|
||||||
|
if page_obj
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"data": {
|
||||||
|
"columns": [
|
||||||
|
"Name",
|
||||||
|
"Group",
|
||||||
|
"Created",
|
||||||
|
"Actions",
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
platform.name,
|
||||||
|
platform.group,
|
||||||
|
platform.created_at.strftime(dateformat),
|
||||||
|
render_to_string(
|
||||||
|
"components/button_group_sm.html",
|
||||||
|
{
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"href": reverse(
|
||||||
|
"edit_platform", args=[platform.pk]
|
||||||
|
),
|
||||||
|
"text": "Edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": reverse(
|
||||||
|
"delete_platform", args=[platform.pk]
|
||||||
|
),
|
||||||
|
"text": "Delete",
|
||||||
|
"color": "red",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for platform in platforms
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return render(request, "list_purchases.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete_platform(request: HttpRequest, platform_id: int) -> HttpResponse:
|
||||||
|
platform = get_object_or_404(Platform, id=platform_id)
|
||||||
|
platform.delete()
|
||||||
|
return redirect("list_platforms")
|
|
@ -1736,10 +1736,6 @@ input:checked + .toggle-bg {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-ellipsis {
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.whitespace-nowrap {
|
.whitespace-nowrap {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
@ -2215,10 +2211,6 @@ input:checked + .toggle-bg {
|
||||||
min-width: 30ch;
|
min-width: 30ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.max-w-30char {
|
|
||||||
max-width: 30ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.\[a-zA-Z\:\\-\] {
|
.\[a-zA-Z\:\\-\] {
|
||||||
a-z-a--z: \-;
|
a-z-a--z: \-;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
<!-- needs data-popover-target on triggering block -->
|
|
||||||
<!-- id -->
|
|
||||||
<!-- children -->
|
|
||||||
<div data-popover
|
<div data-popover
|
||||||
id="{{ id }}"
|
id="{{ id }}"
|
||||||
role="tooltip"
|
role="tooltip"
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
{% fragment as default_content %}
|
{% fragment as default_content %}
|
||||||
{% load randomid %}
|
|
||||||
{% for td in data %}
|
{% for td in data %}
|
||||||
{% if forloop.first %}
|
{% if forloop.first %}
|
||||||
<th scope="row"
|
<th scope="row"
|
||||||
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white min-w-30char">
|
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">{{ td }}</th>
|
||||||
{% randomid td as th_popover_id %}
|
|
||||||
<span data-popover-target="{{ th_popover_id }}">{{ td|truncatechars:30 }}</span>
|
|
||||||
{% if td|length > 30 %}
|
|
||||||
{% #popover id=th_popover_id %}
|
|
||||||
{{ td }}
|
|
||||||
{% /popover %}
|
|
||||||
{% endif %}
|
|
||||||
</th>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% #table_td %}
|
{% #table_td %}
|
||||||
{{ td }}
|
{{ td }}
|
||||||
|
|
|
@ -95,19 +95,19 @@
|
||||||
<ul class="py-2 text-sm text-gray-700 dark:text-gray-400"
|
<ul class="py-2 text-sm text-gray-700 dark:text-gray-400"
|
||||||
aria-labelledby="dropdownLargeButton">
|
aria-labelledby="dropdownLargeButton">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'add_device' %}"
|
<a href="{% url 'list_devices' %}"
|
||||||
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Devices</a>
|
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Devices</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'add_game' %}"
|
<a href="{% url 'list_games' %}"
|
||||||
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Games</a>
|
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Games</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'add_edition' %}"
|
<a href="{% url 'list_editions' %}"
|
||||||
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Editions</a>
|
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Editions</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'add_platform' %}"
|
<a href="{% url 'list_platforms' %}"
|
||||||
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Platforms</a>
|
class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Platforms</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from games import purchaseviews, sessionviews, views
|
from games import (
|
||||||
|
deviceviews,
|
||||||
|
editionviews,
|
||||||
|
gameviews,
|
||||||
|
platformviews,
|
||||||
|
purchaseviews,
|
||||||
|
sessionviews,
|
||||||
|
views,
|
||||||
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
path("device/add", views.add_device, name="add_device"),
|
path("device/add", views.add_device, name="add_device"),
|
||||||
|
path(
|
||||||
|
"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/list", deviceviews.list_devices, name="list_devices"),
|
||||||
path("edition/add", views.add_edition, name="add_edition"),
|
path("edition/add", views.add_edition, name="add_edition"),
|
||||||
path(
|
path(
|
||||||
"edition/add/for-game/<int:game_id>",
|
"edition/add/for-game/<int:game_id>",
|
||||||
|
@ -12,12 +25,25 @@ urlpatterns = [
|
||||||
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", views.edit_edition, name="edit_edition"),
|
||||||
|
path("edition/list", editionviews.list_editions, name="list_editions"),
|
||||||
|
path(
|
||||||
|
"edition/<int:edition_id>/delete",
|
||||||
|
editionviews.delete_edition,
|
||||||
|
name="delete_edition",
|
||||||
|
),
|
||||||
path("game/add", views.add_game, name="add_game"),
|
path("game/add", views.add_game, name="add_game"),
|
||||||
path("game/<int:game_id>/edit", views.edit_game, name="edit_game"),
|
path("game/<int:game_id>/edit", views.edit_game, name="edit_game"),
|
||||||
path("game/<int:game_id>/view", views.view_game, name="view_game"),
|
path("game/<int:game_id>/view", views.view_game, name="view_game"),
|
||||||
path("game/<int:game_id>/delete", views.delete_game, name="delete_game"),
|
path("game/<int:game_id>/delete", views.delete_game, name="delete_game"),
|
||||||
|
path("game/list", gameviews.list_games, name="list_games"),
|
||||||
path("platform/add", views.add_platform, name="add_platform"),
|
path("platform/add", views.add_platform, name="add_platform"),
|
||||||
path("platform/<int:platform_id>/edit", views.edit_platform, name="edit_platform"),
|
path("platform/<int:platform_id>/edit", views.edit_platform, name="edit_platform"),
|
||||||
|
path(
|
||||||
|
"platform/<int:platform_id>/delete",
|
||||||
|
platformviews.delete_platform,
|
||||||
|
name="delete_platform",
|
||||||
|
),
|
||||||
|
path("platform/list", platformviews.list_platforms, name="list_platforms"),
|
||||||
path("purchase/add", views.add_purchase, name="add_purchase"),
|
path("purchase/add", views.add_purchase, name="add_purchase"),
|
||||||
path("purchase/<int:purchase_id>/edit", views.edit_purchase, name="edit_purchase"),
|
path("purchase/<int:purchase_id>/edit", views.edit_purchase, name="edit_purchase"),
|
||||||
path(
|
path(
|
||||||
|
@ -77,12 +103,6 @@ urlpatterns = [
|
||||||
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(
|
|
||||||
"session/list/recent",
|
|
||||||
views.list_sessions,
|
|
||||||
{"filter": "recent"},
|
|
||||||
name="list_sessions_recent",
|
|
||||||
),
|
|
||||||
path(
|
path(
|
||||||
"session/list/by-purchase/<int:purchase_id>",
|
"session/list/by-purchase/<int:purchase_id>",
|
||||||
views.list_sessions,
|
views.list_sessions,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from datetime import datetime
|
|
||||||
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
|
||||||
|
@ -225,11 +224,11 @@ def view_game(request: HttpRequest, game_id: int) -> HttpResponse:
|
||||||
@use_custom_redirect
|
@use_custom_redirect
|
||||||
def edit_platform(request: HttpRequest, platform_id: int) -> HttpResponse:
|
def edit_platform(request: HttpRequest, platform_id: int) -> HttpResponse:
|
||||||
context = {}
|
context = {}
|
||||||
purchase = get_object_or_404(Purchase, id=platform_id)
|
platform = get_object_or_404(Platform, id=platform_id)
|
||||||
form = PlatformForm(request.POST or None, instance=purchase)
|
form = PlatformForm(request.POST or None, instance=platform)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
return redirect("list_sessions")
|
return redirect("list_platforms")
|
||||||
context["title"] = "Edit Platform"
|
context["title"] = "Edit Platform"
|
||||||
context["form"] = form
|
context["form"] = form
|
||||||
return render(request, "add.html", context)
|
return render(request, "add.html", context)
|
||||||
|
@ -342,12 +341,6 @@ def list_sessions(
|
||||||
elif filter == "ownership_type":
|
elif filter == "ownership_type":
|
||||||
dataset = all_sessions.filter(purchase__ownership_type=ownership_type)
|
dataset = all_sessions.filter(purchase__ownership_type=ownership_type)
|
||||||
context["ownership_type"] = dict(Purchase.OWNERSHIP_TYPES)[ownership_type]
|
context["ownership_type"] = dict(Purchase.OWNERSHIP_TYPES)[ownership_type]
|
||||||
elif filter == "recent":
|
|
||||||
current_year = timezone.now().year
|
|
||||||
first_day_of_year = timezone.make_aware(datetime(current_year, 1, 1))
|
|
||||||
dataset = all_sessions.filter(timestamp_start__gte=first_day_of_year).order_by(
|
|
||||||
"-timestamp_start"
|
|
||||||
)
|
|
||||||
context["title"] = "This year"
|
context["title"] = "This year"
|
||||||
else:
|
else:
|
||||||
dataset = all_sessions
|
dataset = all_sessions
|
||||||
|
@ -757,15 +750,11 @@ def stats(request: HttpRequest, year: int = 0) -> HttpResponse:
|
||||||
"all_finished_this_year_count": purchases_finished_this_year.count(),
|
"all_finished_this_year_count": purchases_finished_this_year.count(),
|
||||||
"this_year_finished_this_year": purchases_finished_this_year_released_this_year.select_related(
|
"this_year_finished_this_year": purchases_finished_this_year_released_this_year.select_related(
|
||||||
"edition"
|
"edition"
|
||||||
).order_by(
|
).order_by("date_finished"),
|
||||||
"date_finished"
|
|
||||||
),
|
|
||||||
"this_year_finished_this_year_count": purchases_finished_this_year_released_this_year.count(),
|
"this_year_finished_this_year_count": purchases_finished_this_year_released_this_year.count(),
|
||||||
"purchased_this_year_finished_this_year": purchased_this_year_finished_this_year.select_related(
|
"purchased_this_year_finished_this_year": purchased_this_year_finished_this_year.select_related(
|
||||||
"edition"
|
"edition"
|
||||||
).order_by(
|
).order_by("date_finished"),
|
||||||
"date_finished"
|
|
||||||
),
|
|
||||||
"total_sessions": this_year_sessions.count(),
|
"total_sessions": this_year_sessions.count(),
|
||||||
"unique_days": unique_days["dates"],
|
"unique_days": unique_days["dates"],
|
||||||
"unique_days_percent": int(unique_days["dates"] / 365 * 100),
|
"unique_days_percent": int(unique_days["dates"] / 365 * 100),
|
||||||
|
@ -949,4 +938,4 @@ def add_device(request: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def index(request: HttpRequest) -> HttpResponse:
|
def index(request: HttpRequest) -> HttpResponse:
|
||||||
return redirect("list_sessions_recent")
|
return redirect("list_sessions")
|
||||||
|
|
Loading…
Reference in New Issue