From 6db1d8273885ba062a0f02d74a95a0b1b8ef1ca2 Mon Sep 17 00:00:00 2001 From: JoanFo <161775222+JoanFo1456@users.noreply.github.com> Date: Thu, 18 Sep 2025 16:40:24 +0200 Subject: [PATCH] Fixed webhooks on v4 and nested values (#1704) Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com> --- .../Pages/EditWebhookConfiguration.php | 5 +- .../Resources/Webhooks/WebhookResource.php | 4 +- app/Models/WebhookConfiguration.php | 217 +++++++++++++++--- .../components/webhooksection.blade.php | 104 +++++++-- 4 files changed, 272 insertions(+), 58 deletions(-) diff --git a/app/Filament/Admin/Resources/Webhooks/Pages/EditWebhookConfiguration.php b/app/Filament/Admin/Resources/Webhooks/Pages/EditWebhookConfiguration.php index 07a86e591..bbf4b711f 100644 --- a/app/Filament/Admin/Resources/Webhooks/Pages/EditWebhookConfiguration.php +++ b/app/Filament/Admin/Resources/Webhooks/Pages/EditWebhookConfiguration.php @@ -41,7 +41,7 @@ class EditWebhookConfiguration extends EditRecord protected function mutateFormDataBeforeSave(array $data): array { - if (($data['type'] ?? null) === WebhookType::Discord->value) { + if (($data['type'] ?? null) === WebhookType::Discord) { $embeds = data_get($data, 'embeds', []); foreach ($embeds as &$embed) { @@ -68,7 +68,7 @@ class EditWebhookConfiguration extends EditRecord $data['payload'] = $tmp; } - if (($data['type'] ?? null) === WebhookType::Regular->value && isset($data['headers']) && is_array($data['headers'])) { + if (($data['type'] ?? null) === WebhookType::Regular && isset($data['headers'])) { $newHeaders = []; foreach ($data['headers'] as $key => $value) { $newKey = str_replace(' ', '-', $key); @@ -84,7 +84,6 @@ class EditWebhookConfiguration extends EditRecord { if (($data['type'] ?? null) === WebhookType::Discord->value) { $embeds = data_get($data, 'payload.embeds', []); - foreach ($embeds as &$embed) { $embed['color'] = '#' . dechex(data_get($embed, 'color')); $embed = collect($embed)->filter(fn ($key) => is_array($key) ? array_filter($key, fn ($arr_key) => !empty($arr_key)) : !empty($key))->all(); diff --git a/app/Filament/Admin/Resources/Webhooks/WebhookResource.php b/app/Filament/Admin/Resources/Webhooks/WebhookResource.php index a8385a3a6..42cb4cc1f 100644 --- a/app/Filament/Admin/Resources/Webhooks/WebhookResource.php +++ b/app/Filament/Admin/Resources/Webhooks/WebhookResource.php @@ -133,7 +133,7 @@ class WebhookResource extends Resource ->live() ->inline() ->options(WebhookType::class) - ->default(WebhookType::Regular->value), + ->default(WebhookType::Regular), TextInput::make('description') ->label(trans('admin/webhook.description')) ->required(), @@ -144,7 +144,6 @@ class WebhookResource extends Resource ->afterStateUpdated(fn (string $state, Set $set) => $set('type', str($state)->contains('discord.com') ? WebhookType::Discord : WebhookType::Regular)), Section::make(trans('admin/webhook.regular')) ->hidden(fn (Get $get) => $get('type') === WebhookType::Discord) - ->dehydratedWhenHidden() ->schema(fn () => self::getRegularFields()) ->headerActions([ Action::make('reset_headers') @@ -158,7 +157,6 @@ class WebhookResource extends Resource ->formBefore(), Section::make(trans('admin/webhook.discord')) ->hidden(fn (Get $get) => $get('type') === WebhookType::Regular) - ->dehydratedWhenHidden() ->afterStateUpdated(fn (Livewire $livewire) => $livewire->dispatch('refresh-widget')) ->schema(fn () => self::getDiscordFields()) ->view('filament.components.webhooksection') diff --git a/app/Models/WebhookConfiguration.php b/app/Models/WebhookConfiguration.php index 45df7f23f..85cf303f0 100644 --- a/app/Models/WebhookConfiguration.php +++ b/app/Models/WebhookConfiguration.php @@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\File; use Livewire\Features\SupportEvents\HandlesEvents; @@ -181,7 +180,7 @@ class WebhookConfiguration extends Model function ($matches) use ($replacement) { $trimmed = trim($matches[1]); - return Arr::get($replacement, $trimmed, $trimmed); + return data_get($replacement, $trimmed, $trimmed); }, $subject ); @@ -191,7 +190,7 @@ class WebhookConfiguration extends Model public function run(?string $eventName = null, ?array $eventData = null): void { $eventName ??= 'eloquent.created: '.Server::class; - $eventData ??= $this->getWebhookSampleData(); + $eventData ??= static::getWebhookSampleData(); ProcessWebhook::dispatch($this, $eventName, [$eventData]); } @@ -199,37 +198,201 @@ class WebhookConfiguration extends Model /** * @return array */ - public function getWebhookSampleData(): array + public static function getWebhookSampleData(): array { return [ - 'status' => 'installing', - 'oom_killer' => false, - 'installed_at' => null, - 'external_id' => 10, - 'uuid' => '651fgbc1-dee6-4250-814e-10slda13f1e', - 'uuid_short' => '651fgbc1', + 'id' => 4, + 'uuid' => '4864a058-9a3b-44a9-a6cf-c1355e89406e', + 'uuid_short' => '4864a058', 'node_id' => 1, - 'name' => 'Eagle', + 'name' => 'Example Server', + 'owner_id' => 1, + 'memory' => 6144, + 'swap' => 0, + 'disk' => 20480, + 'io' => 500, + 'cpu' => 300, + 'egg_id' => 1, + 'startup' => 'java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}', + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-11T22:45:14.000000Z', + 'allocation_id' => 4, + 'image' => 'ghcr.io/parkervcp/yolks:java_21', 'description' => 'This is an example server description.', 'skip_scripts' => false, - 'owner_id' => 1, - 'memory' => 2048, - 'swap' => 128, - 'disk' => 10240, - 'io' => 500, - 'cpu' => 100, - 'threads' => '1,3,5', - 'allocation_id' => 4, - 'egg_id' => 2, - 'startup' => 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}', - 'image' => 'ghcr.io/parkervcp/yolks:java_21', - 'database_limit' => 1, + 'external_id' => null, + 'database_limit' => 5, 'allocation_limit' => 5, - 'backup_limit' => 3, + 'threads' => null, + 'backup_limit' => 5, + 'status' => null, + 'installed_at' => '2025-09-06T03:02:31.000000Z', + 'oom_killer' => false, 'docker_labels' => [], - 'created_at' => '2025-03-17T15:20:32.000000Z', - 'updated_at' => '2025-05-12T17:53:12.000000Z', - 'id' => 2, + 'allocation' => [ + 'id' => 4, + 'node_id' => 1, + 'ip' => '0.0.0.0', + 'port' => 25565, + 'server_id' => 4, + 'created_at' => '2025-07-01T20:12:41.000000Z', + 'updated_at' => '2025-09-09T17:47:22.000000Z', + 'ip_alias' => null, + 'notes' => null, + ], + 'variables' => [ + [ + 'id' => 1, + 'egg_id' => 1, + 'name' => 'Build Number', + 'description' => 'The build number for the paper release.\r\n\r\nLeave at latest to always get the latest version. Invalid versions will default to latest.', + 'env_variable' => 'BUILD_NUMBER', + 'default_value' => 'latest', + 'user_viewable' => true, + 'user_editable' => true, + 'rules' => ['required', 'string', 'max:20'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 4, + 'server_value' => 'latest', + ], + [ + 'id' => 2, + 'egg_id' => 1, + 'name' => 'Download Path', + 'description' => 'A URL to use to download a server.jar rather than the ones in the install script. This is not user\nviewable.', + 'env_variable' => 'DL_PATH', + 'default_value' => '', + 'user_viewable' => false, + 'user_editable' => false, + 'rules' => ['nullable', 'string'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 3, + 'server_value' => '', + ], + [ + 'id' => 3, + 'egg_id' => 1, + 'name' => 'Minecraft Version', + 'description' => 'The version of minecraft to download. \r\n\r\nLeave at latest to always get the latest version. Invalid versions will default to latest.', + 'env_variable' => 'MINECRAFT_VERSION', + 'default_value' => 'latest', + 'user_viewable' => true, + 'user_editable' => true, + 'rules' => ['nullable', 'string', 'max:20'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 1, + 'server_value' => '1.21.8', + ], + [ + 'id' => 4, + 'egg_id' => 1, + 'name' => 'Server Jar File', + 'description' => 'The name of the server jarfile to run the server with.', + 'env_variable' => 'SERVER_JARFILE', + 'default_value' => 'server.jar', + 'user_viewable' => true, + 'user_editable' => true, + 'rules' => ['required', 'regex:/^([\w\d._-]+)(\.jar)$/'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 2, + 'server_value' => 'server.jar', + ], + ], + 'server_variables' => [ + 'record-21' => [ + 'id' => 21, + 'server_id' => 4, + 'variable_id' => 3, + 'variable_value' => '1.21.8', + 'created_at' => '2025-09-06T06:00:58.000000Z', + 'updated_at' => '2025-09-09T17:59:40.000000Z', + 'variable' => [ + 'id' => 3, + 'egg_id' => 1, + 'name' => 'Minecraft Version', + 'description' => 'The version of minecraft to download. \r\n\r\nLeave at latest to always get the latest version. Invalid versions will default to latest.', + 'env_variable' => 'MINECRAFT_VERSION', + 'default_value' => 'latest', + 'user_viewable' => true, + 'user_editable' => true, + 'rules' => ['nullable', 'string', 'max:20'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 1, + ], + ], + 'record-22' => [ + 'id' => 22, + 'server_id' => 4, + 'variable_id' => 4, + 'variable_value' => 'server.jar', + 'created_at' => '2025-09-06T06:00:58.000000Z', + 'updated_at' => '2025-09-06T06:01:05.000000Z', + 'variable' => [ + 'id' => 4, + 'egg_id' => 1, + 'name' => 'Server Jar File', + 'description' => 'The name of the server jarfile to run the server with.', + 'env_variable' => 'SERVER_JARFILE', + 'default_value' => 'server.jar', + 'user_viewable' => true, + 'user_editable' => true, + 'rules' => ['required', 'regex:/^([\w\d._-]+)(\.jar)$/'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 2, + ], + ], + 'record-20' => [ + 'id' => 20, + 'server_id' => 4, + 'variable_id' => 2, + 'variable_value' => '', + 'created_at' => '2025-09-06T06:00:58.000000Z', + 'updated_at' => '2025-09-06T06:00:58.000000Z', + 'variable' => [ + 'id' => 2, + 'egg_id' => 1, + 'name' => 'Download Path', + 'description' => 'A URL to use to download a server.jar rather than the ones in the install script. This is not user\nviewable.', + 'env_variable' => 'DL_PATH', + 'default_value' => '', + 'user_viewable' => false, + 'user_editable' => false, + 'rules' => ['nullable', 'string'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 3, + ], + ], + 'record-19' => [ + 'id' => 19, + 'server_id' => 4, + 'variable_id' => 1, + 'variable_value' => 'latest', + 'created_at' => '2025-09-06T06:00:58.000000Z', + 'updated_at' => '2025-09-06T06:00:58.000000Z', + 'variable' => [ + 'id' => 1, + 'egg_id' => 1, + 'name' => 'Build Number', + 'description' => 'The build number for the paper release.\r\n\r\nLeave at latest to always get the latest version. Invalid versions will default to latest.', + 'env_variable' => 'BUILD_NUMBER', + 'default_value' => 'latest', + 'user_viewable' => true, + 'user_editable' => true, + 'rules' => ['required', 'string', 'max:20'], + 'created_at' => '2025-09-05T01:15:43.000000Z', + 'updated_at' => '2025-09-05T01:15:43.000000Z', + 'sort' => 4, + ], + ], + ], + 'event' => 'updated: Server', ]; } } diff --git a/resources/views/filament/components/webhooksection.blade.php b/resources/views/filament/components/webhooksection.blade.php index d635c6925..ae290339f 100644 --- a/resources/views/filament/components/webhooksection.blade.php +++ b/resources/views/filament/components/webhooksection.blade.php @@ -1,26 +1,80 @@ - - - @livewire(App\Filament\Admin\Widgets\DiscordPreview::class, ['record' => $getRecord(), 'pollingInterval' => $pollingInterval ?? null]) - +@php + $afterHeader = $getChildSchema($schemaComponent::AFTER_HEADER_SCHEMA_KEY)?->toHtmlString(); + $isAside = $isAside(); + $isCollapsed = $isCollapsed(); + $isCollapsible = $isCollapsible(); + $isCompact = $isCompact(); + $isContained = $isContained(); + $isDivided = $isDivided(); + $isFormBefore = $isFormBefore(); + $description = $getDescription(); + $footer = $getChildSchema($schemaComponent::FOOTER_SCHEMA_KEY)?->toHtmlString(); + $heading = $getHeading(); + $headingTag = $getHeadingTag(); + $icon = $getIcon(); + $iconColor = $getIconColor(); + $iconSize = $getIconSize(); + $shouldPersistCollapsed = $shouldPersistCollapsed(); + $isSecondary = $isSecondary(); + $id = $getId(); +@endphp - {{ $getChildComponentContainer() }} - +
merge([ + 'id' => $id, + ], escape: false) + ->merge($getExtraAttributes(), escape: false) + ->merge($getExtraAlpineAttributes(), escape: false) + ->class(['fi-sc-section']) + }} +> + @if (filled($label = $getLabel())) + + @endif + + @if ($aboveContentContainer = $getChildSchema($schemaComponent::ABOVE_CONTENT_SCHEMA_KEY)?->toHtmlString()) + {{ $aboveContentContainer }} + @endif + + + + @livewire(App\Filament\Admin\Widgets\DiscordPreview::class, ['record' => $getRecord(), 'pollingInterval' => $pollingInterval ?? null]) + + + {{ $getChildSchema()->gap(! $isDivided)->extraAttributes(['class' => 'fi-section-content']) }} + + + @if ($belowContentContainer = $getChildSchema($schemaComponent::BELOW_CONTENT_SCHEMA_KEY)?->toHtmlString()) + {{ $belowContentContainer }} + @endif +