PICK SEA Sprint A: async sky→sea transition via WS room:sky_confirmed — TDD
- natus_save: group_send room:sky_confirmed after confirm (carries seat_role) - consumer: sky_confirmed handler rebroadcasts to room group - _notify_sky_confirmed() helper mirrors _notify_pick_sky_available - sea_partial view: renders _sea_overlay.html partial for in-page injection (403 if not sky_confirmed) - epic:sea_partial URL registered - _natus_overlay.html: data-user-seat-role attr; _onSkyConfirmed() fetches sea partial, removes natus overlay + backdrop, injects sea HTML, toggles sea-open on html root; room:sky_confirmed WS listener calls _onSkyConfirmed only for matching seat role - user_seat_role added to SKY_SELECT context - FT: PickSeaAsyncTransitionTest (3 tests, ChannelsFunctionalTest) — sea overlay, natus gone, sea-open class — all green Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -90,5 +90,8 @@ class RoomConsumer(AsyncJsonWebsocketConsumer):
|
||||
async def pick_sky_available(self, event):
|
||||
await self.send_json(event)
|
||||
|
||||
async def sky_confirmed(self, event):
|
||||
await self.send_json(event)
|
||||
|
||||
async def cursor_move(self, event):
|
||||
await self.send_json(event)
|
||||
|
||||
@@ -27,4 +27,5 @@ urlpatterns = [
|
||||
path('room/<uuid:room_id>/tarot/deal', views.tarot_deal, name='tarot_deal'),
|
||||
path('room/<uuid:room_id>/natus/preview', views.natus_preview, name='natus_preview'),
|
||||
path('room/<uuid:room_id>/natus/save', views.natus_save, name='natus_save'),
|
||||
path('room/<uuid:room_id>/sea/partial', views.sea_partial, name='sea_partial'),
|
||||
]
|
||||
|
||||
@@ -126,6 +126,13 @@ def _notify_pick_sky_available(room_id):
|
||||
)
|
||||
|
||||
|
||||
def _notify_sky_confirmed(room_id, seat_role):
|
||||
async_to_sync(get_channel_layer().group_send)(
|
||||
f'room_{room_id}',
|
||||
{'type': 'sky_confirmed', 'seat_role': seat_role},
|
||||
)
|
||||
|
||||
|
||||
SLOT_ROLE_LABELS = {1: "PC", 2: "NC", 3: "EC", 4: "SC", 5: "AC", 6: "BC"}
|
||||
|
||||
_SIG_SEAT_ORDERING = Case(
|
||||
@@ -362,6 +369,7 @@ def _role_select_context(room, user):
|
||||
)
|
||||
sky_confirmed = confirmed_char is not None
|
||||
ctx["sky_confirmed"] = sky_confirmed
|
||||
ctx["user_seat_role"] = _canonical_seat.role if _canonical_seat else ''
|
||||
if sky_confirmed:
|
||||
ctx["my_tray_sig"] = confirmed_char.significator
|
||||
|
||||
@@ -1093,5 +1101,19 @@ def natus_save(request, room_id):
|
||||
char.confirmed_at = timezone.now()
|
||||
|
||||
char.save()
|
||||
|
||||
if char.is_confirmed:
|
||||
_notify_sky_confirmed(room_id, seat.role)
|
||||
|
||||
return JsonResponse({'id': char.id, 'confirmed': char.is_confirmed})
|
||||
|
||||
|
||||
@login_required
|
||||
def sea_partial(request, room_id):
|
||||
"""Return the rendered sea overlay partial for in-page injection after sky confirm."""
|
||||
room = Room.objects.get(id=room_id)
|
||||
ctx = _role_select_context(room, request.user)
|
||||
if not ctx.get('sky_confirmed'):
|
||||
return HttpResponse(status=403)
|
||||
return render(request, 'apps/gameboard/_partials/_sea_overlay.html', ctx)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user