-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
feat: developer view for shared environment variables #7091
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Conversation
|
@CodeRabbit review? |
|
@ShadowArcanist: I'll review the changes in this PR right away! ✅ Actions performedReview triggered.
|
WalkthroughAdded developer mode UI for bulk environment variable editing across three Livewire shared variable components (Environment, Project, Team). Each component now supports toggling between normal list view and developer view, with bulk submission workflow for creating, updating, and deleting variables. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Livewire
participant Backend
participant View
User->>Livewire: Click "switch()" button
Livewire->>Livewire: Toggle $view between 'normal' and 'dev'
Livewire->>Livewire: Call getDevView()
Livewire->>Livewire: formatEnvironmentVariables($variables)
Livewire->>Livewire: Populate $variables string
Livewire->>View: Re-render with new $view state
View->>User: Display Normal/Dev view UI
rect rgba(100, 150, 200, 0.3)
Note over User,View: Developer View Submission
User->>Livewire: submit() with textarea content
Livewire->>Livewire: Validate & parse variables
Livewire->>Livewire: handleBulkSubmit()
Livewire->>Livewire: deleteRemovedVariables()
Livewire->>Backend: Delete unused keys
Livewire->>Livewire: updateOrCreateVariables()
Livewire->>Backend: Update/create remaining vars
Backend->>Livewire: Persist changes
Livewire->>Livewire: refreshEnvs()
Livewire->>Livewire: getDevView() refresh
Livewire->>View: Dispatch success, re-render
View->>User: Show updated state
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (7)
app/Livewire/SharedVariables/Team/Index.php (3)
62-74: Add return type hint for consistency.Per coding guidelines, always declare explicit return types for functions and methods.
Apply this diff:
- private function formatEnvironmentVariables($variables) + private function formatEnvironmentVariables($variables): stringAs per coding guidelines
76-87: Add validation rules for bulk submission.The
submit()method processes user input from the$variablestextarea but does not define or invoke validation rules. Per coding guidelines, Livewire components should declareprotected $rulesand call$this->validate()before processing form data.Consider adding validation:
protected $rules = [ 'variables' => 'required|string', ]; public function submit() { try { $this->authorize('update', $this->team); $this->validate(); $this->handleBulkSubmit(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } }As per coding guidelines
15-158: Significant code duplication across Team, Project, and Environment components.The bulk editing workflow (properties, methods, logic) in this file is nearly identical to
app/Livewire/SharedVariables/Project/Show.phpandapp/Livewire/SharedVariables/Environment/Show.php. This violates DRY principles and makes maintenance harder.Consider extracting the shared logic into a trait or abstract base class:
// app/Livewire/SharedVariables/Concerns/ManagesBulkVariables.php trait ManagesBulkVariables { public string $view = 'normal'; public ?string $variables = null; public function switch() { $this->view = $this->view === 'normal' ? 'dev' : 'normal'; $this->getDevView(); } abstract protected function getEnvironmentVariables(); public function getDevView() { $this->variables = $this->formatEnvironmentVariables( $this->getEnvironmentVariables()->sortBy('key') ); } private function formatEnvironmentVariables($variables): string { // ... shared formatting logic } // ... other shared methods }Then use the trait in all three components:
class Index extends Component { use AuthorizesRequests, ManagesBulkVariables; protected function getEnvironmentVariables() { return $this->team->environment_variables; } }As per coding guidelines
app/Livewire/SharedVariables/Project/Show.php (2)
68-80: Add return type hint for consistency.Per coding guidelines, always declare explicit return types for functions and methods.
Apply this diff:
- private function formatEnvironmentVariables($variables) + private function formatEnvironmentVariables($variables): stringAs per coding guidelines
82-93: Add validation rules for bulk submission.The
submit()method processes user input from the$variablestextarea but does not define or invoke validation rules. Per coding guidelines, Livewire components should declareprotected $rulesand call$this->validate()before processing form data.Consider adding validation:
protected $rules = [ 'variables' => 'required|string', ]; public function submit() { try { $this->authorize('update', $this->project); $this->validate(); $this->handleBulkSubmit(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } }As per coding guidelines
app/Livewire/SharedVariables/Environment/Show.php (2)
71-83: Add return type hint for consistency.Per coding guidelines, always declare explicit return types for functions and methods.
Apply this diff:
- private function formatEnvironmentVariables($variables) + private function formatEnvironmentVariables($variables): stringAs per coding guidelines
85-96: Add validation rules for bulk submission.The
submit()method processes user input from the$variablestextarea but does not define or invoke validation rules. Per coding guidelines, Livewire components should declareprotected $rulesand call$this->validate()before processing form data.Consider adding validation:
protected $rules = [ 'variables' => 'required|string', ]; public function submit() { try { $this->authorize('update', $this->environment); $this->validate(); $this->handleBulkSubmit(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } }As per coding guidelines
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/Livewire/SharedVariables/Environment/Show.php(3 hunks)app/Livewire/SharedVariables/Project/Show.php(3 hunks)app/Livewire/SharedVariables/Team/Index.php(3 hunks)resources/views/livewire/shared-variables/environment/show.blade.php(1 hunks)resources/views/livewire/shared-variables/project/show.blade.php(1 hunks)resources/views/livewire/shared-variables/team/index.blade.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
**/*.php: Follow PSR-12 coding standards for all PHP code
Format PHP code with Laravel Pint configuration
Run static analysis with PHPStan to ensure type safety in PHP code
Document complex methods with PHPDoc blocks including parameters, return types, and thrown exceptions
**/*.php: Follow PSR-12 PHP coding standards across the codebase
Prefer eager loading and query optimization to prevent N+1 issues in database interactions
Use Laravel best practices for structure, services, and policies
**/*.php: Always use curly braces for control structures in PHP, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors
Always declare explicit return types for functions and methods; add appropriate parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline code comments for very complex logic
When documenting arrays, add useful array shape types in PHPDoc where appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)
Files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpapp/Livewire/SharedVariables/Team/Index.phpapp/Livewire/SharedVariables/Environment/Show.phpresources/views/livewire/shared-variables/project/show.blade.phpapp/Livewire/SharedVariables/Project/Show.php
resources/views/**/*.blade.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
Use semantic Tailwind CSS classes and consistent spacing in Blade templates
resources/views/**/*.blade.php: In Blade views, prefer using x-forms components with canGate and :canResource instead of wrapping elements in @can/@else blocks
Remove legacy @can/@else blocks around individual form inputs/buttons and migrate to the single-line component pattern
Choose gates consistently in views: use update for configuration changes, deploy for operational actions, view for read-only access, and delete for destructive actions
Always pass the specific resource to :canResource (e.g., :canResource="$application", "$service", "$server"), and use team context for creation permissions (e.g., :canResource="auth()->user()->currentTeam" with canGate="createAnyResource")
Only set autoDisable="false" when also providing explicit :disabled logic on the component
Use single-line authorized components for forms (inputs, selects, checkboxes, buttons) to reduce duplication (e.g., <x-forms.input canGate="update" :canResource="$resource" ... />)
resources/views/**/*.blade.php: Prefer Alpine.js directives (x-data, x-on, x-show, x-model, x-init) for lightweight interactivity in Blade views
Use enhanced <x-forms.*> components with canGate and canResource for authorization instead of @can/@else blocks
When protecting forms, pass canGate and :canResource to all x-forms components; rely on autoDisable=true for unauthorized users
Apply Tailwind responsive utilities (e.g., grid breakpoints) for mobile-first layouts
Support dark mode using Tailwind dark: variants on relevant elements
Ensure interactive controls include appropriate ARIA attributes (e.g., aria-label, aria-describedby) for accessibility
resources/views/**/*.blade.php: In Blade views, prefer x-forms.* components with canGate and :canResource for authorization (autoDisable defaults to true) instead of manual permission blocks.
Do not wrap x-forms.* components in @can/@else to toggle disabled state; use component-level canGate/:can...
Files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
resources/views/{layouts,components,livewire,server,auth,emails,errors}/**/*.blade.php
📄 CodeRabbit inference engine (.cursor/rules/frontend-patterns.mdc)
Organize Blade templates into the specified folders: layouts/, components/, livewire/, and feature-specific directories server/, auth/, emails/, errors/
Files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
resources/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Store frontend assets and views under resources
Files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
resources/views/livewire/**/*.blade.php
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
Livewire components must have a single root element; use wire:key in loops and wire:loading/wire:dirty for UX
Files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
resources/**/*.{blade.php,vue}
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
Use Tailwind gap utilities for spacing lists instead of margins when listing items
Files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
app/Livewire/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Define Livewire components in app/Livewire and keep HTTP/UI concerns there
app/Livewire/**/*.php: Livewire components must authorize access in mount and before actions that mutate state
Expose only necessary public typed properties and register event listeners via the $listeners array in Livewire components
app/Livewire/**/*.php: Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Declare protected $rules and validate with $this->validate() in Livewire form actions
For real-time updates, define getListeners() in Livewire components to register broadcast/event listeners
Use Livewire placeholder() to lazy-load heavy components or sections for performancePlace Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)
Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()
Files:
app/Livewire/SharedVariables/Team/Index.phpapp/Livewire/SharedVariables/Environment/Show.phpapp/Livewire/SharedVariables/Project/Show.php
app/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
Use database transactions to group related write operations for consistency in services/controllers/jobs
Files:
app/Livewire/SharedVariables/Team/Index.phpapp/Livewire/SharedVariables/Environment/Show.phpapp/Livewire/SharedVariables/Project/Show.php
app/Livewire/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Implement frontend components as Livewire classes under app/Livewire
Files:
app/Livewire/SharedVariables/Team/Index.phpapp/Livewire/SharedVariables/Environment/Show.phpapp/Livewire/SharedVariables/Project/Show.php
{app/Http/Controllers/**/*.php,app/Livewire/**/*.php}
📄 CodeRabbit inference engine (.cursor/rules/README.mdc)
Authorize sensitive actions with policies (e.g., $this->authorize('deploy', $model)) before invoking services
Files:
app/Livewire/SharedVariables/Team/Index.phpapp/Livewire/SharedVariables/Environment/Show.phpapp/Livewire/SharedVariables/Project/Show.php
🧠 Learnings (4)
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to resources/views/**/*.blade.php : Choose gates consistently in views: use update for configuration changes, deploy for operational actions, view for read-only access, and delete for destructive actions
Applied to files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to resources/views/**/*.blade.php : Remove legacy can/else blocks around individual form inputs/buttons and migrate to the single-line component pattern
Applied to files:
resources/views/livewire/shared-variables/team/index.blade.phpresources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to resources/views/**/*.blade.php : For custom interactive components not using x-forms.* (e.g., Alpine.js widgets), wrap with can('gate', $resource) and provide a disabled/readonly fallback in else with opacity-50 and cursor-not-allowed styling.
Applied to files:
resources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to resources/views/**/*.blade.php : Do not wrap x-forms.* components in can/else to toggle disabled state; use component-level canGate/:canResource instead.
Applied to files:
resources/views/livewire/shared-variables/environment/show.blade.phpresources/views/livewire/shared-variables/project/show.blade.php
| private function handleBulkSubmit() | ||
| { | ||
| $variables = parseEnvFormatToArray($this->variables); | ||
| $changesMade = false; | ||
|
|
||
| // Delete removed variables | ||
| $deletedCount = $this->deleteRemovedVariables($variables); | ||
| if ($deletedCount > 0) { | ||
| $changesMade = true; | ||
| } | ||
|
|
||
| // Update or create variables | ||
| $updatedCount = $this->updateOrCreateVariables($variables); | ||
| if ($updatedCount > 0) { | ||
| $changesMade = true; | ||
| } | ||
|
|
||
| if ($changesMade) { | ||
| $this->dispatch('success', 'Environment variables updated.'); | ||
| } | ||
| } | ||
|
|
||
| private function deleteRemovedVariables($variables) | ||
| { | ||
| $variablesToDelete = $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | ||
|
|
||
| if ($variablesToDelete->isEmpty()) { | ||
| return 0; | ||
| } | ||
|
|
||
| $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | ||
|
|
||
| return $variablesToDelete->count(); | ||
| } | ||
|
|
||
| private function updateOrCreateVariables($variables) | ||
| { | ||
| $count = 0; | ||
| foreach ($variables as $key => $value) { | ||
| $found = $this->environment->environment_variables()->where('key', $key)->first(); | ||
|
|
||
| if ($found) { | ||
| if (! $found->is_shown_once && ! $found->is_multiline) { | ||
| if ($found->value !== $value) { | ||
| $found->value = $value; | ||
| $found->save(); | ||
| $count++; | ||
| } | ||
| } | ||
| } else { | ||
| $this->environment->environment_variables()->create([ | ||
| 'key' => $key, | ||
| 'value' => $value, | ||
| 'is_multiline' => false, | ||
| 'is_literal' => false, | ||
| 'type' => 'environment', | ||
| 'team_id' => currentTeam()->id, | ||
| ]); | ||
| $count++; | ||
| } | ||
| } | ||
|
|
||
| return $count; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Wrap bulk operations in a database transaction.
The bulk submission process involves multiple database writes (deletions, updates, creations) that should be atomic. Per coding guidelines, use database transactions to group related write operations for consistency.
Apply this diff:
private function handleBulkSubmit()
{
- $variables = parseEnvFormatToArray($this->variables);
- $changesMade = false;
-
- // Delete removed variables
- $deletedCount = $this->deleteRemovedVariables($variables);
- if ($deletedCount > 0) {
- $changesMade = true;
- }
-
- // Update or create variables
- $updatedCount = $this->updateOrCreateVariables($variables);
- if ($updatedCount > 0) {
- $changesMade = true;
- }
-
- if ($changesMade) {
- $this->dispatch('success', 'Environment variables updated.');
- }
+ $variables = parseEnvFormatToArray($this->variables);
+ $changesMade = false;
+
+ \DB::transaction(function () use ($variables, &$changesMade) {
+ // Delete removed variables
+ $deletedCount = $this->deleteRemovedVariables($variables);
+ if ($deletedCount > 0) {
+ $changesMade = true;
+ }
+
+ // Update or create variables
+ $updatedCount = $this->updateOrCreateVariables($variables);
+ if ($updatedCount > 0) {
+ $changesMade = true;
+ }
+ });
+
+ if ($changesMade) {
+ $this->dispatch('success', 'Environment variables updated.');
+ }
}As per coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleBulkSubmit() | |
| { | |
| $variables = parseEnvFormatToArray($this->variables); | |
| $changesMade = false; | |
| // Delete removed variables | |
| $deletedCount = $this->deleteRemovedVariables($variables); | |
| if ($deletedCount > 0) { | |
| $changesMade = true; | |
| } | |
| // Update or create variables | |
| $updatedCount = $this->updateOrCreateVariables($variables); | |
| if ($updatedCount > 0) { | |
| $changesMade = true; | |
| } | |
| if ($changesMade) { | |
| $this->dispatch('success', 'Environment variables updated.'); | |
| } | |
| } | |
| private function deleteRemovedVariables($variables) | |
| { | |
| $variablesToDelete = $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | |
| if ($variablesToDelete->isEmpty()) { | |
| return 0; | |
| } | |
| $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | |
| return $variablesToDelete->count(); | |
| } | |
| private function updateOrCreateVariables($variables) | |
| { | |
| $count = 0; | |
| foreach ($variables as $key => $value) { | |
| $found = $this->environment->environment_variables()->where('key', $key)->first(); | |
| if ($found) { | |
| if (! $found->is_shown_once && ! $found->is_multiline) { | |
| if ($found->value !== $value) { | |
| $found->value = $value; | |
| $found->save(); | |
| $count++; | |
| } | |
| } | |
| } else { | |
| $this->environment->environment_variables()->create([ | |
| 'key' => $key, | |
| 'value' => $value, | |
| 'is_multiline' => false, | |
| 'is_literal' => false, | |
| 'type' => 'environment', | |
| 'team_id' => currentTeam()->id, | |
| ]); | |
| $count++; | |
| } | |
| } | |
| return $count; | |
| } | |
| private function handleBulkSubmit() | |
| { | |
| $variables = parseEnvFormatToArray($this->variables); | |
| $changesMade = false; | |
| \DB::transaction(function () use ($variables, &$changesMade) { | |
| // Delete removed variables | |
| $deletedCount = $this->deleteRemovedVariables($variables); | |
| if ($deletedCount > 0) { | |
| $changesMade = true; | |
| } | |
| // Update or create variables | |
| $updatedCount = $this->updateOrCreateVariables($variables); | |
| if ($updatedCount > 0) { | |
| $changesMade = true; | |
| } | |
| }); | |
| if ($changesMade) { | |
| $this->dispatch('success', 'Environment variables updated.'); | |
| } | |
| } | |
| private function deleteRemovedVariables($variables) | |
| { | |
| $variablesToDelete = $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | |
| if ($variablesToDelete->isEmpty()) { | |
| return 0; | |
| } | |
| $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | |
| return $variablesToDelete->count(); | |
| } | |
| private function updateOrCreateVariables($variables) | |
| { | |
| $count = 0; | |
| foreach ($variables as $key => $value) { | |
| $found = $this->environment->environment_variables()->where('key', $key)->first(); | |
| if ($found) { | |
| if (! $found->is_shown_once && ! $found->is_multiline) { | |
| if ($found->value !== $value) { | |
| $found->value = $value; | |
| $found->save(); | |
| $count++; | |
| } | |
| } | |
| } else { | |
| $this->environment->environment_variables()->create([ | |
| 'key' => $key, | |
| 'value' => $value, | |
| 'is_multiline' => false, | |
| 'is_literal' => false, | |
| 'type' => 'environment', | |
| 'team_id' => currentTeam()->id, | |
| ]); | |
| $count++; | |
| } | |
| } | |
| return $count; | |
| } |
🤖 Prompt for AI Agents
In app/Livewire/SharedVariables/Environment/Show.php around lines 98 to 161,
wrap the whole bulk submit workflow (deletion + update/create) in a single
database transaction so all writes are atomic: start a DB transaction before
calling deleteRemovedVariables and updateOrCreateVariables, run both operations
inside the transaction, commit if no exception and rollback on error; ensure the
success dispatch only fires after the transaction commits and propagate or
handle exceptions so partial changes cannot persist.
| private function handleBulkSubmit() | ||
| { | ||
| $variables = parseEnvFormatToArray($this->variables); | ||
| $changesMade = false; | ||
|
|
||
| // Delete removed variables | ||
| $deletedCount = $this->deleteRemovedVariables($variables); | ||
| if ($deletedCount > 0) { | ||
| $changesMade = true; | ||
| } | ||
|
|
||
| // Update or create variables | ||
| $updatedCount = $this->updateOrCreateVariables($variables); | ||
| if ($updatedCount > 0) { | ||
| $changesMade = true; | ||
| } | ||
|
|
||
| if ($changesMade) { | ||
| $this->dispatch('success', 'Environment variables updated.'); | ||
| } | ||
| } | ||
|
|
||
| private function deleteRemovedVariables($variables) | ||
| { | ||
| $variablesToDelete = $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | ||
|
|
||
| if ($variablesToDelete->isEmpty()) { | ||
| return 0; | ||
| } | ||
|
|
||
| $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | ||
|
|
||
| return $variablesToDelete->count(); | ||
| } | ||
|
|
||
| private function updateOrCreateVariables($variables) | ||
| { | ||
| $count = 0; | ||
| foreach ($variables as $key => $value) { | ||
| $found = $this->project->environment_variables()->where('key', $key)->first(); | ||
|
|
||
| if ($found) { | ||
| if (! $found->is_shown_once && ! $found->is_multiline) { | ||
| if ($found->value !== $value) { | ||
| $found->value = $value; | ||
| $found->save(); | ||
| $count++; | ||
| } | ||
| } | ||
| } else { | ||
| $this->project->environment_variables()->create([ | ||
| 'key' => $key, | ||
| 'value' => $value, | ||
| 'is_multiline' => false, | ||
| 'is_literal' => false, | ||
| 'type' => 'project', | ||
| 'team_id' => currentTeam()->id, | ||
| ]); | ||
| $count++; | ||
| } | ||
| } | ||
|
|
||
| return $count; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Wrap bulk operations in a database transaction.
The bulk submission process involves multiple database writes (deletions, updates, creations) that should be atomic. Per coding guidelines, use database transactions to group related write operations for consistency.
Apply this diff:
private function handleBulkSubmit()
{
- $variables = parseEnvFormatToArray($this->variables);
- $changesMade = false;
-
- // Delete removed variables
- $deletedCount = $this->deleteRemovedVariables($variables);
- if ($deletedCount > 0) {
- $changesMade = true;
- }
-
- // Update or create variables
- $updatedCount = $this->updateOrCreateVariables($variables);
- if ($updatedCount > 0) {
- $changesMade = true;
- }
-
- if ($changesMade) {
- $this->dispatch('success', 'Environment variables updated.');
- }
+ $variables = parseEnvFormatToArray($this->variables);
+ $changesMade = false;
+
+ \DB::transaction(function () use ($variables, &$changesMade) {
+ // Delete removed variables
+ $deletedCount = $this->deleteRemovedVariables($variables);
+ if ($deletedCount > 0) {
+ $changesMade = true;
+ }
+
+ // Update or create variables
+ $updatedCount = $this->updateOrCreateVariables($variables);
+ if ($updatedCount > 0) {
+ $changesMade = true;
+ }
+ });
+
+ if ($changesMade) {
+ $this->dispatch('success', 'Environment variables updated.');
+ }
}As per coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleBulkSubmit() | |
| { | |
| $variables = parseEnvFormatToArray($this->variables); | |
| $changesMade = false; | |
| // Delete removed variables | |
| $deletedCount = $this->deleteRemovedVariables($variables); | |
| if ($deletedCount > 0) { | |
| $changesMade = true; | |
| } | |
| // Update or create variables | |
| $updatedCount = $this->updateOrCreateVariables($variables); | |
| if ($updatedCount > 0) { | |
| $changesMade = true; | |
| } | |
| if ($changesMade) { | |
| $this->dispatch('success', 'Environment variables updated.'); | |
| } | |
| } | |
| private function deleteRemovedVariables($variables) | |
| { | |
| $variablesToDelete = $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | |
| if ($variablesToDelete->isEmpty()) { | |
| return 0; | |
| } | |
| $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | |
| return $variablesToDelete->count(); | |
| } | |
| private function updateOrCreateVariables($variables) | |
| { | |
| $count = 0; | |
| foreach ($variables as $key => $value) { | |
| $found = $this->project->environment_variables()->where('key', $key)->first(); | |
| if ($found) { | |
| if (! $found->is_shown_once && ! $found->is_multiline) { | |
| if ($found->value !== $value) { | |
| $found->value = $value; | |
| $found->save(); | |
| $count++; | |
| } | |
| } | |
| } else { | |
| $this->project->environment_variables()->create([ | |
| 'key' => $key, | |
| 'value' => $value, | |
| 'is_multiline' => false, | |
| 'is_literal' => false, | |
| 'type' => 'project', | |
| 'team_id' => currentTeam()->id, | |
| ]); | |
| $count++; | |
| } | |
| } | |
| return $count; | |
| } | |
| private function handleBulkSubmit() | |
| { | |
| $variables = parseEnvFormatToArray($this->variables); | |
| $changesMade = false; | |
| \DB::transaction(function () use ($variables, &$changesMade) { | |
| // Delete removed variables | |
| $deletedCount = $this->deleteRemovedVariables($variables); | |
| if ($deletedCount > 0) { | |
| $changesMade = true; | |
| } | |
| // Update or create variables | |
| $updatedCount = $this->updateOrCreateVariables($variables); | |
| if ($updatedCount > 0) { | |
| $changesMade = true; | |
| } | |
| }); | |
| if ($changesMade) { | |
| $this->dispatch('success', 'Environment variables updated.'); | |
| } | |
| } | |
| private function deleteRemovedVariables($variables) | |
| { | |
| $variablesToDelete = $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | |
| if ($variablesToDelete->isEmpty()) { | |
| return 0; | |
| } | |
| $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | |
| return $variablesToDelete->count(); | |
| } | |
| private function updateOrCreateVariables($variables) | |
| { | |
| $count = 0; | |
| foreach ($variables as $key => $value) { | |
| $found = $this->project->environment_variables()->where('key', $key)->first(); | |
| if ($found) { | |
| if (! $found->is_shown_once && ! $found->is_multiline) { | |
| if ($found->value !== $value) { | |
| $found->value = $value; | |
| $found->save(); | |
| $count++; | |
| } | |
| } | |
| } else { | |
| $this->project->environment_variables()->create([ | |
| 'key' => $key, | |
| 'value' => $value, | |
| 'is_multiline' => false, | |
| 'is_literal' => false, | |
| 'type' => 'project', | |
| 'team_id' => currentTeam()->id, | |
| ]); | |
| $count++; | |
| } | |
| } | |
| return $count; | |
| } |
🤖 Prompt for AI Agents
In app/Livewire/SharedVariables/Project/Show.php around lines 95 to 158, the
bulk submit flow performs multiple deletes/updates/creates without a
transaction; wrap the deleteRemovedVariables and updateOrCreateVariables calls
inside a single DB::transaction so the operations are atomic. Modify
handleBulkSubmit to begin a transaction, perform the delete and update/create
inside it, commit on success (keeping the existing change counting and success
dispatch), and let the transaction roll back on exception (optionally catch
exceptions to dispatch an error and rethrow or return). Ensure the DB facade is
imported/available.
| private function handleBulkSubmit() | ||
| { | ||
| $variables = parseEnvFormatToArray($this->variables); | ||
| $changesMade = false; | ||
|
|
||
| // Delete removed variables | ||
| $deletedCount = $this->deleteRemovedVariables($variables); | ||
| if ($deletedCount > 0) { | ||
| $changesMade = true; | ||
| } | ||
|
|
||
| // Update or create variables | ||
| $updatedCount = $this->updateOrCreateVariables($variables); | ||
| if ($updatedCount > 0) { | ||
| $changesMade = true; | ||
| } | ||
|
|
||
| if ($changesMade) { | ||
| $this->dispatch('success', 'Environment variables updated.'); | ||
| } | ||
| } | ||
|
|
||
| private function deleteRemovedVariables($variables) | ||
| { | ||
| $variablesToDelete = $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | ||
|
|
||
| if ($variablesToDelete->isEmpty()) { | ||
| return 0; | ||
| } | ||
|
|
||
| $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | ||
|
|
||
| return $variablesToDelete->count(); | ||
| } | ||
|
|
||
| private function updateOrCreateVariables($variables) | ||
| { | ||
| $count = 0; | ||
| foreach ($variables as $key => $value) { | ||
| $found = $this->team->environment_variables()->where('key', $key)->first(); | ||
|
|
||
| if ($found) { | ||
| if (! $found->is_shown_once && ! $found->is_multiline) { | ||
| if ($found->value !== $value) { | ||
| $found->value = $value; | ||
| $found->save(); | ||
| $count++; | ||
| } | ||
| } | ||
| } else { | ||
| $this->team->environment_variables()->create([ | ||
| 'key' => $key, | ||
| 'value' => $value, | ||
| 'is_multiline' => false, | ||
| 'is_literal' => false, | ||
| 'type' => 'team', | ||
| 'team_id' => currentTeam()->id, | ||
| ]); | ||
| $count++; | ||
| } | ||
| } | ||
|
|
||
| return $count; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Wrap bulk operations in a database transaction.
The bulk submission process involves multiple database writes (deletions, updates, creations) that should be atomic. Per coding guidelines, use database transactions to group related write operations for consistency.
Apply this diff:
private function handleBulkSubmit()
{
- $variables = parseEnvFormatToArray($this->variables);
- $changesMade = false;
-
- // Delete removed variables
- $deletedCount = $this->deleteRemovedVariables($variables);
- if ($deletedCount > 0) {
- $changesMade = true;
- }
-
- // Update or create variables
- $updatedCount = $this->updateOrCreateVariables($variables);
- if ($updatedCount > 0) {
- $changesMade = true;
- }
-
- if ($changesMade) {
- $this->dispatch('success', 'Environment variables updated.');
- }
+ $variables = parseEnvFormatToArray($this->variables);
+ $changesMade = false;
+
+ \DB::transaction(function () use ($variables, &$changesMade) {
+ // Delete removed variables
+ $deletedCount = $this->deleteRemovedVariables($variables);
+ if ($deletedCount > 0) {
+ $changesMade = true;
+ }
+
+ // Update or create variables
+ $updatedCount = $this->updateOrCreateVariables($variables);
+ if ($updatedCount > 0) {
+ $changesMade = true;
+ }
+ });
+
+ if ($changesMade) {
+ $this->dispatch('success', 'Environment variables updated.');
+ }
}As per coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleBulkSubmit() | |
| { | |
| $variables = parseEnvFormatToArray($this->variables); | |
| $changesMade = false; | |
| // Delete removed variables | |
| $deletedCount = $this->deleteRemovedVariables($variables); | |
| if ($deletedCount > 0) { | |
| $changesMade = true; | |
| } | |
| // Update or create variables | |
| $updatedCount = $this->updateOrCreateVariables($variables); | |
| if ($updatedCount > 0) { | |
| $changesMade = true; | |
| } | |
| if ($changesMade) { | |
| $this->dispatch('success', 'Environment variables updated.'); | |
| } | |
| } | |
| private function deleteRemovedVariables($variables) | |
| { | |
| $variablesToDelete = $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | |
| if ($variablesToDelete->isEmpty()) { | |
| return 0; | |
| } | |
| $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | |
| return $variablesToDelete->count(); | |
| } | |
| private function updateOrCreateVariables($variables) | |
| { | |
| $count = 0; | |
| foreach ($variables as $key => $value) { | |
| $found = $this->team->environment_variables()->where('key', $key)->first(); | |
| if ($found) { | |
| if (! $found->is_shown_once && ! $found->is_multiline) { | |
| if ($found->value !== $value) { | |
| $found->value = $value; | |
| $found->save(); | |
| $count++; | |
| } | |
| } | |
| } else { | |
| $this->team->environment_variables()->create([ | |
| 'key' => $key, | |
| 'value' => $value, | |
| 'is_multiline' => false, | |
| 'is_literal' => false, | |
| 'type' => 'team', | |
| 'team_id' => currentTeam()->id, | |
| ]); | |
| $count++; | |
| } | |
| } | |
| return $count; | |
| } | |
| private function handleBulkSubmit() | |
| { | |
| $variables = parseEnvFormatToArray($this->variables); | |
| $changesMade = false; | |
| \DB::transaction(function () use ($variables, &$changesMade) { | |
| // Delete removed variables | |
| $deletedCount = $this->deleteRemovedVariables($variables); | |
| if ($deletedCount > 0) { | |
| $changesMade = true; | |
| } | |
| // Update or create variables | |
| $updatedCount = $this->updateOrCreateVariables($variables); | |
| if ($updatedCount > 0) { | |
| $changesMade = true; | |
| } | |
| }); | |
| if ($changesMade) { | |
| $this->dispatch('success', 'Environment variables updated.'); | |
| } | |
| } | |
| private function deleteRemovedVariables($variables) | |
| { | |
| $variablesToDelete = $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->get(); | |
| if ($variablesToDelete->isEmpty()) { | |
| return 0; | |
| } | |
| $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); | |
| return $variablesToDelete->count(); | |
| } | |
| private function updateOrCreateVariables($variables) | |
| { | |
| $count = 0; | |
| foreach ($variables as $key => $value) { | |
| $found = $this->team->environment_variables()->where('key', $key)->first(); | |
| if ($found) { | |
| if (! $found->is_shown_once && ! $found->is_multiline) { | |
| if ($found->value !== $value) { | |
| $found->value = $value; | |
| $found->save(); | |
| $count++; | |
| } | |
| } | |
| } else { | |
| $this->team->environment_variables()->create([ | |
| 'key' => $key, | |
| 'value' => $value, | |
| 'is_multiline' => false, | |
| 'is_literal' => false, | |
| 'type' => 'team', | |
| 'team_id' => currentTeam()->id, | |
| ]); | |
| $count++; | |
| } | |
| } | |
| return $count; | |
| } |
🤖 Prompt for AI Agents
In app/Livewire/SharedVariables/Team/Index.php around lines 89 to 152, the bulk
submit flow performs multiple deletes/updates/creates without a transaction;
wrap the deleteRemovedVariables and updateOrCreateVariables calls in a single
database transaction (use DB::transaction or
DB::beginTransaction/commit/rollback) so all writes are atomic, ensure any
exception triggers a rollback, and only dispatch the success event after the
transaction completes successfully; adjust helper methods if needed so they run
inside the same transaction context and do not commit independently.
| @can('update', $environment) | ||
| <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> | ||
| @endcan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Migrate to single-line authorization pattern for the switch button.
Per coding guidelines, prefer using canGate and :canResource on x-forms components instead of wrapping them in @can blocks.
Apply this diff:
- @can('update', $environment)
- <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
- @endcan
+ <x-forms.button canGate="update" :canResource="$environment" wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>Based on coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @can('update', $environment) | |
| <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> | |
| @endcan | |
| <x-forms.button canGate="update" :canResource="$environment" wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> |
🤖 Prompt for AI Agents
In resources/views/livewire/shared-variables/environment/show.blade.php around
lines 12 to 14, replace the @can wrapper with the single-line authorization
pattern by removing the @can('update', $environment) ... @endcan block and
instead add canGate="update" and :canResource="$environment" attributes to the
<x-forms.button> component (keep the existing wire:click='switch' and label
expression unchanged) so the button itself enforces the authorization.
| <form wire:submit='submit' class="flex flex-col gap-2"> | ||
| @can('update', $environment) | ||
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | ||
| label="Environment Shared Variables"></x-forms.textarea> | ||
| <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button> | ||
| @else | ||
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | ||
| label="Environment Shared Variables" disabled></x-forms.textarea> | ||
| @endcan | ||
| </form> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Migrate to component-level authorization for developer view form.
Per coding guidelines, avoid wrapping x-forms.* components in @can/@else blocks. Use canGate and :canResource on the components directly; autoDisable defaults to true and will handle the disabled state automatically.
Apply this diff:
@else
<form wire:submit='submit' class="flex flex-col gap-2">
- @can('update', $environment)
- <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
- label="Environment Shared Variables"></x-forms.textarea>
- <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
- @else
- <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
- label="Environment Shared Variables" disabled></x-forms.textarea>
- @endcan
+ <x-forms.textarea canGate="update" :canResource="$environment" rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
+ label="Environment Shared Variables"></x-forms.textarea>
+ <x-forms.button canGate="update" :canResource="$environment" type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
</form>
@endifBased on coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <form wire:submit='submit' class="flex flex-col gap-2"> | |
| @can('update', $environment) | |
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | |
| label="Environment Shared Variables"></x-forms.textarea> | |
| <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button> | |
| @else | |
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | |
| label="Environment Shared Variables" disabled></x-forms.textarea> | |
| @endcan | |
| </form> | |
| <form wire:submit='submit' class="flex flex-col gap-2"> | |
| <x-forms.textarea canGate="update" :canResource="$environment" rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | |
| label="Environment Shared Variables"></x-forms.textarea> | |
| <x-forms.button canGate="update" :canResource="$environment" type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button> | |
| </form> |
🤖 Prompt for AI Agents
In resources/views/livewire/shared-variables/environment/show.blade.php around
lines 30 to 39, the view uses an @can/@else block to enable/disable x-forms
components; change this to component-level authorization by removing the
@can/@else wrapper and adding canGate="update" and :canResource="$environment"
attributes to the x-forms.textarea and x-forms.button components (rely on
autoDisable=true so the textarea/button will auto-disable for unauthorized
users) and keep the same rows, id, wire:model, label and button type/label.
| @can('update', $project) | ||
| <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> | ||
| @endcan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Migrate to single-line authorization pattern for the switch button.
Per coding guidelines, prefer using canGate and :canResource on x-forms components instead of wrapping them in @can blocks.
Apply this diff:
- @can('update', $project)
- <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
- @endcan
+ <x-forms.button canGate="update" :canResource="$project" wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>Based on coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @can('update', $project) | |
| <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> | |
| @endcan | |
| <x-forms.button canGate="update" :canResource="$project" wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> |
🤖 Prompt for AI Agents
In resources/views/livewire/shared-variables/project/show.blade.php around lines
12 to 14, replace the @can wrapper with the single-line authorization pattern on
the x-forms.button by adding canGate="update" and :canResource="$project" to the
component and keeping the existing wire:click and label expression; ensure you
remove the surrounding @can/@endcan lines so the button uses component-level
authorization instead of a Blade directive.
| <form wire:submit='submit' class="flex flex-col gap-2"> | ||
| @can('update', $project) | ||
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | ||
| label="Project Shared Variables"></x-forms.textarea> | ||
| <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button> | ||
| @else | ||
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | ||
| label="Project Shared Variables" disabled></x-forms.textarea> | ||
| @endcan | ||
| </form> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Migrate to component-level authorization for developer view form.
Per coding guidelines, avoid wrapping x-forms.* components in @can/@else blocks. Use canGate and :canResource on the components directly; autoDisable defaults to true and will handle the disabled state automatically.
Apply this diff:
@else
<form wire:submit='submit' class="flex flex-col gap-2">
- @can('update', $project)
- <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
- label="Project Shared Variables"></x-forms.textarea>
- <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
- @else
- <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
- label="Project Shared Variables" disabled></x-forms.textarea>
- @endcan
+ <x-forms.textarea canGate="update" :canResource="$project" rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
+ label="Project Shared Variables"></x-forms.textarea>
+ <x-forms.button canGate="update" :canResource="$project" type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
</form>
@endifBased on coding guidelines
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In resources/views/livewire/shared-variables/project/show.blade.php around lines
32 to 41, remove the outer @can/@else wrapper and instead put component-level
authorization attributes on the form controls: add canGate="update" and
:canResource="$project" to the <x-forms.textarea> and the <x-forms.button> (the
components will autoDisable by default), and keep the same
rows/class/id/wire:model/label attributes; this ensures the textarea and button
handle disabled state via the component-level authorization instead of the blade
@can block.
| @can('update', $team) | ||
| <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> | ||
| @endcan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Migrate to single-line authorization pattern for the switch button.
Per coding guidelines, prefer using canGate and :canResource on x-forms components instead of wrapping them in @can blocks.
Apply this diff:
- @can('update', $team)
- <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
- @endcan
+ <x-forms.button canGate="update" :canResource="$team" wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>Based on coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @can('update', $team) | |
| <x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> | |
| @endcan | |
| <x-forms.button canGate="update" :canResource="$team" wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> |
🤖 Prompt for AI Agents
In resources/views/livewire/shared-variables/team/index.blade.php around lines
12 to 14, replace the @can wrapper with the single-line authorization pattern on
the x-forms.button component: remove the @can/@endcan block and add
canGate="update" and :canResource="$team" attributes to the <x-forms.button>
while keeping the existing wire:click and label expression so the button renders
conditionally using the component's authorization props.
| <form wire:submit='submit' class="flex flex-col gap-2"> | ||
| @can('update', $team) | ||
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | ||
| label="Team Shared Variables"></x-forms.textarea> | ||
| <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button> | ||
| @else | ||
| <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables" | ||
| label="Team Shared Variables" disabled></x-forms.textarea> | ||
| @endcan | ||
| </form> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Migrate to component-level authorization for developer view form.
Per coding guidelines, avoid wrapping x-forms.* components in @can/@else blocks. Use canGate and :canResource on the components directly; autoDisable defaults to true and will handle the disabled state automatically.
Apply this diff:
@else
<form wire:submit='submit' class="flex flex-col gap-2">
- @can('update', $team)
- <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
- label="Team Shared Variables"></x-forms.textarea>
- <x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
- @else
- <x-forms.textarea rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
- label="Team Shared Variables" disabled></x-forms.textarea>
- @endcan
+ <x-forms.textarea canGate="update" :canResource="$team" rows="20" class="whitespace-pre-wrap" id="variables" wire:model="variables"
+ label="Team Shared Variables"></x-forms.textarea>
+ <x-forms.button canGate="update" :canResource="$team" type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
</form>
@endifBased on coding guidelines
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In resources/views/livewire/shared-variables/team/index.blade.php around lines
31 to 40, the template wraps x-forms components in an @can/@else block; update
to component-level authorization by removing the @can/@else wrapper and applying
canGate and :canResource on the components (e.g., add canGate="update" and
:canResource="$team" to the textarea and the submit button) letting autoDisable
(defaults to true) handle disabled state so you must also remove the manual
disabled attribute and the conditional block structure.
Changes
Preview:

Summary by CodeRabbit