mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-21 00:24:36 +00:00
Collapse environment variable rows to the key and settings action on small screens, and let the key open the corresponding details modal.
251 lines
16 KiB
PHP
251 lines
16 KiB
PHP
@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' }} {{ ! $isSharedVariable && ! $showEnvironmentType ? 'env-table-grid-no-type' : '' }}">
|
|
<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>
|
|
@endif
|
|
<button type="button" data-env-name-trigger
|
|
class="env-key-label min-w-0 truncate text-left font-mono text-[13px] text-black dark:text-fg"
|
|
title="{{ $env->key }}"
|
|
@click="$el.closest('.data-table-row').querySelector('[data-env-settings-trigger]').click()">
|
|
{{ $env->key }}
|
|
</button>
|
|
@if (! $isSharedVariable && filled($comment))
|
|
<x-helper :helper="e($comment)" />
|
|
@endif
|
|
@if ($is_really_required)
|
|
<span class="table-badge table-badge-danger shrink-0">Required</span>
|
|
@endif
|
|
</div>
|
|
@if (! $isSharedVariable)
|
|
@if ($isMagicVariable)
|
|
<span class="env-managed-desktop 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
|
|
<span class="env-managed-desktop data-table-cell-dash">-</span>
|
|
@endif
|
|
@endif
|
|
@if ($showEnvironmentType)
|
|
<div class="env-type-desktop text-[13px] text-neutral-500 dark:text-fg-dim">{{ $rowScopeLabel }}</div>
|
|
@endif
|
|
@if ($isSharedVariable)
|
|
<div class="min-w-0 truncate text-[13px] text-neutral-500 dark:text-fg-dim"
|
|
@if ($comment) title="{{ $comment }}" @endif>
|
|
{{ $comment ?: '-' }}
|
|
</div>
|
|
@endif
|
|
@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
|
|
<span class="data-table-cell-dash">-</span>
|
|
@endif
|
|
@else
|
|
@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
|
|
<span class="data-table-cell-dash">-</span>
|
|
@endif
|
|
@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" data-env-settings-trigger 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 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
|
|
{{-- 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
|
|
</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>
|
|
|
|
@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>
|
|
@endif
|
|
|
|
@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>
|