Skip to content

Conversation

@Boy132
Copy link
Member

@Boy132 Boy132 commented Jan 12, 2026

No description provided.

@Boy132 Boy132 self-assigned this Jan 12, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 12, 2026

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • app/Filament/Admin/Resources/Servers/Pages/EditServer.php

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Adds a new TabPosition enum and two traits (CanCustomizeTabs, CanCustomizeStaticTabs) to register and compose Filament tabs. Multiple Filament pages/resources (Settings, Eggs, Nodes, Users, EditProfile) were refactored to provide getDefaultTabs() and resolve tabs via getTabs() / static::getTabs() instead of inline tab arrays.

Changes

Cohort / File(s) Summary
Core tab customization
app/Enums/TabPosition.php, app/Traits/Filament/CanCustomizeTabs.php, app/Traits/Filament/CanCustomizeStaticTabs.php
New TabPosition enum (Before, After). Two traits added that maintain protected static array $customTabs, expose public static function registerCustomTabs(TabPosition $position, Tab ...$customTabs): void, and provide getDefaultTabs() / getTabs() to merge Before → default → After tabs.
Settings page
app/Filament/Admin/Pages/Settings.php
Added use App\Traits\Filament\CanCustomizeTabs; and use CanCustomizeTabs;. New protected function getDefaultTabs(): array; form now uses getTabs() instead of inline Tabs(...). Docblock simplified.
Eggs resource pages
app/Filament/Admin/Resources/Eggs/Pages/CreateEgg.php, app/Filament/Admin/Resources/Eggs/Pages/EditEgg.php
Added CanCustomizeTabs trait and protected function getDefaultTabs(): array in each. Replaced large inline tab schemas with getTabs() provider; reorganized tab schemas into modular tabs (configuration, process_management, egg_variables, install_script).
Node edit page
app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
Added CanCustomizeTabs trait and protected function getDefaultTabs(): array. Replaced inline tab definitions with getTabs() and restructured tabs (overview, basic_settings, advanced_settings, config_file, diagnostics). Removed @throws Throwable docblock.
User resource (static tabs)
app/Filament/Admin/Resources/Users/UserResource.php
Added CanCustomizeStaticTabs trait and protected static function getDefaultTabs(): array. Form now uses static::getTabs() instead of inline tab definitions.
Auth / EditProfile page
app/Filament/Pages/Auth/EditProfile.php
Added CanCustomizeTabs trait and protected function getDefaultTabs(): array. Form now sources tabs from getTabs(); moved inline schemas into the tab provider.
Server create page (minor)
app/Filament/Admin/Resources/Servers/Pages/CreateServer.php
Removed unused Random\RandomException import and a related @throws docblock; no functional changes to form behavior.

Sequence Diagram(s)

(omitted)

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, making it impossible to evaluate relevance or quality. Add a meaningful description explaining the purpose of these traits, what problems they solve, and how they're used across the affected files.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: introducing new traits to enable tab customization across multiple Filament pages and resources.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In @app/Filament/Admin/Resources/Eggs/Pages/CreateEgg.php:
- Around line 206-209: The unique validation for nested variables fails because
$get('../../id') is null during form validation; implement Filament's pattern by
overriding handleRecordCreation to first create the Egg record and then persist
relationship data via $this->form->model($egg)->saveRelationships(); in
handleRecordCreation ensure uuid and config_startup/config_logs are normalized
(json-encoded if arrays), call Egg::create($data) to create $egg, then call
$this->form->model($egg)->saveRelationships() and return $egg so the unique rule
with where('egg_id', $get('../../id')) can resolve the egg id.

In @app/Filament/Admin/Resources/Nodes/Pages/EditNode.php:
- Around line 461-476: The ToggleButtons field's two afterStateUpdated callbacks
only allow the last one to run, so combine them into a single afterStateUpdated
callback on the ToggleButtons instance that accepts a Set parameter and calls
$set('disk', 0) and $set('disk_overallocate', 0) within that one callback
(preserving the existing state handling such as formatStateUsing and stateCast).
- Around line 619-634: The success notification is sent regardless of errors
because it lives outside the try-catch; move the
Notification::make()->success()->title(trans('admin/node.token_reset'))->send()
(and the subsequent $this->fillForm() if you only want to refresh on success)
into the try block immediately after $this->nodeUpdateService->handle($node, [],
true) so that it runs only when handle() succeeds; keep the catch block as-is to
send the warning notification when an Exception is thrown.
- Around line 517-533: The ToggleButtons::make('unlimited_cpu') currently has
two afterStateUpdated handlers but only the last one runs; replace them with a
single afterStateUpdated callback that accepts Set $set and sets both 'cpu' and
'cpu_overallocate' to 0 (e.g., ->afterStateUpdated(fn (Set $set) => $set('cpu',
0)->set('cpu_overallocate', 0))). Keep the other chain methods
(formatStateUsing, stateCast, options, colors, columnSpan) unchanged.
- Around line 400-421: The ToggleButtons::make('unlimited_mem') component
currently has two afterStateUpdated(...) calls but only the last one runs;
combine them into a single afterStateUpdated callback on the ToggleButtons
component that calls $set('memory', 0) and $set('memory_overallocate', 0) (e.g.,
->afterStateUpdated(fn (Set $set) => [$set('memory', 0),
$set('memory_overallocate', 0)]) or a single closure that invokes both $set
calls) so both fields are cleared when unlimited_mem is toggled.
- Around line 143-153: The helperText callback on the domain field currently
returns trans('admin/node.error') for valid FQDNs which is a misleading key
name; update the key to a clearer name (e.g. trans('admin/node.domain_help') or
trans('admin/node.fqdn_explanation')) in the ->helperText(function ($state) {
... }) block and add/rename the corresponding entry in your translation files so
the message text remains the same but the key reflects guidance rather than an
error.
🧹 Nitpick comments (3)
app/Traits/Filament/CanCustomizeStaticTabs.php (1)

8-32: Consider consolidating shared logic between the two tab traits.

This trait is nearly identical to CanCustomizeTabs, differing only in using static methods for getDefaultTabs() and getTabs(). While this duplication is acceptable given Filament's distinct patterns for Resources (static) vs Pages (instance), you might consider extracting the shared registerCustomTabs logic or documenting when to use each trait.

app/Filament/Admin/Resources/Users/UserResource.php (1)

304-304: Consider using array_keys() to avoid the unused variable warning.

The $_ variable is flagged by static analysis as unused. Using array_keys() is more explicit.

Suggested fix
-                            foreach ($user->oauth ?? [] as $schema => $_) {
+                            foreach (array_keys($user->oauth ?? []) as $schema) {
app/Filament/Admin/Resources/Eggs/Pages/CreateEgg.php (1)

180-197: Setting checkbox fields to empty string may cause type issues.

Lines 184-185 and 193-194 set user_viewable and user_editable to empty strings when null. These fields back Checkbox components (lines 229-230), which typically expect boolean values. Consider using false instead of '' for consistency with checkbox semantics.

Suggested fix
 ->mutateRelationshipDataBeforeCreateUsing(function (array $data): array {
     $data['default_value'] ??= '';
     $data['description'] ??= '';
     $data['rules'] ??= [];
-    $data['user_viewable'] ??= '';
-    $data['user_editable'] ??= '';
+    $data['user_viewable'] ??= false;
+    $data['user_editable'] ??= false;

     return $data;
 })
 ->mutateRelationshipDataBeforeSaveUsing(function (array $data): array {
     $data['default_value'] ??= '';
     $data['description'] ??= '';
     $data['rules'] ??= [];
-    $data['user_viewable'] ??= '';
-    $data['user_editable'] ??= '';
+    $data['user_viewable'] ??= false;
+    $data['user_editable'] ??= false;

     return $data;
 })
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b9d683 and 7c31ec1.

📒 Files selected for processing (11)
  • app/Enums/TabPosition.php
  • app/Filament/Admin/Pages/Settings.php
  • app/Filament/Admin/Resources/Eggs/Pages/CreateEgg.php
  • app/Filament/Admin/Resources/Eggs/Pages/EditEgg.php
  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
  • app/Filament/Admin/Resources/Servers/Pages/CreateServer.php
  • app/Filament/Admin/Resources/Servers/Pages/EditServer.php
  • app/Filament/Admin/Resources/Users/UserResource.php
  • app/Filament/Pages/Auth/EditProfile.php
  • app/Traits/Filament/CanCustomizeStaticTabs.php
  • app/Traits/Filament/CanCustomizeTabs.php
💤 Files with no reviewable changes (1)
  • app/Filament/Admin/Resources/Servers/Pages/CreateServer.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-05T22:21:31.863Z
Learnt from: notAreYouScared
Repo: pelican-dev/panel PR: 1865
File: app/Filament/Admin/Resources/Nodes/Pages/EditNode.php:682-682
Timestamp: 2025-11-05T22:21:31.863Z
Learning: In app/Filament/Admin/Resources/Nodes/Pages/EditNode.php, the diagnostics tab's upload action intentionally does not use the iconButton() modifier, while the pull action does. This UI difference is intentional.

Applied to files:

  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
🧬 Code graph analysis (5)
app/Traits/Filament/CanCustomizeStaticTabs.php (4)
app/Traits/Filament/CanCustomizeTabs.php (3)
  • registerCustomTabs (13-16)
  • getDefaultTabs (19-22)
  • getTabs (25-32)
app/Filament/Admin/Pages/Settings.php (1)
  • getDefaultTabs (118-148)
app/Filament/Admin/Resources/Eggs/Pages/CreateEgg.php (1)
  • getDefaultTabs (73-286)
app/Filament/Admin/Resources/Eggs/Pages/EditEgg.php (1)
  • getDefaultTabs (67-443)
app/Traits/Filament/CanCustomizeTabs.php (2)
app/Traits/Filament/CanCustomizeStaticTabs.php (3)
  • registerCustomTabs (13-16)
  • getDefaultTabs (19-22)
  • getTabs (25-32)
app/Filament/Admin/Resources/Users/UserResource.php (1)
  • getDefaultTabs (157-484)
app/Filament/Admin/Resources/Users/UserResource.php (2)
app/Traits/Filament/CanCustomizeStaticTabs.php (2)
  • getTabs (25-32)
  • getDefaultTabs (19-22)
app/Traits/Filament/CanCustomizeTabs.php (2)
  • getTabs (25-32)
  • getDefaultTabs (19-22)
app/Filament/Admin/Resources/Eggs/Pages/EditEgg.php (2)
app/Traits/Filament/CanCustomizeStaticTabs.php (2)
  • getTabs (25-32)
  • getDefaultTabs (19-22)
app/Traits/Filament/CanCustomizeTabs.php (2)
  • getTabs (25-32)
  • getDefaultTabs (19-22)
app/Filament/Admin/Resources/Nodes/Pages/EditNode.php (2)
app/Traits/Filament/CanCustomizeStaticTabs.php (2)
  • getTabs (25-32)
  • getDefaultTabs (19-22)
app/Traits/Filament/CanCustomizeTabs.php (2)
  • getTabs (25-32)
  • getDefaultTabs (19-22)
🪛 PHPMD (2.15.0)
app/Filament/Admin/Resources/Users/UserResource.php

304-304: Avoid unused local variables such as '$_'. (undefined)

(UnusedLocalVariable)

🔇 Additional comments (18)
app/Enums/TabPosition.php (1)

5-9: LGTM!

Clean and minimal enum definition. The string-backed enum is appropriate for use as array keys in the tab customization system.

app/Traits/Filament/CanCustomizeTabs.php (1)

8-32: LGTM!

The trait design correctly uses late static binding (static::) for the $customTabs property, ensuring each class using the trait maintains its own custom tabs registry. The mix of static registration (allowing customization before instantiation) and instance retrieval methods is a clean API design.

app/Filament/Admin/Resources/Users/UserResource.php (3)

21-21: LGTM!

Correct import and usage of CanCustomizeStaticTabs trait for the Resource class, which uses static method patterns.

Also applies to: 63-63


150-154: LGTM!

The form schema correctly delegates tab construction to static::getTabs(), enabling the tab customization system.


156-483: LGTM!

Comprehensive default tabs implementation covering account, roles, keys, and activity tabs. The structure aligns well with the new tab customization pattern.

app/Filament/Admin/Resources/Eggs/Pages/EditEgg.php (3)

15-15: LGTM!

Correct import and usage of CanCustomizeTabs trait for the EditRecord page class.

Also applies to: 51-51


55-64: LGTM!

The form method correctly uses the instance method $this->getTabs() for tab assembly, enabling the tab customization system.


66-442: LGTM!

Comprehensive default tabs implementation with well-structured configuration, process management, egg variables, and install script tabs.

app/Filament/Admin/Pages/Settings.php (3)

13-13: LGTM!

Correct import and usage of CanCustomizeTabs trait for the Settings page.

Also applies to: 57-57


101-111: LGTM!

Clean delegation to $this->getTabs() within the form schema.


113-148: LGTM!

Well-organized default tabs definition delegating to focused helper methods for each settings section.

app/Filament/Pages/Auth/EditProfile.php (3)

17-17: LGTM!

Correct import and usage of CanCustomizeTabs trait for the EditProfile page.

Also applies to: 60-60


85-97: LGTM!

The form method correctly uses $this->getTabs() and properly chains the additional schema configuration.


99-557: LGTM!

Comprehensive default tabs implementation covering all profile-related functionality including account settings, OAuth, 2FA, API keys, SSH keys, activity, and customization options.

app/Filament/Admin/Resources/Eggs/Pages/CreateEgg.php (2)

61-70: LGTM on the tab customization integration.

The form correctly delegates to getTabs() from the CanCustomizeTabs trait, enabling the tab customization framework. The persistTabInQueryString() and columnSpanFull() configurations are appropriately preserved.


72-286: Well-structured tab organization.

The getDefaultTabs() method is cleanly organized with logical groupings: configuration, process management, variables, and install script. Translation keys are consistently used for labels, and responsive column spans are properly configured.

app/Filament/Admin/Resources/Nodes/Pages/EditNode.php (2)

65-79: LGTM on the tab customization integration.

The form correctly integrates with the CanCustomizeTabs trait via getTabs(), maintaining the existing column configuration and tab persistence behavior.


81-780: Comprehensive tab organization with clear separation of concerns.

The getDefaultTabs() method provides a well-structured organization of node management features across overview, settings, configuration, and diagnostics tabs. The trait integration enables future extensibility for custom tab additions. Based on learnings, the intentional UI difference between the diagnostics upload action (without iconButton()) and pull action (with iconButton()) is preserved.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @app/Filament/Admin/Resources/Nodes/Pages/EditNode.php:
- Around line 707-708: Add a defensive check after calling $response->json() to
ensure the 'url' key exists before accessing $data['url']; in the EditNode page
(EditNode class / the method containing the $response->json() call) validate
with isset($data['url']) or array_key_exists('url', $data), and if missing
handle it gracefully (log the unexpected response, set a safe default or
return/throw a descriptive exception and avoid using a null/undefined value) so
the code doesn't trigger undefined index warnings or propagate invalid data.
🧹 Nitpick comments (1)
app/Filament/Admin/Resources/Nodes/Pages/EditNode.php (1)

143-153: The translation key admin/node.error is misleadingly named but contains helpful text.

The helper text returned when a domain (non-IP) is entered uses the translation key admin/node.error, which actually contains: "This is the domain name that points to your node's IP Address. If you've already set up this, you can verify it by checking the next field!" This is instructional text, not an error message.

Consider renaming the translation key to something more descriptive like fqdn_note or domain_help to better reflect its purpose and avoid confusing developers about what this field expects.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c31ec1 and fd879af.

📒 Files selected for processing (1)
  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-05T22:21:31.863Z
Learnt from: notAreYouScared
Repo: pelican-dev/panel PR: 1865
File: app/Filament/Admin/Resources/Nodes/Pages/EditNode.php:682-682
Timestamp: 2025-11-05T22:21:31.863Z
Learning: In app/Filament/Admin/Resources/Nodes/Pages/EditNode.php, the diagnostics tab's upload action intentionally does not use the iconButton() modifier, while the pull action does. This UI difference is intentional.

Applied to files:

  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
🧬 Code graph analysis (1)
app/Filament/Admin/Resources/Nodes/Pages/EditNode.php (1)
app/helpers.php (2)
  • is_ip (15-18)
  • get_ip_from_hostname (98-111)
🔇 Additional comments (2)
app/Filament/Admin/Resources/Nodes/Pages/EditNode.php (2)

65-83: LGTM! Trait integration is correct.

The refactoring properly:

  • Uses the CanCustomizeTabs trait to enable tab customization
  • Delegates tab assembly to $this->getTabs() which merges custom tabs with defaults
  • Implements getDefaultTabs() with the correct visibility (protected) and return type

686-689: Verify intentional UI change: iconButton() now added to upload action.

Based on learnings from PR #1865, the diagnostics tab's upload action intentionally did not use the iconButton() modifier (while the pull action did). This code now adds iconButton() to the upload action at line 689.

Please confirm this is an intentional UI change, or if the previous distinction should be preserved.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@app/Filament/Admin/Resources/Eggs/Pages/EditEgg.php`:
- Around line 126-133: The hostname is validated via parse_url/gethostbyname
($host/$ip) but the actual fetch still calls file_get_contents($imageUrl),
enabling DNS rebinding; update the download logic (where file_get_contents is
used) to use the already-resolved $ip: perform the HTTP request to
http://$ip/... while setting the original Host header to $host and disable
redirects, or replace file_get_contents with a cURL implementation using
CURLOPT_RESOLVE (map $host to $ip), CURLOPT_FOLLOWLOCATION = 0, and explicit
Host header handling; ensure you reuse the validated $ip/$host values from the
earlier parse_url/gethostbyname checks and block redirects to prevent secondary
rebinding.

# Conflicts:
#	app/Filament/Admin/Resources/Servers/Pages/EditServer.php
@Boy132 Boy132 merged commit 9f744d3 into main Jan 18, 2026
32 checks passed
@Boy132 Boy132 deleted the boy132/customize-tabs branch January 18, 2026 21:32
@github-actions github-actions bot locked and limited conversation to collaborators Jan 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants