Fix green room Go live and Panels hidden for conference hosts.
Deploy Ladill Meet / deploy (push) Successful in 34s
Deploy Ladill Meet / deploy (push) Successful in 34s
Stop registerPresenter from demoting hosts to panelists, recognize room owners as managers, and show stage controls in the green room banner. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -356,7 +356,16 @@ class MeetingFeaturesController extends Controller
|
||||
protected function hostOnly(Request $request, Session $session): Participant
|
||||
{
|
||||
$participant = $this->participant($request, $session);
|
||||
abort_unless($participant->isHost(), 403);
|
||||
$user = $request->user();
|
||||
$isRoomHost = $user && $user->ownerRef() === $session->room->host_user_ref;
|
||||
|
||||
abort_unless($participant->isHost() || $isRoomHost, 403);
|
||||
|
||||
if ($isRoomHost && ! $participant->isHost()) {
|
||||
$participant->update(['role' => 'host']);
|
||||
|
||||
return $participant->fresh();
|
||||
}
|
||||
|
||||
return $participant;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ class MeetingRoomController extends Controller
|
||||
$spaces = app(SpaceService::class);
|
||||
$isAudioOnly = $room->isAudioOnly();
|
||||
$stageLayout = app(StageLayoutService::class);
|
||||
$authUser = $request->user();
|
||||
$isRoomHost = $authUser && $authUser->ownerRef() === $room->host_user_ref;
|
||||
$canManageConference = $participant->isHost() || $isRoomHost;
|
||||
|
||||
return view('meet.room.show', [
|
||||
'session' => $session,
|
||||
@@ -90,6 +93,7 @@ class MeetingRoomController extends Controller
|
||||
'isAttendee' => $participant->isAttendee() || $spaces->isListener($room, $participant),
|
||||
'usesStageLayout' => $stageLayout->usesStageLayout($room),
|
||||
'stageConfig' => $stageLayout->config($room),
|
||||
'canManageConference' => $canManageConference,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,12 @@ class SessionService
|
||||
$updates['joined_at'] = $existing->joined_at ?? now();
|
||||
}
|
||||
|
||||
if (in_array($role, ['host', 'co_host'], true)) {
|
||||
$updates['role'] = $role;
|
||||
} elseif ($existing->role === 'guest' && $role !== 'guest') {
|
||||
$updates['role'] = $role;
|
||||
}
|
||||
|
||||
$existing->update($updates);
|
||||
|
||||
return $existing;
|
||||
|
||||
@@ -103,6 +103,7 @@ class TownHallService
|
||||
$session->participants()
|
||||
->where('user_ref', $userRef)
|
||||
->where('status', 'joined')
|
||||
->whereNotIn('role', ['host', 'co_host'])
|
||||
->update(['role' => 'panelist']);
|
||||
|
||||
return $session->fresh();
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
data-configured="{{ $mediaConfigured ? '1' : '0' }}"
|
||||
data-participant="{{ $participant->uuid }}"
|
||||
data-display-name="{{ $participant->display_name }}"
|
||||
data-is-host="{{ $participant->isHost() ? '1' : '0' }}"
|
||||
data-is-host="{{ ($canManageConference ?? $participant->isHost()) ? '1' : '0' }}"
|
||||
data-poll-url="{{ route('meet.room.poll', $session) }}"
|
||||
data-ended-url="{{ route('meet.ended', $session) }}"
|
||||
data-chat-url="{{ route('meet.room.chat', $session) }}"
|
||||
@@ -59,9 +59,9 @@
|
||||
data-is-conference="{{ ($isConference ?? false) ? '1' : '0' }}"
|
||||
data-is-green-room="{{ ($isGreenRoom ?? false) ? '1' : '0' }}"
|
||||
data-session-mode="{{ $session->session_mode }}"
|
||||
data-go-live-url="{{ ($isConference ?? false) && ($isGreenRoom ?? false) && $participant->isHost() ? route('meet.room.townhall.live', $session) : '' }}"
|
||||
data-add-presenter-url="{{ ($isConference ?? false) && $participant->isHost() ? route('meet.room.townhall.presenters', $session) : '' }}"
|
||||
data-stage-update-url="{{ ($usesStageLayout ?? false) && $participant->isHost() ? route('meet.room.stage.update', $session) : '' }}"
|
||||
data-go-live-url="{{ ($isConference ?? false) && ($isGreenRoom ?? false) && ($canManageConference ?? $participant->isHost()) ? route('meet.room.townhall.live', $session) : '' }}"
|
||||
data-add-presenter-url="{{ ($isConference ?? false) && ($canManageConference ?? $participant->isHost()) ? route('meet.room.townhall.presenters', $session) : '' }}"
|
||||
data-stage-update-url="{{ ($usesStageLayout ?? false) && ($canManageConference ?? $participant->isHost()) ? route('meet.room.stage.update', $session) : '' }}"
|
||||
data-uses-stage-layout="{{ ($usesStageLayout ?? false) ? '1' : '0' }}"
|
||||
data-panel-discussions="{{ ($stageConfig['panel_discussions'] ?? false) ? '1' : '0' }}"
|
||||
data-stage-layout="{{ $stageConfig['stage_layout'] ?? 'plenary' }}"
|
||||
@@ -143,13 +143,13 @@
|
||||
</header>
|
||||
|
||||
<div x-show="isConference && isGreenRoom" x-cloak
|
||||
class="flex shrink-0 items-center justify-between gap-3 border-b border-violet-500/30 bg-violet-500/15 px-4 py-2.5">
|
||||
class="flex shrink-0 flex-col gap-2 border-b border-violet-500/30 bg-violet-500/15 px-4 py-2.5 sm:flex-row sm:items-center sm:justify-between sm:gap-3">
|
||||
<div class="min-w-0 text-sm text-violet-100">
|
||||
<p class="font-medium">Green room</p>
|
||||
<p class="truncate text-xs text-violet-200/90">Only hosts and speakers are visible. Attendees join after you go live.</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<button x-show="isHost && usesStageLayout && panelDiscussions" @click="panelSetupOpen = true" type="button"
|
||||
<div class="flex shrink-0 flex-wrap items-center gap-2">
|
||||
<button x-show="isHost && usesStageLayout" @click="panelSetupOpen = true" type="button"
|
||||
class="shrink-0 rounded-lg border border-violet-400/40 bg-violet-500/20 px-3 py-1.5 text-xs font-semibold text-violet-100 transition-colors hover:bg-violet-500/30">
|
||||
@include('meet.room.partials.meet-icon', ['icon' => 'panel', 'class' => 'mr-1 inline h-3.5 w-3.5'])
|
||||
Panels
|
||||
|
||||
@@ -749,6 +749,44 @@ class MeetWebTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_green_room_register_presenter_keeps_host_role(): void
|
||||
{
|
||||
$room = Room::create([
|
||||
'owner_ref' => $this->user->public_id,
|
||||
'organization_id' => $this->organization->id,
|
||||
'host_user_ref' => $this->user->public_id,
|
||||
'title' => 'NextGen Summit',
|
||||
'type' => 'town_hall',
|
||||
'status' => 'live',
|
||||
'scheduled_at' => now()->addHour(),
|
||||
'timezone' => 'UTC',
|
||||
'settings' => config('meet.default_settings'),
|
||||
]);
|
||||
|
||||
$session = Session::create([
|
||||
'owner_ref' => $this->user->public_id,
|
||||
'room_id' => $room->id,
|
||||
'media_room_name' => 'meet-'.$room->uuid.'-green',
|
||||
'status' => 'live',
|
||||
'session_mode' => 'green_room',
|
||||
'started_at' => now(),
|
||||
]);
|
||||
|
||||
$participant = \App\Models\Participant::create([
|
||||
'owner_ref' => $this->user->public_id,
|
||||
'session_id' => $session->id,
|
||||
'user_ref' => $this->user->public_id,
|
||||
'display_name' => $this->user->name,
|
||||
'role' => 'host',
|
||||
'status' => 'joined',
|
||||
'joined_at' => now(),
|
||||
]);
|
||||
|
||||
app(\App\Services\Meet\ConferenceService::class)->registerPresenter($session, $this->user, 'host');
|
||||
|
||||
$this->assertSame('host', $participant->fresh()->role);
|
||||
}
|
||||
|
||||
public function test_host_can_end_conference_and_view_details(): void
|
||||
{
|
||||
$room = Room::create([
|
||||
|
||||
Reference in New Issue
Block a user