feat(ui): Shadow UI redesign, domain management, and DNS autoconfigure (#11119)

Co-authored-by: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com>
This commit is contained in:
Andras BacsaiandShadowArcanist authored and GitHub committed 2026-08-03 23:11:54 +02:00
1 parent 0b843bb07c
commit 8ae56587d5
497 files changed
+44045 -22630

No files matched your search

@@ -1,47 +1,64 @@
<form class="flex flex-col w-full gap-2 rounded-sm" wire:submit='submit'
<form class="flex w-full flex-col gap-4" wire:submit='submit'
x-data="{ isMultiline: $wire.entangle('is_multiline') }">
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required />
<template x-if="isMultiline">
<div wire:key="env-value-textarea">
<x-forms.textarea id="value" label="Value" required class="font-sans" spellcheck />
</div>
</template>
<template x-if="!isMultiline">
<div wire:key="env-value-input">
<x-forms.env-var-input placeholder="production" id="value" label="Value" required
:availableVars="$shared ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')"
:serverUuid="data_get($parameters, 'server_uuid')" />
</div>
</template>
<div class="grid gap-4 sm:grid-cols-2">
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required />
<x-forms.input id="comment" label="Comment" placeholder="Optional note"
helper="Add a note to document what this environment variable is used for." maxlength="256" />
</div>
<div>
<template x-if="isMultiline">
<div wire:key="env-value-textarea">
<x-forms.textarea id="value" label="Value" required class="font-sans" spellcheck />
</div>
</template>
<template x-if="!isMultiline">
<div wire:key="env-value-input">
<x-forms.env-var-input placeholder="production" id="value" label="Value" required
:availableVars="$shared ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')"
:serverUuid="data_get($parameters, 'server_uuid')" />
</div>
</template>
@if (!$shared)
<div x-cloak x-show="!isMultiline" wire:key="env-value-tip"
class="mt-1.5 text-xs text-neutral-500 dark:text-fg-faint">
Tip: Type <span class="font-mono text-coollabs dark:text-warning">{{ '{{' }}</span> to reference a
shared environment variable
</div>
@endif
</div>
<div class="grid gap-4 border-t border-neutral-200 pt-4 dark:border-white/[0.07] sm:grid-cols-2">
<x-forms.listbox id="is_multiline" label="Value type" :live="true" :options="[
['value' => false, 'label' => 'Single line'],
['value' => true, 'label' => 'Multiline'],
]" />
@if (!$shared)
<x-forms.listbox id="is_literal" label="Interpolation" :options="[
['value' => false, 'label' => 'Interpolate $VARIABLES'],
['value' => true, 'label' => 'Literal (keep $ characters as-is)'],
]"
helper="Literal means $VARIABLES in the value is kept as the actual characters '$VARIABLES' instead of being resolved from another variable. Useful when your value contains a $ sign." />
<x-forms.listbox id="is_buildtime" label="Build time" :options="[
['value' => true, 'label' => 'Available during build'],
['value' => false, 'label' => 'Not available during build'],
]"
helper="Make this variable available during the Docker build process. Useful for build secrets and dependencies." />
<x-forms.listbox id="is_runtime" label="Runtime" :options="[
['value' => true, 'label' => 'Available in the container'],
['value' => false, 'label' => 'Not available in the container'],
]" helper="Make this variable available in the running container at runtime." />
@endif
</div>
@if (!$shared)
<div x-cloak x-show="!isMultiline" wire:key="env-value-tip" class="text-xs text-neutral-500 dark:text-neutral-400 -mt-1">
Tip: Type <span class="font-mono dark:text-warning text-coollabs">{{</span> to reference a shared environment
variable
</div>
@endif
<x-forms.input id="comment" label="Comment"
helper="Add a note to document what this environment variable is used for." maxlength="256" />
@if (!$shared)
<x-forms.checkbox id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-environment-variable-warning :problematic-variables="$problematicVariables" />
<x-forms.checkbox id="is_runtime" helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
<x-forms.checkbox id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
<x-forms.checkbox id="is_multiline" x-model="isMultiline" label="Is Multiline?" />
<x-forms.button type="submit" @click="slideOverOpen=false">
Save
</x-forms.button>
<div class="flex justify-end border-t border-neutral-200 pt-4 dark:border-white/[0.07]">
<x-forms.button type="submit" @click="modalOpen = false">
Add variable
</x-forms.button>
</div>
</form>
@@ -1,140 +1,192 @@
<div class="flex flex-col gap-4">
<div>
<div class="flex items-center gap-2">
<h2>Environment Variables</h2>
@can('manageEnvironment', $resource)
<div class="flex flex-col items-center">
<x-modal-input buttonTitle="+ Add" title="New Environment Variable" :closeOutside="false">
<div class="flex flex-col gap-4" wire:init="loadEnvironmentVariables">
<x-application.settings-section id="environment-variables-section" title="Environment variables"
helper="Environment variables (secrets) for this resource.">
@can('manageEnvironment', $resource)
<x-slot:actions>
<x-forms.button wire:click='switch' wire:loading.attr="disabled"
wire:target="loadEnvironmentVariables,switch">
{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}
</x-forms.button>
</x-slot:actions>
@endcan
@if ($view === 'normal')
@if ($resourceClass === 'App\Models\Application')
<div class="grid w-full items-end gap-4 sm:grid-cols-2">
@if (data_get($resource, 'build_pack') !== 'dockercompose')
<x-forms.listbox id="is_env_sorting_enabled" label="Environment variable order"
onChange="instantSave"
helper="Controls how environment variables are ordered in the list and written to the generated .env file on deploy."
:options="[
['value' => false, 'label' => 'Creation order'],
['value' => true, 'label' => 'Alphabetical'],
]" :disabled="! auth()->user()->can('manageEnvironment', $resource)" />
@endif
<x-forms.listbox id="use_build_secrets" label="Build secrets" onChange="instantSave"
helper="Docker BuildKit secrets keep values out of the final image for enhanced security during builds. Requires Docker 18.09+ with BuildKit support."
:options="[
['value' => false, 'label' => 'Standard build arguments'],
['value' => true, 'label' => 'Docker BuildKit secrets'],
]" :disabled="! auth()->user()->can('manageEnvironment', $resource)" />
</div>
@else
<p class="text-sm text-neutral-500 dark:text-fg-dim">Manage this resource's environment variables below.</p>
@endif
@else
<form wire:submit.prevent='submit' class="flex w-full flex-col gap-4">
@can('manageEnvironment', $resource)
<x-callout type="info" title="Note">
Inline comments with space before # (e.g., <code class="font-mono">KEY=value #comment</code>) are stripped.
</x-callout>
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans" id="variables"
wire:model="variables" label="Production"></x-forms.textarea>
@if ($showPreview)
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans" label="Preview deployments"
id="variablesPreview" wire:model="variablesPreview"></x-forms.textarea>
@endif
<x-unsaved-bar action="submit" />
@else
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans" id="variables"
wire:model="variables" label="Production" disabled></x-forms.textarea>
@if ($showPreview)
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans" label="Preview deployments"
id="variablesPreview" wire:model="variablesPreview" disabled></x-forms.textarea>
@endif
@endcan
</form>
@endif
</x-application.settings-section>
{{-- Toolbar: search left; filter and add right --}}
@if ($view === 'normal')
<div class="mt-2 flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center"
@if (! $readyToLoad) aria-busy="true" @endif>
<div class="relative min-w-0 w-full flex-1 sm:max-w-md">
<input type="search" placeholder="Search environment variables"
aria-label="Search environment variables" wire:model.live.debounce.300ms="search"
class="input w-full pl-8!" @disabled(! $readyToLoad) />
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-2.5">
<x-reicon name="search" wire:loading.remove wire:target="search,loadEnvironmentVariables"
class="size-3.5 text-neutral-400 dark:text-fg-faint" />
<svg wire:loading wire:target="search,loadEnvironmentVariables" aria-hidden="true"
class="size-3.5 animate-spin text-neutral-400 dark:text-fg-dim" fill="none"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
<path class="opacity-75" fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
</div>
</div>
<div class="flex flex-wrap items-center gap-2 sm:ml-auto">
@if ($resource->type() === 'application' && $showPreview)
<div class="relative" x-data="{ open: false }" @keydown.escape.window="open = false">
<button type="button" class="button" @click="open = !open" @click.outside="open = false"
aria-haspopup="listbox" :aria-expanded="open" @disabled(! $readyToLoad)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.8"
stroke="currentColor" class="size-3.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 0 1-.659 1.591l-5.432 5.432a2.25 2.25 0 0 0-.659 1.591v2.927a2.25 2.25 0 0 1-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 0 0-.659-1.591L3.659 7.409A2.25 2.25 0 0 1 3 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0 1 12 3Z" />
</svg>
Filter
</button>
<div class="listbox-panel left-auto! right-0! z-[90]! min-w-48!" x-show="open" x-cloak
role="listbox">
@foreach ([
'all' => 'All environments',
'production' => 'Production',
'preview' => 'Preview',
] as $filterValue => $filterLabel)
<button type="button" class="listbox-option" role="option"
aria-selected="{{ $environmentFilter === $filterValue ? 'true' : 'false' }}"
wire:click="setEnvironmentFilter('{{ $filterValue }}')" @click="open = false">
<span class="truncate">{{ $filterLabel }}</span>
@if ($environmentFilter === $filterValue)
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="2.5" stroke="currentColor" class="size-3.5 shrink-0">
<path stroke-linecap="round" stroke-linejoin="round"
d="m4.5 12.75 6 6 9-13.5" />
</svg>
@endif
</button>
@endforeach
</div>
</div>
@endif
@can('manageEnvironment', $resource)
{{-- Do not disable Add based on readyToLoad: modal-input uses wire:ignore, so a
disabled attribute painted on first load would never re-enable. --}}
<x-modal-input title="New Environment Variable" :closeOutside="false">
<x-slot:content>
<button type="button"
class="button bg-coollabs/10! text-coollabs! ring-1 ring-coollabs/25 hover:bg-coollabs/15! dark:bg-warning/15! dark:text-warning! dark:ring-warning/25 dark:hover:bg-warning/20!">
<x-reicon name="plus" class="size-3.5" />
Add
</button>
</x-slot:content>
<livewire:project.shared.environment-variable.add />
</x-modal-input>
</div>
<x-forms.button
wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
@endcan
</div>
<div>Environment variables (secrets) for this resource. </div>
@if ($resourceClass === 'App\Models\Application')
<div class="flex flex-col gap-2 pt-2">
@if (data_get($resource, 'build_pack') !== 'dockercompose')
<div class="w-64">
@can('manageEnvironment', $resource)
<x-forms.checkbox id="is_env_sorting_enabled" label="Sort alphabetically"
helper="Turn this off if one environment is dependent on another. It will be sorted by creation order (like you pasted them or in the order you created them)."
instantSave></x-forms.checkbox>
@else
<x-forms.checkbox id="is_env_sorting_enabled" label="Sort alphabetically"
helper="Turn this off if one environment is dependent on another. It will be sorted by creation order (like you pasted them or in the order you created them)."
disabled></x-forms.checkbox>
@endcan
</div>
@endif
<div class="w-64">
@can('manageEnvironment', $resource)
<x-forms.checkbox id="use_build_secrets" label="Use Docker Build Secrets"
helper="Enable Docker BuildKit secrets for enhanced security during builds. Secrets won't be exposed in the final image. Requires Docker 18.09+ with BuildKit support."
instantSave></x-forms.checkbox>
@else
<x-forms.checkbox id="use_build_secrets" label="Use Docker Build Secrets"
helper="Enable Docker BuildKit secrets for enhanced security during builds. Secrets won't be exposed in the final image. Requires Docker 18.09+ with BuildKit support."
disabled></x-forms.checkbox>
@endcan
</div>
@endcan
</div>
@endif
</div>
</div>
@endif
@if ($view === 'normal')
<div class="w-full md:w-96">
<div class="relative">
<input type="search" placeholder="Search" aria-label="Search environment variables"
wire:model.live.debounce.300ms="search" class="w-full input pl-10" />
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<div class="relative w-4 h-4">
<svg wire:loading.remove wire:target="search" aria-hidden="true"
class="absolute inset-0 w-4 h-4 dark:text-neutral-400" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<svg wire:loading wire:target="search" aria-hidden="true"
class="absolute inset-0 w-4 h-4 text-coollabs dark:text-warning animate-spin" fill="none"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
stroke-width="4" />
<path class="opacity-75" fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
</div>
</div>
@if (! $readyToLoad)
<div id="environment-table-section"
class="application-settings-section-body mt-1 flex min-h-40 w-full scroll-mt-28 items-center justify-center"
wire:loading.class="opacity-100" wire:target="loadEnvironmentVariables">
<x-loading text="Loading environment variables..." />
</div>
</div>
@if ($this->isSearchActive && ! $this->hasEnvironmentVariables)
<div>No environment variables found.</div>
@else
@if ($this->environmentVariables->isNotEmpty() || $this->hardcodedEnvironmentVariables->isNotEmpty())
<div>
<h3>Production Environment Variables</h3>
<div>Environment (secrets) variables for Production.</div>
</div>
@foreach ($this->environmentVariables as $env)
<livewire:project.shared.environment-variable.show wire:key="environment-{{ $env->id }}" :env="$env"
:type="$resource->type()" />
@endforeach
@if (($resource->type() === 'service' || $resource?->build_pack === 'dockercompose') && $this->hardcodedEnvironmentVariables->isNotEmpty())
@foreach ($this->hardcodedEnvironmentVariables as $index => $env)
<livewire:project.shared.environment-variable.show-hardcoded
wire:key="hardcoded-prod-{{ $env['key'] }}-{{ $env['service_name'] ?? 'default' }}-{{ $index }}" :env="$env" />
@endforeach
@php
$totalRows = $this->environmentVariableRowCount;
$currentPage = $this->currentEnvironmentVariablePage;
$lastPage = $this->environmentVariableLastPage;
$firstVisibleRow = $totalRows === 0 ? 0 : ($currentPage - 1) * $perPage + 1;
$lastVisibleRow = min($currentPage * $perPage, $totalRows);
@endphp
<div id="environment-table-section"
class="application-settings-section-body mt-1 scroll-mt-28 {{ $totalRows > 0 ? 'is-flush' : '' }} w-full">
@if ($this->isSearchActive && $totalRows === 0)
<x-empty size="sm" title="No environment variables found"
description="No variables match your search." />
@elseif ($totalRows > 0)
<div class="data-table w-full transition-opacity"
wire:loading.class="opacity-50 pointer-events-none"
wire:target="setEnvironmentVariablePage,previousEnvironmentVariablePage,nextEnvironmentVariablePage">
<div class="data-table-header env-table-grid">
<span>Name</span>
<span>Type</span>
<span>Comment</span>
<span class="text-center">Literal</span>
<span class="text-center">Multiline</span>
<span class="text-center">Buildtime</span>
<span class="text-center">Runtime</span>
<span></span>
</div>
@foreach ($this->environmentVariablePageRows as $row)
@if ($row['kind'] === 'managed')
<livewire:project.shared.environment-variable.show wire:key="{{ $row['id'] }}"
:env="$row['environmentVariable']" :type="$resource->type()" />
@else
<livewire:project.shared.environment-variable.show-hardcoded
wire:key="{{ $row['id'] }}" :env="$row['environmentVariable']"
:isPreview="$row['scope'] === 'preview'" />
@endif
@endforeach
<x-table-pagination :from="$firstVisibleRow" :to="$lastVisibleRow" :total="$totalRows"
:current-page="$currentPage" :last-page="$lastPage"
wire-target="setEnvironmentVariablePage,previousEnvironmentVariablePage,nextEnvironmentVariablePage"
first-action="setEnvironmentVariablePage(1)"
previous-action="previousEnvironmentVariablePage"
next-action="nextEnvironmentVariablePage"
last-action="setEnvironmentVariablePage({{ $lastPage }})" />
</div>
@else
<x-empty size="sm" title="No environment variables"
description="Add your first variable with the + Add button above."
icon-name="variables" />
@endif
@endif
@if (
$resource->type() === 'application' &&
$showPreview &&
($this->environmentVariablesPreview->isNotEmpty() || $this->hardcodedEnvironmentVariablesPreview->isNotEmpty())
)
<div>
<h3>Preview Deployments Environment Variables</h3>
<div>Environment (secrets) variables for Preview Deployments.</div>
</div>
@foreach ($this->environmentVariablesPreview as $env)
<livewire:project.shared.environment-variable.show wire:key="environment-{{ $env->id }}" :env="$env"
:type="$resource->type()" />
@endforeach
@if (($resource->type() === 'service' || $resource?->build_pack === 'dockercompose') && $this->hardcodedEnvironmentVariablesPreview->isNotEmpty())
@foreach ($this->hardcodedEnvironmentVariablesPreview as $index => $env)
<livewire:project.shared.environment-variable.show-hardcoded
wire:key="hardcoded-preview-{{ $env['key'] }}-{{ $env['service_name'] ?? 'default' }}-{{ $index }}"
:env="$env" />
@endforeach
@endif
@endif
</div>
@endif
@else
<form wire:submit.prevent='submit' class="flex flex-col gap-2">
@can('manageEnvironment', $resource)
<x-callout type="info" title="Note" class="mb-2">
Inline comments with space before # (e.g., <code class="font-mono">KEY=value #comment</code>) are stripped.
</x-callout>
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans" id="variables" wire:model="variables"
label="Production Environment Variables"></x-forms.textarea>
@if ($showPreview)
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans"
label="Preview Deployments Environment Variables" id="variablesPreview"
wire:model="variablesPreview"></x-forms.textarea>
@endif
<x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
@else
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans" id="variables" wire:model="variables"
label="Production Environment Variables" disabled></x-forms.textarea>
@if ($showPreview)
<x-forms.textarea rows="10" class="whitespace-pre-wrap font-sans"
label="Preview Deployments Environment Variables" id="variablesPreview" wire:model="variablesPreview"
disabled></x-forms.textarea>
@endif
@endcan
</form>
@endif
</div>
@@ -1,31 +1,24 @@
<div>
<div
class="flex flex-col items-center gap-4 p-4 bg-white border lg:items-start dark:bg-base dark:border-coolgray-300 border-neutral-200">
<div class="flex flex-wrap items-center gap-2">
<span
class="px-2 py-0.5 text-xs font-normal rounded dark:bg-coolgray-400/50 bg-neutral-200 dark:text-neutral-400 text-neutral-600">
Hardcoded env
</span>
@if($serviceName)
<span
class="px-2 py-0.5 text-xs font-normal rounded dark:bg-coolgray-400/50 bg-neutral-200 dark:text-neutral-400 text-neutral-600">
Service: {{ $serviceName }}
</span>
<div class="env-table-item"
x-show="typeof envFilter === 'undefined' || envFilter === 'all' || envFilter === '{{ $isPreview ? 'preview' : 'production' }}'">
<div class="data-table-row env-table-grid">
<div class="flex min-w-0 items-center gap-2">
<span class="env-key-label min-w-0 truncate font-mono text-[13px] text-black dark:text-fg" title="{{ $key }}">{{ $key }}</span>
<span class="table-badge shrink-0">Hardcoded</span>
@if ($serviceName)
<span class="table-badge shrink-0">{{ $serviceName }}</span>
@endif
<span class="env-type-mobile table-badge shrink-0">{{ $isPreview ? 'Preview' : 'Production' }}</span>
</div>
<div class="flex flex-col w-full gap-2">
<div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input disabled id="key" />
@if($value !== null && $value !== '')
<x-forms.input disabled type="password" value="{{ $value }}" />
@else
<x-forms.input disabled value="(inherited from host)" />
@endif
</div>
@if($comment)
<x-forms.input disabled value="{{ $comment }}" label="Comment"
helper="Documentation for this environment variable." />
@endif
<div class="env-type-desktop text-[13px] text-neutral-500 dark:text-fg-dim">
{{ $isPreview ? 'Preview' : 'Production' }}
</div>
<div class="min-w-0 truncate text-[13px] text-neutral-500 dark:text-fg-dim">
{{ $comment ?: ($value !== null && $value !== '' ? '-' : 'Inherited from host') }}
</div>
<span class="data-table-cell-dash">-</span>
<span class="data-table-cell-dash">-</span>
<span class="data-table-cell-dash">-</span>
<span class="data-table-cell-dash">-</span>
<div></div>
</div>
</div>
</div>
@@ -1,353 +1,233 @@
<div>
<form wire:submit='submit' @class([
'flex flex-col items-center gap-4 p-4 bg-white border lg:items-start dark:bg-base',
'border-error' => $is_really_required,
'dark:border-coolgray-300 border-neutral-200' => !$is_really_required,
])>
@if ($isLocked)
<div class="flex flex-1 w-full gap-2">
<x-forms.input disabled id="key" />
<svg class="icon my-1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
@php
$rowScope = $isSharedVariable ? 'shared' : (data_get($env, 'is_preview') ? 'preview' : 'production');
$rowScopeLabel = $isSharedVariable ? str($type)->headline() : ($rowScope === 'preview' ? 'Preview' : 'Production');
$canUpdate = auth()->user()?->can('update', $this->env) ?? false;
$canEditValue = $canUpdate && !$isLocked && !$isDisabled && !$isValueHidden;
$showValueType = !$is_redis_credential && !$isMagicVariable;
$showInterpolation = !$is_redis_credential && !$isMagicVariable && !$isSharedVariable;
$showBuildtime = !$is_redis_credential && !$isMagicVariable && !$isSharedVariable;
$showRuntime = !$is_redis_credential && !$isMagicVariable && !$isSharedVariable;
@endphp
<div class="env-table-item"
@if ($isSharedVariable) :style="`order: ${sharedSort === 'alphabetical' ? {{ $tableAlphabeticalOrder }} : {{ $tableCreationOrder }}}`" @endif
x-show="(typeof envFilter === 'undefined' || envFilter === 'all' || envFilter === '{{ $rowScope }}')
&& (typeof sharedSearch === 'undefined' || @js(mb_strtolower($env->key . ' ' . ($comment ?? '') . ' ' . $rowScopeLabel)).includes(sharedSearch.trim().toLowerCase()))">
<div class="data-table-row {{ $isSharedVariable ? 'env-table-grid-shared' : 'env-table-grid' }}">
<div class="flex min-w-0 items-center gap-2">
@if ($isLocked)
<svg class="size-3.5 shrink-0 text-neutral-400 dark:text-fg-faint" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path d="M5 13a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6z" />
<path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0-2 0m-3-5V7a4 4 0 1 1 8 0v4" />
</g>
</svg>
@can('delete', $this->env)
<x-modal-confirmation title="Confirm Environment Variable Deletion?" isErrorButton buttonTitle="Delete"
submitAction="delete" :actions="['The selected environment variable will be permanently deleted.']"
confirmationText="{{ $env->key }}"
confirmationLabel="Please confirm the execution of the actions by entering the Environment Variable Name below"
shortConfirmationLabel="Environment Variable Name" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" />
@endcan
</div>
@can('update', $this->env)
<div class="flex flex-col w-full gap-2 lg:flex-row lg:items-end">
<div class="flex-1">
<x-forms.input id="comment" label="Comment"
placeholder="{{ $isMagicVariable ? 'This env cannot be edited manually, it is handled by Coolify.' : '' }}"
helper="Add a note to document what this environment variable is used for." maxlength="256" />
</div>
<x-forms.button type="submit">Update</x-forms.button>
</div>
<div class="flex flex-col w-full gap-3">
<div class="flex flex-wrap w-full items-center gap-4">
@if (!$is_redis_credential)
@if ($type === 'service')
@if (!$isMagicVariable)
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@else
@if ($is_shared)
<x-forms.checkbox instantSave id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-forms.checkbox instantSave id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@else
@if ($isSharedVariable)
@if (!$isMagicVariable)
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@endif
@else
@if (!$env->is_buildpack_control)
<x-forms.checkbox instantSave id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
@endif
<x-forms.checkbox instantSave id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
@if (!$isMagicVariable)
@if (!$env->is_buildpack_control)
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@if ($is_multiline === false)
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@endif
@endif
@endif
@endif
@endif
@endif
</div>
</div>
@endif
<span class="env-key-label min-w-0 truncate font-mono text-[13px] text-black dark:text-fg"
title="{{ $env->key }}">{{ $env->key }}</span>
@if ($is_really_required)
<span class="table-badge table-badge-danger shrink-0">Required</span>
@endif
@if ($isMagicVariable)
<span class="table-badge shrink-0">Managed</span>
@endif
<span class="env-type-mobile table-badge shrink-0">{{ $rowScopeLabel }}</span>
</div>
<div class="env-type-desktop text-[13px] text-neutral-500 dark:text-fg-dim">
{{ $rowScopeLabel }}
</div>
<div class="min-w-0 truncate text-[13px] text-neutral-500 dark:text-fg-dim"
@if ($comment) title="{{ $comment }}" @endif>
{{ $comment ?: '-' }}
</div>
@if ($isSharedVariable)
@if ($is_multiline)
<span class="data-table-cell-check">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2"
stroke="currentColor" class="size-4">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
</span>
@else
<div class="flex flex-col w-full gap-3">
<div class="flex flex-wrap w-full items-center gap-4">
@if (!$is_redis_credential)
@if ($type === 'service')
@if (!$isMagicVariable)
<x-forms.checkbox disabled id="is_multiline" label="Is Multiline?" />
<x-forms.checkbox disabled id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@else
@if ($is_shared)
<x-forms.checkbox disabled id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-forms.checkbox disabled id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
<x-forms.checkbox disabled id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@else
@if ($isSharedVariable)
@if (!$isMagicVariable)
<x-forms.checkbox disabled id="is_multiline" label="Is Multiline?" />
@endif
@else
<x-forms.checkbox disabled id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-forms.checkbox disabled id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
@if (!$isMagicVariable)
<x-forms.checkbox disabled id="is_multiline" label="Is Multiline?" />
@if ($is_multiline === false)
<x-forms.checkbox disabled id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@endif
@endif
@endif
@endif
@endif
</div>
</div>
<div class="w-full">
<x-forms.input disabled id="comment" label="Comment" helper="Documentation for this environment variable."
maxlength="256" />
</div>
@endcan
<span class="data-table-cell-dash">-</span>
@endif
@else
@can('update', $this->env)
@if ($isDisabled)
<div class="flex flex-col w-full gap-2">
<div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input disabled id="key" />
<x-forms.env-var-input
disabled
type="password"
id="value"
:availableVars="$isSharedVariable ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')"
:serverUuid="data_get($parameters, 'server_uuid')" />
@if ($is_shared)
<x-forms.input disabled type="password" id="real_value" />
@endif
</div>
<x-forms.input instantSave id="comment" label="Comment"
placeholder="{{ $isMagicVariable ? 'This env cannot be edited manually, it is handled by Coolify.' : '' }}"
helper="Add a note to document what this environment variable is used for." maxlength="256" />
</div>
@foreach ([$is_literal, $is_multiline, $is_buildtime && !$is_redis_credential, $is_runtime && !$is_redis_credential] as $flag)
@if ($flag)
<span class="data-table-cell-check">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2"
stroke="currentColor" class="size-4">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
</span>
@else
<div class="flex flex-col w-full gap-2">
<div class="flex flex-col w-full gap-2 lg:flex-row">
@if ($is_multiline)
<x-forms.input :required="$is_redis_credential" isMultiline="{{ $is_multiline }}" id="key" />
<div class="flex-1" wire:key="env-show-value-textarea-{{ $env->id }}">
<x-forms.textarea :required="$is_redis_credential" type="password" id="value" />
</div>
@else
<x-forms.input :disabled="$is_redis_credential" :required="$is_redis_credential" id="key" />
<div class="w-full" wire:key="env-show-value-input-{{ $env->id }}">
<x-forms.env-var-input
:required="$is_redis_credential"
type="password"
id="value"
:availableVars="$isSharedVariable ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')"
:serverUuid="data_get($parameters, 'server_uuid')" />
</div>
@endif
@if ($is_shared)
<x-forms.input :disabled="$is_redis_credential" :required="$is_redis_credential" disabled
type="password" id="real_value" />
@endif
</div>
<x-forms.input instantSave id="comment" label="Comment"
placeholder="{{ $isMagicVariable ? 'This env cannot be edited manually, it is handled by Coolify.' : '' }}"
helper="Add a note to document what this environment variable is used for." maxlength="256" />
</div>
<span class="data-table-cell-dash">-</span>
@endif
@else
<div class="flex flex-col w-full gap-2">
<div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input disabled id="key" />
@endforeach
@endif
<div class="justify-self-end">
{{-- Open modal immediately (Alpine); decrypt value in a follow-up Livewire request. --}}
<x-modal-input title="Edit environment variable" :closeOutside="false" :wireIgnore="false"
wireOpen="editorOpen">
<x-slot:content>
<button type="button" wire:click="loadValues" class="icon-button shrink-0"
title="Edit environment variable" aria-label="Edit environment variable">
<x-reicon name="settings" class="size-3.5" />
</button>
</x-slot:content>
<form wire:submit="submit" class="flex w-full flex-col gap-4"
x-data="{ isMultiline: $wire.entangle('is_multiline') }">
<div class="grid items-end gap-4 sm:grid-cols-2">
<x-forms.input id="key" label="Name" :required="$is_redis_credential"
:disabled="!$canEditValue || $is_redis_credential" />
<x-forms.input id="comment" label="Comment" placeholder="Optional note"
helper="Add a note to document what this environment variable is used for." maxlength="256"
:disabled="!$canUpdate" />
</div>
<div>
@if ($isValueHidden)
<div class="w-full">
<label class="mb-1 flex items-center gap-1 text-sm font-medium">Value</label>
<input disabled type="text" value="Hidden (only admins can view)"
class="input italic !text-neutral-500 dark:!text-neutral-500" />
class="input w-full italic !text-neutral-500 dark:!text-neutral-500" />
</div>
@elseif ($isLocked)
<div class="w-full">
<label class="mb-1 flex items-center gap-1 text-sm font-medium">Value</label>
<input disabled type="text" value="Hidden after locking"
class="input w-full italic !text-neutral-500 dark:!text-neutral-500" />
</div>
@else
<x-forms.env-var-input
disabled
type="password"
id="value"
:availableVars="$isSharedVariable ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')"
:serverUuid="data_get($parameters, 'server_uuid')" />
@if ($is_shared)
<x-forms.input disabled type="password" id="real_value" />
@endif
@endif
</div>
<x-forms.input disabled id="comment" label="Comment"
placeholder="{{ $isMagicVariable ? 'This env cannot be edited manually, it is handled by Coolify.' : '' }}"
helper="Add a note to document what this environment variable is used for." maxlength="256" />
</div>
@endcan
@can('update', $this->env)
<div class="flex w-full flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div class="flex min-w-0 flex-1 flex-col gap-3">
<div class="flex flex-wrap w-full items-center gap-4">
@if (!$is_redis_credential)
@if ($type === 'service')
@if (!$isMagicVariable)
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@else
@if ($is_shared)
<x-forms.checkbox instantSave id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-forms.checkbox instantSave id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@else
@if ($isSharedVariable)
@if (!$isMagicVariable)
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@endif
@else
@if (!$env->is_buildpack_control)
<x-forms.checkbox instantSave id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
@endif
<x-forms.checkbox instantSave id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
@if (!$isMagicVariable)
@if (!$env->is_buildpack_control)
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@if ($is_multiline === false)
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@endif
@endif
{{-- Multiline: same shell while loading/loaded to avoid layout jump. --}}
<div x-show="isMultiline" x-cloak wire:key="env-show-value-multiline-{{ $env->id }}"
class="w-full">
<label class="mb-1 flex items-center gap-1 text-sm font-medium">
Value
@if ($is_redis_credential)
<x-highlighted text="*" />
@endif
</label>
@if (!$valuesLoaded)
<div class="input flex min-h-24 w-full items-start py-2 text-neutral-500 dark:text-fg-dim"
aria-busy="true">
<x-loading text="Loading value..." />
</div>
@else
<x-forms.textarea id="value" class="font-sans" :required="$is_redis_credential"
:disabled="!$canEditValue" spellcheck />
@endif
@endif
</div>
{{-- Single-line: keep one label + control shell so label/input gap never changes. --}}
<div x-show="!isMultiline" class="w-full"
wire:key="env-show-value-single-{{ $env->id }}">
<label class="mb-1 flex items-center gap-1 text-sm font-medium">
Value
@if ($is_redis_credential)
<x-highlighted text="*" />
@endif
</label>
<div class="relative">
@if (!$valuesLoaded)
<div class="input input-with-password-toggle flex w-full items-center text-neutral-500 dark:text-fg-dim"
aria-busy="true">
<x-loading text="Loading value..." />
</div>
@else
<x-forms.env-var-input id="value" type="password"
:required="$is_redis_credential" :disabled="!$canEditValue"
:availableVars="$isSharedVariable ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')"
:serverUuid="data_get($parameters, 'server_uuid')" />
@endif
</div>
</div>
@endif
{{-- Keep tip mounted during value load so layout does not jump when decrypt finishes. --}}
@if (!$isSharedVariable && !$isValueHidden && !$isLocked)
<div x-cloak x-show="!isMultiline" wire:key="env-show-value-tip-{{ $env->id }}"
class="mt-1.5 text-xs text-neutral-500 dark:text-fg-faint">
Tip: Type <span
class="font-mono text-coollabs dark:text-warning">{{ '{{' }}</span> to reference
a shared environment variable
</div>
@endif
</div>
<x-environment-variable-warning :problematic-variables="$problematicVariables" />
</div>
@if (!$isMagicVariable)
<div class="flex w-full justify-end gap-2 lg:w-auto lg:shrink-0">
@if ($isDisabled)
<x-forms.button disabled type="submit">Update</x-forms.button>
<x-forms.button wire:click='lock'>Lock</x-forms.button>
<x-modal-confirmation title="Confirm Environment Variable Deletion?" isErrorButton buttonTitle="Delete"
submitAction="delete" :actions="['The selected environment variable will be permanently deleted.']"
confirmationText="{{ $key }}"
confirmationLabel="Please confirm the execution of the actions by entering the Environment Variable Name below"
shortConfirmationLabel="Environment Variable Name" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" />
@else
<x-forms.button type="submit">Update</x-forms.button>
<x-forms.button wire:click='lock'>Lock</x-forms.button>
<x-modal-confirmation title="Confirm Environment Variable Deletion?" isErrorButton buttonTitle="Delete"
submitAction="delete" :actions="['The selected environment variable will be permanently deleted.']"
confirmationText="{{ $key }}"
confirmationLabel="Please confirm the execution of the actions by entering the Environment Variable Name below"
shortConfirmationLabel="Environment Variable Name" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" />
@if ($is_shared)
<x-forms.input disabled type="password" id="real_value" label="Resolved value" />
@endif
@if ($showValueType || $showInterpolation || $showBuildtime || $showRuntime)
<div
class="grid gap-4 border-t border-neutral-200 pt-4 dark:border-white/[0.07] sm:grid-cols-2">
@if ($showValueType)
<x-forms.listbox id="is_multiline" label="Value type" :live="true" :options="[
['value' => false, 'label' => 'Single line'],
['value' => true, 'label' => 'Multiline'],
]"
:disabled="! $canUpdate" />
@endif
@if ($showInterpolation)
<x-forms.listbox id="is_literal" label="Interpolation" :options="[
['value' => false, 'label' => 'Interpolate $VARIABLES'],
['value' => true, 'label' => 'Literal (keep $ characters as-is)'],
]"
helper="Literal means $VARIABLES in the value is kept as the actual characters '$VARIABLES' instead of being resolved from another variable. Useful when your value contains a $ sign."
:disabled="! $canUpdate" />
@endif
@if ($showBuildtime)
<x-forms.listbox id="is_buildtime" label="Build time" :options="[
['value' => true, 'label' => 'Available during build'],
['value' => false, 'label' => 'Not available during build'],
]"
helper="Make this variable available during the Docker build process. Useful for build secrets and dependencies."
:disabled="! $canUpdate" />
@endif
@if ($showRuntime)
<x-forms.listbox id="is_runtime" label="Runtime" :options="[
['value' => true, 'label' => 'Available in the container'],
['value' => false, 'label' => 'Not available in the container'],
]" helper="Make this variable available in the running container at runtime."
:disabled="! $canUpdate" />
@endif
</div>
@elseif ($type === 'service')
<div class="flex w-full justify-end gap-2 lg:w-auto lg:shrink-0">
<x-forms.button wire:click='lock'>Lock</x-forms.button>
</div>
@endif
</div>
@else
<div class="flex flex-col w-full gap-3">
<div class="flex flex-wrap w-full items-center gap-4">
@if (!$is_redis_credential)
@if ($type === 'service')
@if (!$isMagicVariable)
<x-forms.checkbox disabled id="is_multiline" label="Is Multiline?" />
<x-forms.checkbox disabled id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@else
@if ($is_shared)
<x-forms.checkbox disabled id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-forms.checkbox disabled id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
<x-forms.checkbox disabled id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@else
@if ($isSharedVariable)
@if (!$isMagicVariable)
<x-forms.checkbox disabled id="is_multiline" label="Is Multiline?" />
@endif
@else
<x-forms.checkbox disabled id="is_buildtime"
helper="Make this variable available during Docker build process. Useful for build secrets and dependencies."
label="Available at Buildtime" />
<x-forms.checkbox disabled id="is_runtime"
helper="Make this variable available in the running container at runtime."
label="Available at Runtime" />
@if (!$isMagicVariable)
<x-forms.checkbox disabled id="is_multiline" label="Is Multiline?" />
@if ($is_multiline === false)
<x-forms.checkbox disabled id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@endif
@endif
@endif
@endif
@endif
</div>
</div>
@endcan
@endif
</form>
@if (!$isSharedVariable)
<x-environment-variable-warning :problematic-variables="$problematicVariables" />
@endif
@if ($canUpdate || auth()->user()?->can('delete', $this->env))
<div
class="flex flex-wrap justify-end gap-2 border-t border-neutral-200 pt-4 dark:border-white/[0.07]">
@if ($canUpdate && !$isLocked && !$isMagicVariable)
<x-forms.button type="button" wire:click="lock">Lock</x-forms.button>
@endif
@can('delete', $this->env)
@if (!$isMagicVariable)
<x-modal-confirmation title="Confirm Environment Variable Deletion?" isErrorButton
buttonTitle="Delete" submitAction="delete"
:actions="['The selected environment variable will be permanently deleted.']"
confirmationText="{{ $key }}"
confirmationLabel="Please confirm the execution of the actions by entering the Environment Variable Name below"
shortConfirmationLabel="Environment Variable Name" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" />
@endif
@endcan
@if ($canUpdate)
<x-forms.button type="submit" :disabled="$isDisabled" @click="modalOpen = false">
Update variable
</x-forms.button>
@endif
</div>
@endif
</form>
</x-modal-input>
</div>
</div>
</div>