Add panel discussions option to webinars and widen audience strip.
Deploy Ladill Meet / deploy (push) Successful in 2m1s
Deploy Ladill Meet / deploy (push) Successful in 2m1s
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 <cursoragent@cursor.com>
This commit is contained in:
@@ -82,6 +82,7 @@ class WebinarController extends Controller
|
|||||||
'auto_record' => ['sometimes', 'boolean'],
|
'auto_record' => ['sometimes', 'boolean'],
|
||||||
'live_captions' => ['sometimes', 'boolean'],
|
'live_captions' => ['sometimes', 'boolean'],
|
||||||
'webinar_auto_approve' => ['sometimes', 'boolean'],
|
'webinar_auto_approve' => ['sometimes', 'boolean'],
|
||||||
|
'panel_discussions' => ['sometimes', 'boolean'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$settings = [
|
$settings = [
|
||||||
@@ -91,6 +92,9 @@ class WebinarController extends Controller
|
|||||||
'auto_record' => $request->boolean('auto_record'),
|
'auto_record' => $request->boolean('auto_record'),
|
||||||
'live_captions' => $request->boolean('live_captions'),
|
'live_captions' => $request->boolean('live_captions'),
|
||||||
'webinar_auto_approve' => $request->boolean('webinar_auto_approve'),
|
'webinar_auto_approve' => $request->boolean('webinar_auto_approve'),
|
||||||
|
'panel_discussions' => $request->boolean('panel_discussions'),
|
||||||
|
'stage_layout' => 'plenary',
|
||||||
|
'panels' => [],
|
||||||
'stage_mode' => true,
|
'stage_mode' => true,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -154,4 +158,24 @@ class WebinarController extends Controller
|
|||||||
|
|
||||||
return redirect()->route('meet.room', $session);
|
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.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -697,7 +697,7 @@ function meetRoom() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxVisible = 8;
|
const maxVisible = 12;
|
||||||
const visible = audience.slice(0, maxVisible);
|
const visible = audience.slice(0, maxVisible);
|
||||||
const overflow = audience.length - visible.length;
|
const overflow = audience.length - visible.length;
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="auto_record" value="1" @checked(old('auto_record')) class="rounded border-slate-300"> Auto-record</label>
|
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="auto_record" value="1" @checked(old('auto_record')) class="rounded border-slate-300"> Auto-record</label>
|
||||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="live_captions" value="1" @checked(old('live_captions')) class="rounded border-slate-300"> Live captions</label>
|
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="live_captions" value="1" @checked(old('live_captions')) class="rounded border-slate-300"> Live captions</label>
|
||||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="webinar_auto_approve" value="1" @checked(old('webinar_auto_approve')) class="rounded border-slate-300"> Auto-approve registrations</label>
|
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="webinar_auto_approve" value="1" @checked(old('webinar_auto_approve')) class="rounded border-slate-300"> Auto-approve registrations</label>
|
||||||
|
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="panel_discussions" value="1" @checked(old('panel_discussions')) class="rounded border-slate-300"> Enable panel discussions (multi-speaker stage layout)</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<button type="submit" class="btn-primary btn-primary-lg w-full">Create webinar</button>
|
<button type="submit" class="btn-primary btn-primary-lg w-full">Create webinar</button>
|
||||||
|
|||||||
@@ -20,6 +20,12 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if (session('success'))
|
||||||
|
<div class="mt-4 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">
|
||||||
|
{{ session('success') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="mt-4 rounded-xl border border-indigo-100 bg-indigo-50 px-4 py-3 text-sm text-indigo-900">
|
<div class="mt-4 rounded-xl border border-indigo-100 bg-indigo-50 px-4 py-3 text-sm text-indigo-900">
|
||||||
Billed at <span class="font-medium">GHS {{ number_format(config('meet.billing.price_per_participant_ghs', 0.30), 2) }} per participant</span> (peak attendance when the session ends).
|
Billed at <span class="font-medium">GHS {{ number_format(config('meet.billing.price_per_participant_ghs', 0.30), 2) }} per participant</span> (peak attendance when the session ends).
|
||||||
</div>
|
</div>
|
||||||
@@ -63,6 +69,19 @@
|
|||||||
Scheduled: {{ $room->scheduled_at->timezone($room->timezone)->format('M j, Y g:i A T') }}
|
Scheduled: {{ $room->scheduled_at->timezone($room->timezone)->format('M j, Y g:i A T') }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if ($room->status === 'scheduled')
|
||||||
|
<form method="POST" action="{{ route('meet.webinars.settings.update', $room) }}" class="mt-6 border-t border-slate-100 pt-6">
|
||||||
|
@csrf
|
||||||
|
<h2 class="text-sm font-medium text-slate-700">Stage layout</h2>
|
||||||
|
<label class="mt-3 flex items-center gap-2 text-sm text-slate-700">
|
||||||
|
<input type="checkbox" name="panel_discussions" value="1"
|
||||||
|
@checked(old('panel_discussions', $room->setting('panel_discussions'))) class="rounded border-slate-300">
|
||||||
|
Enable panel discussions (multi-speaker stage layout)
|
||||||
|
</label>
|
||||||
|
<button type="submit" class="btn-primary btn-primary-sm mt-3">Save settings</button>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@php
|
@php
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ Route::middleware(['auth', 'platform.session'])->group(function () {
|
|||||||
Route::post('/webinars', [WebinarController::class, 'store'])->name('meet.webinars.store');
|
Route::post('/webinars', [WebinarController::class, 'store'])->name('meet.webinars.store');
|
||||||
Route::get('/webinars/{room}', [WebinarController::class, 'show'])->name('meet.webinars.show');
|
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}/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', [ConferenceController::class, 'index'])->name('meet.conferences.index');
|
||||||
Route::get('/conferences/create', [ConferenceController::class, 'create'])->name('meet.conferences.create');
|
Route::get('/conferences/create', [ConferenceController::class, 'create'])->name('meet.conferences.create');
|
||||||
|
|||||||
@@ -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
|
public function test_user_can_create_channel_and_post_message(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($this->user)
|
$this->actingAs($this->user)
|
||||||
|
|||||||
Reference in New Issue
Block a user