diff --git a/app/Console/Commands/Init.php b/app/Console/Commands/Init.php index f087002da1..e21a2f1c81 100644 --- a/app/Console/Commands/Init.php +++ b/app/Console/Commands/Init.php @@ -257,10 +257,8 @@ class Init extends Command $database = StandalonePostgresql::withTrashed()->find(0); if ($database && $database->trashed()) { $database->restore(); - $scheduledBackup = ScheduledDatabaseBackup::find(0); - if (! $scheduledBackup) { + if (! $database->scheduledBackups()->exists()) { ScheduledDatabaseBackup::create([ - 'id' => 0, 'enabled' => true, 'save_s3' => false, 'frequency' => '0 0 * * *', diff --git a/app/Livewire/SettingsBackup.php b/app/Livewire/SettingsBackup.php index a498f9169b..43563e7c83 100644 --- a/app/Livewire/SettingsBackup.php +++ b/app/Livewire/SettingsBackup.php @@ -71,7 +71,7 @@ class SettingsBackup extends Component $this->backup->enabled = false; $this->backup->save(); } - $this->executions = $this->backup->executions; + $this->executions = $this->backup?->executions ?? []; } $this->settings = $settings; $this->s3s = $s3s; @@ -81,44 +81,46 @@ class SettingsBackup extends Component { try { $this->authorize('update', $this->settings); - $server = Server::findOrFail(0); - $out = instant_remote_process(['docker inspect coolify-db'], $server); - $envs = format_docker_envs_to_json($out); - $postgres_password = $envs['POSTGRES_PASSWORD']; - $postgres_user = $envs['POSTGRES_USER']; - $postgres_db = $envs['POSTGRES_DB']; - $this->database = new StandalonePostgresql; - $this->database->forceFill([ - 'id' => 0, - 'name' => 'coolify-db', - 'description' => 'Coolify database', - 'postgres_user' => $postgres_user, - 'postgres_password' => $postgres_password, - 'postgres_db' => $postgres_db, - 'status' => 'running', - 'destination_type' => StandaloneDocker::class, - 'destination_id' => 0, - ]); - $this->database->save(); - $this->backup = ScheduledDatabaseBackup::create([ - 'id' => 0, - 'enabled' => true, - 'save_s3' => false, - 'frequency' => '0 0 * * *', - 'database_id' => $this->database->id, - 'database_type' => StandalonePostgresql::class, - 'team_id' => currentTeam()->id, - ]); + $this->database = StandalonePostgresql::whereName('coolify-db')->first(); + if (! $this->database) { + $server = Server::findOrFail(0); + $out = instant_remote_process(['docker inspect coolify-db'], $server); + $envs = format_docker_envs_to_json($out); + $this->database = new StandalonePostgresql; + $this->database->forceFill([ + 'id' => 0, + 'name' => 'coolify-db', + 'description' => 'Coolify database', + 'postgres_user' => $envs['POSTGRES_USER'], + 'postgres_password' => $envs['POSTGRES_PASSWORD'], + 'postgres_db' => $envs['POSTGRES_DB'], + 'status' => 'running', + 'destination_type' => StandaloneDocker::class, + 'destination_id' => 0, + ]); + $this->database->save(); + } + $this->backup = $this->database->scheduledBackups()->first() + ?? ScheduledDatabaseBackup::create([ + 'enabled' => true, + 'save_s3' => false, + 'frequency' => '0 0 * * *', + 'database_id' => $this->database->id, + 'database_type' => StandalonePostgresql::class, + 'team_id' => 0, + ]); $this->database->refresh(); $this->backup->refresh(); - auditLog('ui.database.backup_schedule_created', [ - 'team_id' => $this->backup->team_id, - 'database_uuid' => $this->database->uuid, - 'database_name' => $this->database->name, - 'backup_uuid' => $this->backup->uuid, - 'frequency' => $this->backup->frequency, - 'save_s3' => (bool) $this->backup->save_s3, - ]); + if ($this->backup->wasRecentlyCreated) { + auditLog('ui.database.backup_schedule_created', [ + 'team_id' => $this->backup->team_id, + 'database_uuid' => $this->database->uuid, + 'database_name' => $this->database->name, + 'backup_uuid' => $this->backup->uuid, + 'frequency' => $this->backup->frequency, + 'save_s3' => (bool) $this->backup->save_s3, + ]); + } $this->s3s = S3Storage::whereTeamId(0)->get(); $this->uuid = $this->database->uuid; diff --git a/resources/js/copy-button.js b/resources/js/copy-button.js index 0ce8d5d67d..b62eaa120e 100644 --- a/resources/js/copy-button.js +++ b/resources/js/copy-button.js @@ -12,15 +12,22 @@ export function initializeCopyButtonComponent() { await navigator.clipboard.writeText(value); } else { // Deprecated, but the only copy path on plain http (non-secure contexts). + // The textarea goes next to the button, not into
: a modal's x-trap + // pulls focus back from nodes outside it, which clears the selection. + const previousFocus = document.activeElement; const textarea = document.createElement('textarea'); textarea.value = value; textarea.setAttribute('readonly', ''); + textarea.setAttribute('tabindex', '-1'); textarea.style.position = 'fixed'; textarea.style.left = '-9999px'; - document.body.appendChild(textarea); + this.$el.after(textarea); + textarea.focus({ preventScroll: true }); textarea.select(); + textarea.setSelectionRange(0, textarea.value.length); const ok = document.execCommand('copy'); - document.body.removeChild(textarea); + textarea.remove(); + previousFocus?.focus?.({ preventScroll: true }); if (!ok) { throw new Error('Copy command was rejected.'); } diff --git a/resources/views/livewire/project/shared/cloudflare-autoconfigure.blade.php b/resources/views/livewire/project/shared/cloudflare-autoconfigure.blade.php index 8d102ff47f..9b565c4e98 100644 --- a/resources/views/livewire/project/shared/cloudflare-autoconfigure.blade.php +++ b/resources/views/livewire/project/shared/cloudflare-autoconfigure.blade.php @@ -223,39 +223,15 @@ @if (filled($dnsCopyText)) -{{ count($dnsHints) }} {{ count($dnsHints) === 1 ? 'entry' : 'entries' }} ยท BIND zone format