diff --git a/games/api.py b/games/api.py index f9fea63..a2fdec2 100644 --- a/games/api.py +++ b/games/api.py @@ -5,14 +5,19 @@ from django.shortcuts import get_object_or_404 from django.utils.timezone import now as django_timezone_now from ninja import Field, ModelSchema, NinjaAPI, Router, Schema -from games.models import PlayEvent +from games.models import Game, PlayEvent api = NinjaAPI() playevent_router = Router() +game_router = Router() NOW_FACTORY = django_timezone_now +class GameStatusUpdate(Schema): + status: str + + class PlayEventIn(Schema): game_id: int started: date | None = None @@ -44,6 +49,14 @@ class PlayEventOut(Schema): created_at: datetime +@game_router.patch("/{game_id}/status", response={204: None}) +def partial_update_game(request, game_id: int, payload: GameStatusUpdate): + game = get_object_or_404(Game, id=game_id) + setattr(game, "status", payload.status) + game.save() + return 204, None + + @playevent_router.get("/", response=List[PlayEventOut]) def list_playevents(request): return PlayEvent.objects.all() @@ -78,3 +91,5 @@ def delete_playevent(request, playevent_id: int): api.add_router("/playevent", playevent_router) +api.add_router("/games", game_router) + diff --git a/games/static/base.css b/games/static/base.css index 2665765..9fe3b9f 100644 --- a/games/static/base.css +++ b/games/static/base.css @@ -1299,10 +1299,6 @@ input:checked + .toggle-bg { bottom: 0px; } -.-left-3 { - left: -0.75rem; -} - .-left-\[1px\] { left: -1px; } @@ -1343,10 +1339,6 @@ input:checked + .toggle-bg { top: 0px; } -.top-2 { - top: 0.5rem; -} - .top-3 { top: 0.75rem; } @@ -1355,6 +1347,10 @@ input:checked + .toggle-bg { top: 100%; } +.top-\[105\%\] { + top: 105%; +} + .z-10 { z-index: 10; } @@ -1431,10 +1427,6 @@ input:checked + .toggle-bg { margin-inline-end: 0.5rem; } -.ml-3 { - margin-left: 0.75rem; -} - .mr-4 { margin-right: 1rem; } @@ -1508,14 +1500,14 @@ input:checked + .toggle-bg { height: 3rem; } -.h-2 { - height: 0.5rem; -} - .h-2\.5 { height: 0.625rem; } +.h-3 { + height: 0.75rem; +} + .h-4 { height: 1rem; } @@ -1548,10 +1540,6 @@ input:checked + .toggle-bg { width: 2.5rem; } -.w-2 { - width: 0.5rem; -} - .w-2\.5 { width: 0.625rem; } @@ -1708,6 +1696,10 @@ input:checked + .toggle-bg { grid-template-columns: repeat(7, minmax(0, 1fr)); } +.flex-row { + flex-direction: row; +} + .flex-col { flex-direction: column; } @@ -1864,6 +1856,11 @@ input:checked + .toggle-bg { border-end-start-radius: 0.5rem; } +.rounded-t-none { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + .rounded-tl-none { border-top-left-radius: 0px; } @@ -3434,6 +3431,15 @@ div [type="submit"] { margin-bottom: 0.5rem; } +.\[\&_li\:first-of-type\]\:rounded-none li:first-of-type { + border-radius: 0px; +} + +.\[\&_li\:last-of-type\]\:rounded-t-none li:last-of-type { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + .\[\&_td\:last-child\]\:text-right td:last-child { text-align: right; } diff --git a/games/templates/cotton/gamestatus.html b/games/templates/cotton/gamestatus.html index c532e38..fd01c71 100644 --- a/games/templates/cotton/gamestatus.html +++ b/games/templates/cotton/gamestatus.html @@ -1,5 +1,5 @@ - - + Original year {{ game.original_year_released }} -
+
Status - - {{ game.get_status_display }} - - {% if game.mastered %}👑{% endif %} + +
+ +
+
Saving...
+ {% if game.mastered %}👑{% endif %}
HttpResponse: "statuschange_count": statuschange_count, "statuschanges": statuschanges, "game": game, + "game_statuses": Game.Status.choices, "playrange": playrange, "purchase_count": game.purchases.count(), "session_average_without_manual": round( diff --git a/timetracker/urls.py b/timetracker/urls.py index 5d1b36f..85e57a4 100644 --- a/timetracker/urls.py +++ b/timetracker/urls.py @@ -22,8 +22,11 @@ from django.views.decorators.csrf import csrf_exempt from django.views.generic import RedirectView from graphene_django.views import GraphQLView +from games.api import api + urlpatterns = [ path("", RedirectView.as_view(url="/tracker")), + path("api/", api.urls), path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))), path("login/", auth_views.LoginView.as_view(), name="login"), path("logout/", auth_views.LogoutView.as_view(), name="logout"),