fixed attribution of .fa-hand-pointer cursor color scheme to ordering according to token-drop sequence instead of seat sequence; updates to accomodate this throughout apps.epic.models & .views, plus new apps.epic migration; assigned #id_sig_cursor_portal a z-index value corresponding to a high position but still beneath the #id_tray apparatus; minor semantic reordering of INSTALLED_APPS in core.settings
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
23
src/apps/epic/migrations/0030_sigreservation_seat_fk.py
Normal file
23
src/apps/epic/migrations/0030_sigreservation_seat_fk.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0029_fix_schizo_cautions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='seat',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='sig_reservation',
|
||||
to='epic.tableseat',
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -359,6 +359,10 @@ class SigReservation(models.Model):
|
||||
gamer = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='sig_reservations'
|
||||
)
|
||||
seat = models.ForeignKey(
|
||||
'TableSeat', null=True, blank=True,
|
||||
on_delete=models.SET_NULL, related_name='sig_reservation',
|
||||
)
|
||||
card = models.ForeignKey(
|
||||
'TarotCard', on_delete=models.CASCADE, related_name='sig_reservations'
|
||||
)
|
||||
|
||||
@@ -10,8 +10,11 @@ from django.shortcuts import redirect, render
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.drama.models import GameEvent, record
|
||||
from django.db.models import Case, IntegerField, Value, When
|
||||
|
||||
from apps.epic.models import (
|
||||
GateSlot, Room, RoomInvite, SigReservation, TableSeat, TarotCard, TarotDeck,
|
||||
GateSlot, Room, RoomInvite, SIG_SEAT_ORDER, SigReservation, TableSeat,
|
||||
TarotCard, TarotDeck,
|
||||
active_sig_seat, debit_token, levity_sig_cards, gravity_sig_cards,
|
||||
select_token, sig_deck_cards,
|
||||
)
|
||||
@@ -92,6 +95,22 @@ def _notify_sig_reserved(room_id, card_id, role, reserved):
|
||||
|
||||
SLOT_ROLE_LABELS = {1: "PC", 2: "NC", 3: "EC", 4: "SC", 5: "AC", 6: "BC"}
|
||||
|
||||
_SIG_SEAT_ORDERING = Case(
|
||||
*[When(role=r, then=Value(i)) for i, r in enumerate(SIG_SEAT_ORDER)],
|
||||
default=Value(99),
|
||||
output_field=IntegerField(),
|
||||
)
|
||||
|
||||
|
||||
def _canonical_user_seat(room, user):
|
||||
"""Return the user's seat whose role comes first in PC→NC→EC→SC→AC→BC order.
|
||||
|
||||
In normal play (one user = one seat) this is equivalent to .first().
|
||||
For Carte Blanche (one user = all seats) it returns the PC seat, ensuring
|
||||
sig-select cursor placement is seat-based, not position/slot-based.
|
||||
"""
|
||||
return room.table_seats.filter(gamer=user).order_by(_SIG_SEAT_ORDERING).first()
|
||||
|
||||
_ROLE_SCRAWL_NAMES = {
|
||||
"PC": "Player", "NC": "Narrator", "EC": "Economist",
|
||||
"SC": "Shepherd", "AC": "Alchemist", "BC": "Builder",
|
||||
@@ -242,7 +261,7 @@ def _role_select_context(room, user):
|
||||
"slots": room.gate_slots.order_by("slot_number"),
|
||||
}
|
||||
if room.table_status == Room.SIG_SELECT:
|
||||
user_seat = room.table_seats.filter(gamer=user).first() if user.is_authenticated else None
|
||||
user_seat = _canonical_user_seat(room, user) if user.is_authenticated else None
|
||||
user_role = user_seat.role if user_seat else None
|
||||
user_polarity = None
|
||||
if user_role in _LEVITY_ROLES:
|
||||
@@ -583,7 +602,7 @@ def sig_reserve(request, room_id):
|
||||
if room.table_status != Room.SIG_SELECT:
|
||||
return HttpResponse(status=400)
|
||||
|
||||
user_seat = room.table_seats.filter(gamer=request.user).first()
|
||||
user_seat = _canonical_user_seat(room, request.user)
|
||||
if not user_seat or not user_seat.role:
|
||||
return HttpResponse(status=403)
|
||||
|
||||
@@ -622,7 +641,7 @@ def sig_reserve(request, room_id):
|
||||
|
||||
SigReservation.objects.create(
|
||||
room=room, gamer=request.user, card=card,
|
||||
role=user_seat.role, polarity=polarity,
|
||||
seat=user_seat, role=user_seat.role, polarity=polarity,
|
||||
)
|
||||
_notify_sig_reserved(room_id, card.pk, user_seat.role, reserved=True)
|
||||
return HttpResponse(status=200)
|
||||
|
||||
@@ -57,13 +57,13 @@ INSTALLED_APPS = [
|
||||
# Board apps
|
||||
'apps.dashboard',
|
||||
'apps.gameboard',
|
||||
'apps.billboard',
|
||||
# Gamer apps
|
||||
'apps.lyric',
|
||||
'apps.epic',
|
||||
'apps.drama',
|
||||
'apps.billboard',
|
||||
'apps.ap',
|
||||
# Custom apps
|
||||
'apps.ap',
|
||||
'apps.api',
|
||||
'apps.applets',
|
||||
'functional_tests',
|
||||
|
||||
@@ -507,7 +507,7 @@ html:has(.sig-backdrop) {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
z-index: 200; // above sig-overlay (120), below tray (310)
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user