diff --git a/app/Http/Controllers/Meet/ConferenceController.php b/app/Http/Controllers/Meet/ConferenceController.php index 3aa0c88..4f1b838 100644 --- a/app/Http/Controllers/Meet/ConferenceController.php +++ b/app/Http/Controllers/Meet/ConferenceController.php @@ -6,14 +6,12 @@ use App\Http\Controllers\Controller; use App\Http\Controllers\Meet\Concerns\ScopesToAccount; use App\Models\Member; use App\Models\Room; -use App\Models\Template; use App\Models\User; use App\Services\Meet\CalendarService; use App\Services\Meet\ConferenceService; use App\Services\Meet\InvitationService; use App\Services\Meet\RoomService; use App\Services\Meet\SessionService; -use App\Services\Meet\TemplateService; use App\Services\Meet\TownHallService; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -26,7 +24,6 @@ class ConferenceController extends Controller public function __construct( protected RoomService $rooms, protected SessionService $sessions, - protected TemplateService $templates, protected InvitationService $invitations, protected CalendarService $calendar, protected TownHallService $townHalls, @@ -55,11 +52,6 @@ class ConferenceController extends Controller $this->authorizeAbility($request, 'meetings.create'); $organization = $this->organization($request); - $templates = Template::owned($this->ownerRef($request)) - ->where('organization_id', $organization->id) - ->orderBy('name') - ->get(); - $members = Member::owned($this->ownerRef($request)) ->where('organization_id', $organization->id) ->where('user_ref', '!=', $this->ownerRef($request)) @@ -68,7 +60,6 @@ class ConferenceController extends Controller return view('meet.conferences.create', [ 'organization' => $organization, - 'templates' => $templates, 'members' => $members, 'timezones' => timezone_identifiers_list(), 'defaultSettings' => config('meet.default_settings'), @@ -87,7 +78,6 @@ class ConferenceController extends Controller 'duration_minutes' => ['nullable', 'integer', 'min:15', 'max:480'], 'timezone' => ['nullable', 'timezone'], 'passcode' => ['nullable', 'string', 'max:20'], - 'template_id' => ['nullable', 'integer', 'exists:meet_templates,id'], 'invite_emails' => ['nullable', 'string'], 'presenter_refs' => ['nullable', 'array'], 'presenter_refs.*' => ['string', 'max:64'], @@ -129,11 +119,6 @@ class ConferenceController extends Controller 'status' => 'scheduled', ]); - if (! empty($validated['template_id'])) { - $template = Template::findOrFail($validated['template_id']); - $data = $this->templates->applyToRoomData($template, $data); - } - $room = $this->rooms->create($request->user(), $organization, $data); if ($emails = trim((string) ($validated['invite_emails'] ?? ''))) { @@ -184,6 +169,8 @@ class ConferenceController extends Controller $canManageSpeakers = app(\App\Services\Meet\MeetPermissions::class) ->can($this->member($request), 'meetings.manage'); + $eventsEventUrl = \App\Support\EventsSourceLink::eventAdminUrl($room); + return view('meet.conferences.show', compact( 'room', 'speakers', @@ -192,6 +179,7 @@ class ConferenceController extends Controller 'memberUsers', 'presenterRefs', 'canManageSpeakers', + 'eventsEventUrl', )); } diff --git a/app/Http/Controllers/Meet/RoomController.php b/app/Http/Controllers/Meet/RoomController.php index 6884ea3..090d789 100644 --- a/app/Http/Controllers/Meet/RoomController.php +++ b/app/Http/Controllers/Meet/RoomController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers\Meet; use App\Http\Controllers\Controller; use App\Http\Controllers\Meet\Concerns\ScopesToAccount; use App\Models\Room; -use App\Models\Template; use App\Services\Meet\AttendanceService; use App\Services\Meet\AvailabilityService; use App\Services\Meet\CalendarService; @@ -14,7 +13,6 @@ use App\Services\Meet\InvitationService; use App\Services\Meet\RecurringMeetingService; use App\Services\Meet\RoomService; use App\Services\Meet\SessionService; -use App\Services\Meet\TemplateService; use chillerlan\QRCode\QRCode; use chillerlan\QRCode\QROptions; use Illuminate\Http\RedirectResponse; @@ -29,7 +27,6 @@ class RoomController extends Controller public function __construct( protected RoomService $rooms, protected SessionService $sessions, - protected TemplateService $templates, protected RecurringMeetingService $recurring, protected InvitationService $invitations, protected CalendarService $calendar, @@ -58,14 +55,8 @@ class RoomController extends Controller $this->authorizeAbility($request, 'meetings.create'); $organization = $this->organization($request); - $templates = Template::owned($this->ownerRef($request)) - ->where('organization_id', $organization->id) - ->orderBy('name') - ->get(); - return view('meet.rooms.create', [ 'organization' => $organization, - 'templates' => $templates, 'timezones' => timezone_identifiers_list(), 'recurrenceRules' => config('meet.recurrence_rules'), 'defaultSettings' => config('meet.default_settings'), @@ -85,7 +76,6 @@ class RoomController extends Controller 'duration_minutes' => ['nullable', 'integer', 'min:15', 'max:480'], 'timezone' => ['nullable', 'timezone'], 'passcode' => ['nullable', 'string', 'max:20'], - 'template_id' => ['nullable', 'integer', 'exists:meet_templates,id'], 'recurrence_rule' => ['nullable', 'string', 'in:'.implode(',', array_keys(config('meet.recurrence_rules')))], 'recurrence_interval' => ['nullable', 'integer', 'min:1', 'max:12'], 'recurrence_until' => ['nullable', 'date'], @@ -113,11 +103,6 @@ class RoomController extends Controller 'timezone' => $validated['timezone'] ?? $organization->timezone, ]); - if (! empty($validated['template_id'])) { - $template = Template::findOrFail($validated['template_id']); - $data = $this->templates->applyToRoomData($template, $data); - } - $isInstant = empty($validated['scheduled_at']); if (! empty($validated['recurrence_rule']) && ! $isInstant) { diff --git a/app/Http/Controllers/Meet/SpaceController.php b/app/Http/Controllers/Meet/SpaceController.php index 30e1cee..abc073a 100644 --- a/app/Http/Controllers/Meet/SpaceController.php +++ b/app/Http/Controllers/Meet/SpaceController.php @@ -6,13 +6,11 @@ use App\Http\Controllers\Controller; use App\Http\Controllers\Meet\Concerns\ScopesToAccount; use App\Models\Member; use App\Models\Room; -use App\Models\Template; use App\Services\Meet\CalendarService; use App\Services\Meet\InvitationService; use App\Services\Meet\RoomService; use App\Services\Meet\SessionService; use App\Services\Meet\SpaceService; -use App\Services\Meet\TemplateService; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; @@ -24,7 +22,6 @@ class SpaceController extends Controller public function __construct( protected RoomService $rooms, protected SessionService $sessions, - protected TemplateService $templates, protected InvitationService $invitations, protected CalendarService $calendar, protected SpaceService $spaces, @@ -53,11 +50,6 @@ class SpaceController extends Controller $organization = $this->organization($request); $owner = $this->ownerRef($request); - $templates = Template::owned($owner) - ->where('organization_id', $organization->id) - ->orderBy('name') - ->get(); - $members = Member::owned($owner) ->where('organization_id', $organization->id) ->where('user_ref', '!=', $owner) @@ -66,7 +58,6 @@ class SpaceController extends Controller return view('meet.spaces.create', [ 'organization' => $organization, - 'templates' => $templates, 'members' => $members, 'timezones' => timezone_identifiers_list(), 'defaultSettings' => config('meet.default_settings'), @@ -85,7 +76,6 @@ class SpaceController extends Controller 'duration_minutes' => ['nullable', 'integer', 'min:15', 'max:480'], 'timezone' => ['nullable', 'timezone'], 'passcode' => ['nullable', 'string', 'max:20'], - 'template_id' => ['nullable', 'integer', 'exists:meet_templates,id'], 'invite_emails' => ['nullable', 'string'], 'speaker_refs' => ['nullable', 'array'], 'speaker_refs.*' => ['string', 'max:64'], @@ -120,11 +110,6 @@ class SpaceController extends Controller unset($data['speaker_refs'], $data['invite_only'], $data['mute_listeners']); - if (! empty($validated['template_id'])) { - $template = Template::findOrFail($validated['template_id']); - $data = $this->templates->applyToRoomData($template, $data); - } - $room = $this->rooms->create($request->user(), $organization, $data); if ($emails = trim((string) ($validated['invite_emails'] ?? ''))) { diff --git a/app/Http/Controllers/Meet/TemplateController.php b/app/Http/Controllers/Meet/TemplateController.php deleted file mode 100644 index b7c547d..0000000 --- a/app/Http/Controllers/Meet/TemplateController.php +++ /dev/null @@ -1,68 +0,0 @@ -authorizeAbility($request, 'meetings.manage'); - $organization = $this->organization($request); - - $templates = Template::owned($this->ownerRef($request)) - ->where('organization_id', $organization->id) - ->orderBy('name') - ->get(); - - return view('meet.templates.index', compact('templates', 'organization')); - } - - public function create(Request $request): View - { - $this->authorizeAbility($request, 'meetings.manage'); - - return view('meet.templates.create', [ - 'defaultSettings' => config('meet.default_settings'), - ]); - } - - public function store(Request $request): RedirectResponse - { - $this->authorizeAbility($request, 'meetings.manage'); - $organization = $this->organization($request); - - $validated = $request->validate([ - 'name' => ['required', 'string', 'max:255'], - 'description' => ['nullable', 'string'], - 'duration_minutes' => ['nullable', 'integer', 'min:15', 'max:480'], - 'is_default' => ['sometimes', 'boolean'], - 'waiting_room' => ['sometimes', 'boolean'], - 'auto_record' => ['sometimes', 'boolean'], - 'live_captions' => ['sometimes', 'boolean'], - ]); - - $this->templates->create($request->user(), $organization, array_merge($validated, [ - 'settings' => [ - 'waiting_room' => $request->boolean('waiting_room', true), - 'auto_record' => $request->boolean('auto_record'), - 'live_captions' => $request->boolean('live_captions'), - ], - ])); - - return redirect()->route('meet.templates.index')->with('success', 'Template saved.'); - } -} diff --git a/app/Http/Controllers/Meet/WebinarController.php b/app/Http/Controllers/Meet/WebinarController.php index fe111bc..89a8d55 100644 --- a/app/Http/Controllers/Meet/WebinarController.php +++ b/app/Http/Controllers/Meet/WebinarController.php @@ -5,12 +5,10 @@ namespace App\Http\Controllers\Meet; use App\Http\Controllers\Controller; use App\Http\Controllers\Meet\Concerns\ScopesToAccount; use App\Models\Room; -use App\Models\Template; use App\Services\Meet\CalendarService; use App\Services\Meet\InvitationService; use App\Services\Meet\RoomService; use App\Services\Meet\SessionService; -use App\Services\Meet\TemplateService; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; @@ -22,7 +20,6 @@ class WebinarController extends Controller public function __construct( protected RoomService $rooms, protected SessionService $sessions, - protected TemplateService $templates, protected InvitationService $invitations, protected CalendarService $calendar, ) {} @@ -49,14 +46,8 @@ class WebinarController extends Controller $this->authorizeAbility($request, 'meetings.create'); $organization = $this->organization($request); - $templates = Template::owned($this->ownerRef($request)) - ->where('organization_id', $organization->id) - ->orderBy('name') - ->get(); - return view('meet.webinars.create', [ 'organization' => $organization, - 'templates' => $templates, 'timezones' => timezone_identifiers_list(), 'defaultSettings' => config('meet.default_settings'), ]); @@ -74,7 +65,6 @@ class WebinarController extends Controller 'duration_minutes' => ['nullable', 'integer', 'min:15', 'max:480'], 'timezone' => ['nullable', 'timezone'], 'passcode' => ['nullable', 'string', 'max:20'], - 'template_id' => ['nullable', 'integer', 'exists:meet_templates,id'], 'invite_emails' => ['nullable', 'string'], 'waiting_room' => ['sometimes', 'boolean'], 'join_before_host' => ['sometimes', 'boolean'], @@ -105,11 +95,6 @@ class WebinarController extends Controller 'status' => 'scheduled', ]); - if (! empty($validated['template_id'])) { - $template = Template::findOrFail($validated['template_id']); - $data = $this->templates->applyToRoomData($template, $data); - } - $room = $this->rooms->create($request->user(), $organization, $data); if ($emails = trim((string) ($validated['invite_emails'] ?? ''))) { @@ -135,7 +120,9 @@ class WebinarController extends Controller $room->load(['sessions.participants', 'invitations', 'sessions.recordings', 'sessions.aiSummaries', 'sessionFiles', 'webinarRegistrations']); - return view('meet.webinars.show', compact('room')); + $eventsEventUrl = \App\Support\EventsSourceLink::eventAdminUrl($room); + + return view('meet.webinars.show', compact('room', 'eventsEventUrl')); } public function start(Request $request, Room $room): RedirectResponse diff --git a/app/Models/Organization.php b/app/Models/Organization.php index 512b777..f014711 100644 --- a/app/Models/Organization.php +++ b/app/Models/Organization.php @@ -37,11 +37,6 @@ class Organization extends Model return $this->hasMany(Member::class, 'organization_id'); } - public function templates(): HasMany - { - return $this->hasMany(Template::class, 'organization_id'); - } - public function securitySetting(string $key, mixed $default = null): mixed { return data_get($this->security_policy, $key, data_get(config('meet.security_defaults'), $key, $default)); diff --git a/app/Models/Room.php b/app/Models/Room.php index 08c87a1..ea1eab0 100644 --- a/app/Models/Room.php +++ b/app/Models/Room.php @@ -19,7 +19,7 @@ class Room extends Model 'uuid', 'owner_ref', 'organization_id', 'branch_id', 'host_user_ref', 'title', 'description', 'type', 'status', 'slug', 'scheduled_at', 'duration_minutes', 'timezone', 'passcode', 'settings', 'source', 'calendar_event_id', - 'template_id', 'recurring_series_id', 'recurrence_rule', 'recurrence_interval', 'recurrence_until', + 'recurring_series_id', 'recurrence_rule', 'recurrence_interval', 'recurrence_until', ]; protected function casts(): array @@ -144,11 +144,6 @@ class Room extends Model return $this->type === 'town_hall'; } - public function template(): BelongsTo - { - return $this->belongsTo(Template::class, 'template_id'); - } - public function isRecurring(): bool { return filled($this->recurrence_rule); diff --git a/app/Models/Template.php b/app/Models/Template.php deleted file mode 100644 index c38bdb9..0000000 --- a/app/Models/Template.php +++ /dev/null @@ -1,50 +0,0 @@ - 'array', 'is_default' => 'boolean']; - } - - protected static function booted(): void - { - static::creating(function (Template $template) { - if (empty($template->uuid)) { - $template->uuid = (string) Str::uuid(); - } - }); - } - - public function getRouteKeyName(): string - { - return 'uuid'; - } - - public function organization(): BelongsTo - { - return $this->belongsTo(Organization::class, 'organization_id'); - } - - public function mergedSettings(): array - { - return array_merge(config('meet.default_settings'), $this->settings ?? []); - } -} diff --git a/app/Services/Meet/RecurringMeetingService.php b/app/Services/Meet/RecurringMeetingService.php index 7ccfb4e..bb3de83 100644 --- a/app/Services/Meet/RecurringMeetingService.php +++ b/app/Services/Meet/RecurringMeetingService.php @@ -72,7 +72,6 @@ class RecurringMeetingService 'timezone' => $parent->timezone, 'passcode' => $parent->passcode, 'settings' => $parent->settings, - 'template_id' => $parent->template_id, 'recurring_series_id' => $parent->recurring_series_id, 'recurrence_rule' => $parent->recurrence_rule, 'recurrence_interval' => $parent->recurrence_interval, diff --git a/app/Services/Meet/TemplateService.php b/app/Services/Meet/TemplateService.php deleted file mode 100644 index a3ad96d..0000000 --- a/app/Services/Meet/TemplateService.php +++ /dev/null @@ -1,42 +0,0 @@ - $data - */ - public function create(User $user, Organization $organization, array $data): Template - { - if ($data['is_default'] ?? false) { - Template::owned($user->ownerRef()) - ->where('organization_id', $organization->id) - ->update(['is_default' => false]); - } - - return Template::create([ - 'owner_ref' => $user->ownerRef(), - 'organization_id' => $organization->id, - 'name' => $data['name'], - 'description' => $data['description'] ?? null, - 'duration_minutes' => $data['duration_minutes'] ?? 60, - 'settings' => array_merge(config('meet.default_settings'), $data['settings'] ?? []), - 'is_default' => (bool) ($data['is_default'] ?? false), - ]); - } - - public function applyToRoomData(Template $template, array $data): array - { - return array_merge($data, [ - 'duration_minutes' => $data['duration_minutes'] ?? $template->duration_minutes, - 'settings' => array_merge($template->mergedSettings(), $data['settings'] ?? []), - 'template_id' => $template->id, - ]); - } -} diff --git a/app/Support/EventsSourceLink.php b/app/Support/EventsSourceLink.php new file mode 100644 index 0000000..83aed9a --- /dev/null +++ b/app/Support/EventsSourceLink.php @@ -0,0 +1,26 @@ +source ?? []); + + if (($source['app'] ?? '') !== 'events') { + return null; + } + + $eventId = (int) ($source['event_id'] ?? 0); + if ($eventId <= 0) { + return null; + } + + $base = rtrim((string) config('meet.events_app_url', 'https://events.ladill.com'), '/'); + + return $base.'/events/'.$eventId.'/attendees'; + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index e3d552c..595ce98 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -27,9 +27,6 @@ return Application::configure(basePath: dirname(__DIR__)) \Illuminate\Support\Facades\Route::bind('summary', function (string $value) { return \App\Models\AiSummary::where('uuid', $value)->firstOrFail(); }); - \Illuminate\Support\Facades\Route::bind('template', function (string $value) { - return \App\Models\Template::where('uuid', $value)->firstOrFail(); - }); \Illuminate\Support\Facades\Route::bind('invitation', function (string $value) { return \App\Models\Invitation::where('uuid', $value)->firstOrFail(); }); diff --git a/config/meet.php b/config/meet.php index 5fbe2e0..c95a4f0 100644 --- a/config/meet.php +++ b/config/meet.php @@ -160,6 +160,8 @@ return [ 'recording.ready', ], + 'events_app_url' => env('LADILL_EVENTS_APP_URL', 'https://events.ladill.com'), + 'calendar' => [ 'google' => [ 'client_id' => env('GOOGLE_CALENDAR_CLIENT_ID'), diff --git a/database/migrations/2026_06_30_170000_drop_meet_templates.php b/database/migrations/2026_06_30_170000_drop_meet_templates.php new file mode 100644 index 0000000..a5f7012 --- /dev/null +++ b/database/migrations/2026_06_30_170000_drop_meet_templates.php @@ -0,0 +1,38 @@ +dropConstrainedForeignId('template_id'); + }); + + Schema::dropIfExists('meet_templates'); + } + + public function down(): void + { + Schema::create('meet_templates', function (Blueprint $table) { + $table->id(); + $table->uuid('uuid')->unique(); + $table->string('owner_ref')->index(); + $table->foreignId('organization_id')->constrained('meet_organizations')->cascadeOnDelete(); + $table->string('name'); + $table->text('description')->nullable(); + $table->unsignedSmallInteger('duration_minutes')->default(60); + $table->json('settings')->nullable(); + $table->boolean('is_default')->default(false); + $table->timestamps(); + $table->softDeletes(); + }); + + Schema::table('meet_rooms', function (Blueprint $table) { + $table->foreignId('template_id')->nullable()->after('source')->constrained('meet_templates')->nullOnDelete(); + }); + } +}; diff --git a/resources/views/meet/conferences/create.blade.php b/resources/views/meet/conferences/create.blade.php index f6a6ae9..49b829f 100644 --- a/resources/views/meet/conferences/create.blade.php +++ b/resources/views/meet/conferences/create.blade.php @@ -6,18 +6,6 @@