coolify/resources/views/livewire/project/shared/environment-variable/all.blade.php
Andras Bacsai 8ae56587d5
feat(ui): Shadow UI redesign, domain management, and DNS autoconfigure (#11119)
Co-authored-by: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com>
2026-08-03 23:11:54 +02:00

192 lines
13 KiB
PHP

<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>
@endcan
</div>
</div>
@endif
@if ($view === 'normal')
@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>
@else
@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
</div>
@endif
@endif
</div>