mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-21 08:25:45 +00:00
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:
co-authored by
ShadowArcanist
parent
0b843bb07c
commit
8ae56587d5
@@ -35,6 +35,10 @@ class Show extends Component
|
||||
|
||||
public string $type;
|
||||
|
||||
public int $tableAlphabeticalOrder = 0;
|
||||
|
||||
public int $tableCreationOrder = 0;
|
||||
|
||||
public string $key;
|
||||
|
||||
public ?string $value = null;
|
||||
@@ -63,6 +67,18 @@ class Show extends Component
|
||||
|
||||
public bool $isValueHidden = false;
|
||||
|
||||
/**
|
||||
* Decrypted value / real_value are only needed in the edit modal (or after save).
|
||||
* Keeping them unloaded for table rows avoids decrypting every visible env on each page change.
|
||||
*/
|
||||
public bool $valuesLoaded = false;
|
||||
|
||||
/**
|
||||
* Entangled with the edit modal open state so the modal stays open across the
|
||||
* async loadValues() re-render (open immediately, decrypt after).
|
||||
*/
|
||||
public bool $editorOpen = false;
|
||||
|
||||
public array $problematicVariables = [];
|
||||
|
||||
protected $listeners = [
|
||||
@@ -116,10 +132,33 @@ class Show extends Component
|
||||
if (! $this->env->exists || ! $this->env->fresh()) {
|
||||
return;
|
||||
}
|
||||
$this->valuesLoaded = false;
|
||||
$this->syncData();
|
||||
$this->checkEnvs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt and resolve values only when the edit modal is opened.
|
||||
*/
|
||||
public function loadValues(): void
|
||||
{
|
||||
if ($this->valuesLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
// List queries omit the encrypted value column; refresh so edit has a full model.
|
||||
if ($this->env->exists) {
|
||||
$fresh = $this->env->fresh();
|
||||
if ($fresh) {
|
||||
$fresh->setAppends([]);
|
||||
$this->env = $fresh;
|
||||
}
|
||||
}
|
||||
|
||||
$this->hydrateValueFields();
|
||||
$this->valuesLoaded = true;
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false)
|
||||
{
|
||||
if ($toModel) {
|
||||
@@ -149,29 +188,55 @@ class Show extends Component
|
||||
$this->env->is_literal = $this->is_literal;
|
||||
$this->env->is_shown_once = $this->is_shown_once;
|
||||
$this->env->save();
|
||||
$this->valuesLoaded = true;
|
||||
} else {
|
||||
// Table metadata only — never decrypt here. Values load via loadValues().
|
||||
$this->env->setAppends([]);
|
||||
$this->key = $this->env->key;
|
||||
$this->value = $this->env->value;
|
||||
$this->comment = $this->env->comment;
|
||||
$this->is_multiline = $this->env->is_multiline;
|
||||
$this->is_literal = $this->env->is_literal;
|
||||
$this->is_shown_once = $this->env->is_shown_once;
|
||||
$this->is_runtime = $this->env->is_runtime ?? true;
|
||||
$this->is_buildtime = $this->env->is_buildtime ?? true;
|
||||
$this->is_required = $this->env->is_required ?? false;
|
||||
$this->is_really_required = $this->env->is_really_required ?? false;
|
||||
$this->is_shared = $this->env->is_shared ?? false;
|
||||
$this->real_value = $this->env->real_value;
|
||||
$this->is_multiline = (bool) $this->env->is_multiline;
|
||||
$this->is_literal = (bool) $this->env->is_literal;
|
||||
$this->is_shown_once = (bool) $this->env->is_shown_once;
|
||||
$this->is_runtime = (bool) ($this->env->is_runtime ?? true);
|
||||
$this->is_buildtime = (bool) ($this->env->is_buildtime ?? true);
|
||||
$this->is_required = (bool) ($this->env->is_required ?? false);
|
||||
// Use the stored column, not the value-based accessor (that decrypts).
|
||||
$this->is_shared = (bool) ($this->env->getAttributes()['is_shared'] ?? false);
|
||||
$this->isValueHidden = auth()->user()?->isMember() ?? false;
|
||||
|
||||
if ($this->env->is_shown_once || auth()->user()?->isMember()) {
|
||||
if ($this->valuesLoaded) {
|
||||
$this->hydrateValueFields();
|
||||
} else {
|
||||
$this->value = null;
|
||||
$this->real_value = null;
|
||||
// Required badge: without decrypting, show when flagged required.
|
||||
// Exact empty-value state is refined when the edit modal opens.
|
||||
$this->is_really_required = $this->is_required;
|
||||
}
|
||||
|
||||
$this->isValueHidden = auth()->user()?->isMember() ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
private function hydrateValueFields(): void
|
||||
{
|
||||
$this->value = $this->env->value;
|
||||
$this->is_shared = (bool) ($this->env->is_shared ?? false);
|
||||
|
||||
if ($this->is_shared) {
|
||||
$this->real_value = $this->env->real_value;
|
||||
$this->is_really_required = $this->is_required && blank($this->real_value);
|
||||
} else {
|
||||
$this->real_value = null;
|
||||
$this->is_really_required = $this->is_required && blank($this->value);
|
||||
}
|
||||
|
||||
if ($this->env->is_shown_once || auth()->user()?->isMember()) {
|
||||
$this->value = null;
|
||||
$this->real_value = null;
|
||||
}
|
||||
|
||||
$this->isValueHidden = auth()->user()?->isMember() ?? false;
|
||||
}
|
||||
|
||||
public function checkEnvs()
|
||||
{
|
||||
$this->isDisabled = false;
|
||||
@@ -215,6 +280,7 @@ class Show extends Component
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->env);
|
||||
$this->loadValues();
|
||||
|
||||
if (! $this->isSharedVariable && $this->is_required && str($this->value)->isEmpty()) {
|
||||
$oldValue = $this->env->getOriginal('value');
|
||||
@@ -238,7 +304,23 @@ class Show extends Component
|
||||
#[Computed]
|
||||
public function availableSharedVariables(): array
|
||||
{
|
||||
// Shared across all Show row components in the same request (edit modals).
|
||||
static $requestCache = [];
|
||||
|
||||
$team = currentTeam();
|
||||
$cacheKey = implode('|', [
|
||||
$team?->id ?? 'none',
|
||||
data_get($this->parameters, 'project_uuid', ''),
|
||||
data_get($this->parameters, 'environment_uuid', ''),
|
||||
data_get($this->parameters, 'server_uuid', ''),
|
||||
data_get($this->parameters, 'application_uuid', ''),
|
||||
data_get($this->parameters, 'service_uuid', ''),
|
||||
]);
|
||||
|
||||
if (array_key_exists($cacheKey, $requestCache)) {
|
||||
return $requestCache[$cacheKey];
|
||||
}
|
||||
|
||||
$result = [
|
||||
'team' => [],
|
||||
'project' => [],
|
||||
@@ -248,7 +330,7 @@ class Show extends Component
|
||||
|
||||
// Early return if no team
|
||||
if (! $team) {
|
||||
return $result;
|
||||
return $requestCache[$cacheKey] = $result;
|
||||
}
|
||||
|
||||
// Check if user can view team variables
|
||||
@@ -359,7 +441,7 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $requestCache[$cacheKey] = $result;
|
||||
}
|
||||
|
||||
public function delete()
|
||||
|
||||
Reference in New Issue
Block a user