Skip to content

Conversation

@adiologydev
Copy link
Contributor

@adiologydev adiologydev commented Nov 2, 2025

Changes

  • Adds developer view to shared variables for environments, projects, and teams.

Preview:
image

Summary by CodeRabbit

  • New Features
    • Added a developer view toggle for environment and shared variables across teams, projects, and environments.
    • Introduced bulk editing capability: users can now edit multiple variables at once in a text format via the developer view.
    • Developer view displays variables in a formatted, human-readable layout with special indicators for different variable types.

@Cinzya Cinzya added 🐰 Release The Rabbit Run CodeRabbitAI review ✨ Enhancement Issues requesting new features, new services or improvements. labels Nov 3, 2025
@ShadowArcanist ShadowArcanist added 🐰 Release The Rabbit Run CodeRabbitAI review and removed 🐰 Release The Rabbit Run CodeRabbitAI review labels Nov 3, 2025
@ShadowArcanist
Copy link
Member

@CodeRabbit review?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

@ShadowArcanist: I'll review the changes in this PR right away!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Walkthrough

Added 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

Cohort / File(s) Summary
Environment Show Component
app/Livewire/SharedVariables/Environment/Show.php
Explicit listener routing, view state properties ($view, $variables), dev view toggle and formatting methods, bulk submission workflow with variable deletion and update/create operations
Project Show Component
app/Livewire/SharedVariables/Project/Show.php
Identical pattern to Environment: view state properties, dev view toggle, formatting, bulk submission workflow, and supporting helpers
Team Index Component
app/Livewire/SharedVariables/Team/Index.php
Parallel implementation of dev mode: view state, toggle mechanics, formatting, bulk processing for variable lifecycle management
Environment Show Template
resources/views/livewire/shared-variables/environment/show.blade.php
Toggle button between "Normal view" and "Developer view", conditional rendering with textarea for bulk editing in dev mode
Project Show Template
resources/views/livewire/shared-variables/project/show.blade.php
Toggle control between view modes, dual-path rendering: list view (normal) and textarea form (developer)
Team Index Template
resources/views/livewire/shared-variables/team/index.blade.php
View mode toggle button, conditional UI with normal list view and developer textarea form with save functionality

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Bulk submission logic: Review handleBulkSubmit(), deleteRemovedVariables(), and updateOrCreateVariables() for data consistency, edge cases (empty submissions, all-delete scenarios), and transaction safety.
  • Variable formatting: Verify formatEnvironmentVariables() handles locked, multiline, and shown-once variables correctly across all three components; check for parsing robustness.
  • Authorization checks: Confirm permission gates on toggle buttons and textarea editability match component authorization rules.
  • Listener refactoring: Validate explicit event handlers (refreshEnvs, environmentVariableDeleted) properly refresh dev view state and prevent stale UI.
  • Pattern consistency: Ensure identical patterns across Environment, Project, and Team components for maintainability.

Suggested reviewers

  • peaklabs-dev

Poem

🐰 Three components now in dev-view bright,
With bulk edits made easy and right.
Toggle and toggle, between views we dance,
Variables formatted at a glance—
Environment, Project, and Team all aligned,
A rabbit-approved refactor, so refined! 🌿✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete; it lacks required sections like detailed changes list and issues reference, and omits the submission checklist removal confirmation. Add a comprehensive changes section with bullet points for each component modified, include an issues section with relevant issue links, and confirm checklist removal.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main feature: adding a developer view for shared environment variables across the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
Contributor

@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: 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): string

As per coding guidelines


76-87: Add validation rules for bulk submission.

The submit() method processes user input from the $variables textarea but does not define or invoke validation rules. Per coding guidelines, Livewire components should declare protected $rules and 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.php and app/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): string

As per coding guidelines


82-93: Add validation rules for bulk submission.

The submit() method processes user input from the $variables textarea but does not define or invoke validation rules. Per coding guidelines, Livewire components should declare protected $rules and 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): string

As per coding guidelines


85-96: Add validation rules for bulk submission.

The submit() method processes user input from the $variables textarea but does not define or invoke validation rules. Per coding guidelines, Livewire components should declare protected $rules and 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9e3fce1 and 2e6b8a6.

📒 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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • app/Livewire/SharedVariables/Team/Index.php
  • app/Livewire/SharedVariables/Environment/Show.php
  • resources/views/livewire/shared-variables/project/show.blade.php
  • app/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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 performance

Place 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.php
  • app/Livewire/SharedVariables/Environment/Show.php
  • app/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.php
  • app/Livewire/SharedVariables/Environment/Show.php
  • app/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.php
  • app/Livewire/SharedVariables/Environment/Show.php
  • app/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.php
  • app/Livewire/SharedVariables/Environment/Show.php
  • app/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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.php
  • resources/views/livewire/shared-variables/environment/show.blade.php
  • resources/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.php
  • resources/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.php
  • resources/views/livewire/shared-variables/project/show.blade.php

Comment on lines 98 to 161
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;
}
Copy link
Contributor

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.

Suggested change
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.

Comment on lines 95 to 158
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;
}
Copy link
Contributor

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.

Suggested change
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.

Comment on lines 89 to 152
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;
}
Copy link
Contributor

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.

Suggested change
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.

Comment on lines 12 to 14
@can('update', $environment)
<x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
@endcan
Copy link
Contributor

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.

Suggested change
@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.

Comment on lines 30 to 39
<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>
Copy link
Contributor

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>
     @endif

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.

Suggested change
<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.

Comment on lines 12 to 14
@can('update', $project)
<x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
@endcan
Copy link
Contributor

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.

Suggested change
@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.

Comment on lines 32 to 41
<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>
Copy link
Contributor

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>
     @endif

Based 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.

Comment on lines 12 to 14
@can('update', $team)
<x-forms.button wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
@endcan
Copy link
Contributor

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.

Suggested change
@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.

Comment on lines 31 to 40
<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>
Copy link
Contributor

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>
     @endif

Based 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Enhancement Issues requesting new features, new services or improvements. 🐰 Release The Rabbit Run CodeRabbitAI review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants