From f98d66c9f9c46dc4ca692c903a63b551379e856b Mon Sep 17 00:00:00 2001 From: isaacclad Date: Wed, 1 Jul 2026 21:29:22 +0000 Subject: [PATCH] Add panel discussions option to webinars and widen audience strip. Webinars can enable multi-speaker stage layout at creation or on the details page; plenary view shows 12 attendee avatars before the overflow count. Co-authored-by: Cursor --- .../Controllers/Meet/WebinarController.php | 24 +++++++++++++++++++ resources/js/meet-room.js | 2 +- .../views/meet/webinars/create.blade.php | 1 + resources/views/meet/webinars/show.blade.php | 19 +++++++++++++++ routes/web.php | 1 + tests/Feature/MeetWebTest.php | 24 +++++++++++++++++++ 6 files changed, 70 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Meet/WebinarController.php b/app/Http/Controllers/Meet/WebinarController.php index ec4c6af..fe111bc 100644 --- a/app/Http/Controllers/Meet/WebinarController.php +++ b/app/Http/Controllers/Meet/WebinarController.php @@ -82,6 +82,7 @@ class WebinarController extends Controller 'auto_record' => ['sometimes', 'boolean'], 'live_captions' => ['sometimes', 'boolean'], 'webinar_auto_approve' => ['sometimes', 'boolean'], + 'panel_discussions' => ['sometimes', 'boolean'], ]); $settings = [ @@ -91,6 +92,9 @@ class WebinarController extends Controller 'auto_record' => $request->boolean('auto_record'), 'live_captions' => $request->boolean('live_captions'), 'webinar_auto_approve' => $request->boolean('webinar_auto_approve'), + 'panel_discussions' => $request->boolean('panel_discussions'), + 'stage_layout' => 'plenary', + 'panels' => [], 'stage_mode' => true, ]; @@ -154,4 +158,24 @@ class WebinarController extends Controller return redirect()->route('meet.room', $session); } + + public function updateSettings(Request $request, Room $room): RedirectResponse + { + $this->authorizeAbility($request, 'meetings.manage'); + $this->authorizeOwner($request, $room); + abort_unless($room->isWebinar(), 404); + + $request->validate([ + 'panel_discussions' => ['sometimes', 'boolean'], + ]); + + if ($request->has('panel_discussions')) { + $settings = array_merge($room->settings ?? [], [ + 'panel_discussions' => $request->boolean('panel_discussions'), + ]); + $room->update(['settings' => $settings]); + } + + return redirect()->route('meet.webinars.show', $room)->with('success', 'Webinar settings updated.'); + } } diff --git a/resources/js/meet-room.js b/resources/js/meet-room.js index 770cc09..c6d3ca9 100644 --- a/resources/js/meet-room.js +++ b/resources/js/meet-room.js @@ -697,7 +697,7 @@ function meetRoom() { return; } - const maxVisible = 8; + const maxVisible = 12; const visible = audience.slice(0, maxVisible); const overflow = audience.length - visible.length; diff --git a/resources/views/meet/webinars/create.blade.php b/resources/views/meet/webinars/create.blade.php index f4e8897..88a6be1 100644 --- a/resources/views/meet/webinars/create.blade.php +++ b/resources/views/meet/webinars/create.blade.php @@ -72,6 +72,7 @@ + diff --git a/resources/views/meet/webinars/show.blade.php b/resources/views/meet/webinars/show.blade.php index 43ac4e1..7266dfc 100644 --- a/resources/views/meet/webinars/show.blade.php +++ b/resources/views/meet/webinars/show.blade.php @@ -20,6 +20,12 @@ @endif + @if (session('success')) +
+ {{ session('success') }} +
+ @endif +
Billed at GHS {{ number_format(config('meet.billing.price_per_participant_ghs', 0.30), 2) }} per participant (peak attendance when the session ends).
@@ -63,6 +69,19 @@ Scheduled: {{ $room->scheduled_at->timezone($room->timezone)->format('M j, Y g:i A T') }}

@endif + + @if ($room->status === 'scheduled') +
+ @csrf +

Stage layout

+ + +
+ @endif @php diff --git a/routes/web.php b/routes/web.php index 57754f8..ffb2726 100644 --- a/routes/web.php +++ b/routes/web.php @@ -134,6 +134,7 @@ Route::middleware(['auth', 'platform.session'])->group(function () { Route::post('/webinars', [WebinarController::class, 'store'])->name('meet.webinars.store'); Route::get('/webinars/{room}', [WebinarController::class, 'show'])->name('meet.webinars.show'); Route::post('/webinars/{room}/start', [WebinarController::class, 'start'])->name('meet.webinars.start'); + Route::post('/webinars/{room}/settings', [WebinarController::class, 'updateSettings'])->name('meet.webinars.settings.update'); Route::get('/conferences', [ConferenceController::class, 'index'])->name('meet.conferences.index'); Route::get('/conferences/create', [ConferenceController::class, 'create'])->name('meet.conferences.create'); diff --git a/tests/Feature/MeetWebTest.php b/tests/Feature/MeetWebTest.php index 43f5263..1ee8c0a 100644 --- a/tests/Feature/MeetWebTest.php +++ b/tests/Feature/MeetWebTest.php @@ -614,6 +614,30 @@ class MeetWebTest extends TestCase ]); } + public function test_host_can_enable_panel_discussions_on_webinar(): void + { + $this->actingAs($this->user) + ->post('/webinars', [ + 'title' => 'Panel webinar', + 'scheduled_at' => now()->addDay()->format('Y-m-d\TH:i'), + 'duration_minutes' => 60, + 'panel_discussions' => '1', + ]) + ->assertRedirect(); + + $room = Room::where('title', 'Panel webinar')->firstOrFail(); + $this->assertTrue($room->setting('panel_discussions')); + $this->assertSame('plenary', $room->setting('stage_layout')); + + $this->actingAs($this->user) + ->post(route('meet.webinars.settings.update', $room), [ + 'panel_discussions' => '0', + ]) + ->assertRedirect(route('meet.webinars.show', $room)); + + $this->assertFalse($room->fresh()->setting('panel_discussions')); + } + public function test_user_can_create_channel_and_post_message(): void { $this->actingAs($this->user)