2026-01-22 23:38:00 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Livewire;
|
|
|
|
|
|
2026-07-25 20:15:52 +02:00
|
|
|
use App\Actions\CreateChannelAction;
|
|
|
|
|
use App\Models\Language;
|
2026-01-22 23:38:00 +01:00
|
|
|
use App\Models\PlatformAccount;
|
|
|
|
|
use App\Models\PlatformChannel;
|
2026-07-25 20:15:52 +02:00
|
|
|
use App\Models\PlatformInstance;
|
2026-03-18 20:01:25 +01:00
|
|
|
use Illuminate\Contracts\View\View;
|
2026-07-29 20:15:43 +02:00
|
|
|
use Illuminate\Database\UniqueConstraintViolationException;
|
2026-07-25 20:15:52 +02:00
|
|
|
use Illuminate\Validation\Rule;
|
2026-01-22 23:38:00 +01:00
|
|
|
use Livewire\Component;
|
2026-07-25 20:15:52 +02:00
|
|
|
use RuntimeException;
|
2026-01-22 23:38:00 +01:00
|
|
|
|
|
|
|
|
class Channels extends Component
|
|
|
|
|
{
|
|
|
|
|
public ?int $managingChannelId = null;
|
|
|
|
|
|
2026-07-25 20:15:52 +02:00
|
|
|
public bool $showCreateModal = false;
|
|
|
|
|
|
|
|
|
|
public string $newName = '';
|
|
|
|
|
|
|
|
|
|
public ?int $newPlatformInstanceId = null;
|
|
|
|
|
|
|
|
|
|
public ?int $newLanguageId = null;
|
|
|
|
|
|
|
|
|
|
public string $newDescription = '';
|
|
|
|
|
|
2026-01-22 23:38:00 +01:00
|
|
|
public function toggle(int $channelId): void
|
|
|
|
|
{
|
|
|
|
|
$channel = PlatformChannel::findOrFail($channelId);
|
2026-03-08 14:18:28 +01:00
|
|
|
$channel->is_active = ! $channel->is_active;
|
2026-01-22 23:38:00 +01:00
|
|
|
$channel->save();
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-25 20:15:52 +02:00
|
|
|
public function openCreateModal(): void
|
|
|
|
|
{
|
|
|
|
|
$this->reset(['newName', 'newPlatformInstanceId', 'newLanguageId', 'newDescription']);
|
|
|
|
|
$this->resetErrorBag();
|
|
|
|
|
$this->showCreateModal = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function closeCreateModal(): void
|
|
|
|
|
{
|
|
|
|
|
$this->showCreateModal = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function createChannel(CreateChannelAction $action): void
|
|
|
|
|
{
|
|
|
|
|
$this->validate([
|
|
|
|
|
// name doubles as the Lemmy community slug (used verbatim as channel_id for
|
|
|
|
|
// community lookup at publish time), so it must be lowercase slug format.
|
|
|
|
|
'newName' => [
|
|
|
|
|
'required',
|
|
|
|
|
'string',
|
|
|
|
|
'max:255',
|
|
|
|
|
'regex:/^[a-z0-9_]+$/',
|
|
|
|
|
Rule::unique('platform_channels', 'name')
|
|
|
|
|
->where('platform_instance_id', $this->newPlatformInstanceId),
|
|
|
|
|
],
|
|
|
|
|
'newPlatformInstanceId' => 'required|integer|exists:platform_instances,id',
|
|
|
|
|
'newLanguageId' => 'nullable|integer|exists:languages,id',
|
|
|
|
|
], [
|
|
|
|
|
'newName.regex' => 'The name must be a valid community slug (lowercase letters, numbers, and underscores only).',
|
|
|
|
|
'newName.unique' => 'A channel with this name already exists for this instance.',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$action->execute(
|
|
|
|
|
$this->newName,
|
|
|
|
|
$this->newPlatformInstanceId,
|
|
|
|
|
$this->newLanguageId,
|
|
|
|
|
// Blade textarea binds an empty string when blank; the action expects null for "no description".
|
|
|
|
|
$this->newDescription !== '' ? $this->newDescription : null,
|
|
|
|
|
);
|
2026-07-29 20:15:43 +02:00
|
|
|
} catch (UniqueConstraintViolationException $e) {
|
|
|
|
|
// Unreachable via this form (the unique rule above catches duplicates first),
|
|
|
|
|
// but the (platform_instance_id, channel_id) index can still fire if channel_id
|
|
|
|
|
// ever drifts from name. Surface it as a field error instead of a 500.
|
|
|
|
|
$this->addError('newName', 'A channel with this name already exists for this instance.');
|
|
|
|
|
|
|
|
|
|
return;
|
2026-07-25 20:15:52 +02:00
|
|
|
} catch (RuntimeException $e) {
|
|
|
|
|
$this->addError('newPlatformInstanceId', $e->getMessage());
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->closeCreateModal();
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 23:38:00 +01:00
|
|
|
public function openAccountModal(int $channelId): void
|
|
|
|
|
{
|
|
|
|
|
$this->managingChannelId = $channelId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function closeAccountModal(): void
|
|
|
|
|
{
|
|
|
|
|
$this->managingChannelId = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function attachAccount(int $accountId): void
|
|
|
|
|
{
|
2026-03-08 14:18:28 +01:00
|
|
|
if (! $this->managingChannelId) {
|
2026-01-22 23:38:00 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$channel = PlatformChannel::findOrFail($this->managingChannelId);
|
|
|
|
|
|
2026-03-08 14:18:28 +01:00
|
|
|
if (! $channel->platformAccounts()->where('platform_account_id', $accountId)->exists()) {
|
2026-01-22 23:38:00 +01:00
|
|
|
$channel->platformAccounts()->attach($accountId, [
|
|
|
|
|
'is_active' => true,
|
|
|
|
|
'priority' => 1,
|
|
|
|
|
'created_at' => now(),
|
|
|
|
|
'updated_at' => now(),
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function detachAccount(int $channelId, int $accountId): void
|
|
|
|
|
{
|
|
|
|
|
$channel = PlatformChannel::findOrFail($channelId);
|
|
|
|
|
$channel->platformAccounts()->detach($accountId);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-18 20:01:25 +01:00
|
|
|
public function render(): View
|
2026-01-22 23:38:00 +01:00
|
|
|
{
|
|
|
|
|
$channels = PlatformChannel::with(['platformInstance', 'platformAccounts'])->orderBy('name')->get();
|
|
|
|
|
$allAccounts = PlatformAccount::where('is_active', true)->get();
|
|
|
|
|
|
|
|
|
|
$managingChannel = $this->managingChannelId
|
|
|
|
|
? PlatformChannel::with('platformAccounts')->find($this->managingChannelId)
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
$availableAccounts = $managingChannel
|
2026-03-08 14:18:28 +01:00
|
|
|
? $allAccounts->filter(fn ($account) => ! $managingChannel->platformAccounts->contains('id', $account->id))
|
2026-01-22 23:38:00 +01:00
|
|
|
: collect();
|
|
|
|
|
|
|
|
|
|
return view('livewire.channels', [
|
|
|
|
|
'channels' => $channels,
|
|
|
|
|
'managingChannel' => $managingChannel,
|
|
|
|
|
'availableAccounts' => $availableAccounts,
|
2026-07-25 20:15:52 +02:00
|
|
|
'platformInstances' => PlatformInstance::where('is_active', true)->orderBy('name')->get(),
|
|
|
|
|
'languages' => Language::where('is_active', true)->orderBy('name')->get(),
|
2026-01-22 23:38:00 +01:00
|
|
|
])->layout('layouts.app');
|
|
|
|
|
}
|
|
|
|
|
}
|