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')
+
+ @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)