feat: configuration checker for all resources

This commit is contained in:
Andras Bacsai 2024-04-12 12:44:49 +02:00
parent 7b0018b661
commit 7a32b8d1d2
41 changed files with 493 additions and 89 deletions

View File

@ -34,7 +34,6 @@ public function handle(StandaloneDragonfly $database)
$persistent_storages = $this->generate_local_persistent_volumes();
$volume_names = $this->generate_local_persistent_volumes_only_volume_names();
$environment_variables = $this->generate_environment_variables();
$this->add_custom_dragonfly();
$docker_compose = [
'version' => '3.8',
@ -99,15 +98,6 @@ public function handle(StandaloneDragonfly $database)
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
if (!is_null($this->database->dragonfly_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $this->configuration_dir . '/dragonfly.conf',
'target' => '/etc/dragonfly/dragonfly.conf',
'read_only' => true,
];
$docker_compose['services'][$container_name]['command'] = "dragonfly /etc/dragonfly/dragonfly.conf --requirepass {$this->database->dragonfly_password}";
}
$docker_compose = Yaml::dump($docker_compose, 10);
$docker_compose_base64 = base64_encode($docker_compose);
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d > $this->configuration_dir/docker-compose.yml";
@ -163,15 +153,4 @@ private function generate_environment_variables()
return $environment_variables->all();
}
private function add_custom_dragonfly()
{
if (is_null($this->database->dragonfly_conf)) {
return;
}
$filename = 'dragonfly.conf';
Storage::disk('local')->put("tmp/dragonfly.conf_{$this->database->uuid}", $this->database->dragonfly_conf);
$path = Storage::path("tmp/dragonfly.conf_{$this->database->uuid}");
instant_scp($path, "{$this->configuration_dir}/{$filename}", $this->database->destination->server);
Storage::disk('local')->delete("tmp/dragonfly.conf_{$this->database->uuid}");
}
}

View File

@ -24,7 +24,6 @@ class General extends Component
public $customLabels;
public bool $labelsChanged = false;
public bool $isConfigurationChanged = false;
public bool $initLoadingCompose = false;
public ?string $initialDockerComposeLocation = null;
@ -124,13 +123,8 @@ public function mount()
$this->application->settings->save();
}
$this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : [];
$this->ports_exposes = $this->application->ports_exposes;
if (str($this->application->status)->startsWith('running') && is_null($this->application->config_hash)) {
$this->application->isConfigurationChanged(true);
}
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
$this->customLabels = $this->application->parseContainerLabels();
$this->customLabels = $this->application->parseContainerLabels();
if (!$this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') {
$this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n");
$this->application->custom_labels = base64_encode($this->customLabels);
@ -141,6 +135,10 @@ public function mount()
$this->initLoadingCompose = true;
$this->dispatch('info', 'Loading docker compose file...');
}
if (str($this->application->status)->startsWith('running') && is_null($this->application->config_hash)) {
$this->dispatch('configurationChanged');
}
}
public function instantSave()
{
@ -316,7 +314,7 @@ public function submit($showToaster = true)
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
$this->dispatch('configurationChanged');
}
}
}

View File

@ -86,26 +86,6 @@ public function instantSave()
return handleError($e, $this);
}
}
// public function save_init_script($script)
// {
// $this->database->init_scripts = filter($this->database->init_scripts, fn ($s) => $s['filename'] !== $script['filename']);
// $this->database->init_scripts = array_merge($this->database->init_scripts, [$script]);
// $this->database->save();
// $this->dispatch('success', 'Init script saved.');
// }
// public function delete_init_script($script)
// {
// $collection = collect($this->database->init_scripts);
// $found = $collection->firstWhere('filename', $script['filename']);
// if ($found) {
// $this->database->init_scripts = $collection->filter(fn ($s) => $s['filename'] !== $script['filename'])->toArray();
// $this->database->save();
// $this->refresh();
// $this->dispatch('success', 'Init script deleted.');
// return;
// }
// }
public function refresh(): void
{
@ -124,6 +104,12 @@ public function submit()
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
}

View File

@ -7,7 +7,8 @@
class Configuration extends Component
{
public $database;
public function mount() {
public function mount()
{
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
@ -21,6 +22,10 @@ public function mount() {
return redirect()->route('dashboard');
}
$this->database = $database;
if (str($this->database->status)->startsWith('running') && is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
$this->dispatch('configurationChanged');
}
}
public function render()
{

View File

@ -19,7 +19,6 @@ class General extends Component
protected $rules = [
'database.name' => 'required',
'database.description' => 'nullable',
'database.dragonfly_conf' => 'nullable',
'database.dragonfly_password' => 'required',
'database.image' => 'required',
'database.ports_mappings' => 'nullable',
@ -30,7 +29,6 @@ class General extends Component
protected $validationAttributes = [
'database.name' => 'Name',
'database.description' => 'Description',
'database.dragonfly_conf' => 'Redis Configuration',
'database.dragonfly_password' => 'Redis Password',
'database.image' => 'Image',
'database.ports_mappings' => 'Port Mapping',
@ -62,13 +60,16 @@ public function submit()
{
try {
$this->validate();
if ($this->database->dragonfly_conf === "") {
$this->database->dragonfly_conf = null;
}
$this->database->save();
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
public function instantSave()

View File

@ -34,6 +34,12 @@ public function activityFinished()
]);
$this->dispatch('refresh');
$this->check_status();
if (is_null($this->database->config_hash) || $this->database->isConfigurationChanged()) {
$this->database->isConfigurationChanged(true);
$this->dispatch('configurationChanged');
} else {
$this->dispatch('configurationChanged');
}
}
public function check_status($showNotification = false)

View File

@ -69,6 +69,12 @@ public function submit()
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
public function instantSave()

View File

@ -76,6 +76,12 @@ public function submit()
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
public function instantSave()

View File

@ -78,6 +78,12 @@ public function submit()
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
public function instantSave()

View File

@ -77,6 +77,12 @@ public function submit()
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
public function instantSave()

View File

@ -58,7 +58,8 @@ public function mount()
$this->db_url_public = $this->database->get_db_url();
}
}
public function instantSaveAdvanced() {
public function instantSaveAdvanced()
{
try {
if (!$this->database->destination->server->isLogDrainEnabled()) {
$this->database->is_log_drain_enabled = false;
@ -164,6 +165,12 @@ public function submit()
$this->dispatch('success', 'Database updated.');
} catch (Exception $e) {
return handleError($e, $this);
} finally {
if (is_null($this->database->config_hash)) {
$this->database->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
}

View File

@ -43,6 +43,7 @@ public function submit()
} finally {
$this->dispatch('generateDockerCompose');
$this->dispatch('refresh');
$this->dispatch('configurationChanged');
}
}
public function render()

View File

@ -17,6 +17,14 @@ class Navbar extends Component
public array $query;
public $isDeploymentProgress = false;
public function mount()
{
if (str($this->service->status())->contains('running') && is_null($this->service->config_hash)) {
ray('isConfigurationChanged init');
$this->service->isConfigurationChanged(true);
$this->dispatch('configurationChanged');
}
}
public function getListeners()
{
$userId = auth()->user()->id;
@ -25,12 +33,19 @@ public function getListeners()
"serviceStatusChanged"
];
}
public function serviceStarted() {
public function serviceStarted()
{
$this->dispatch('success', 'Service status changed.');
}
public function serviceStatusChanged()
{
$this->dispatch('refresh')->self();
// if (is_null($this->service->config_hash) || $this->service->isConfigurationChanged()) {
// $this->service->isConfigurationChanged(true);
// $this->dispatch('configurationChanged');
// } else {
// $this->dispatch('configurationChanged');
// }
}
public function check_status()
{

View File

@ -69,6 +69,13 @@ public function submit()
$this->dispatch('success', 'Service saved.');
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
if (is_null($this->service->config_hash)) {
ray('asdf');
$this->service->isConfigurationChanged(true);
} else {
$this->dispatch('configurationChanged');
}
}
}
public function render()

View File

@ -0,0 +1,34 @@
<?php
namespace App\Livewire\Project\Shared;
use App\Models\Application;
use App\Models\Service;
use App\Models\StandaloneClickhouse;
use App\Models\StandaloneDragonfly;
use App\Models\StandaloneKeydb;
use App\Models\StandaloneMariadb;
use App\Models\StandaloneMongodb;
use App\Models\StandaloneMysql;
use App\Models\StandalonePostgresql;
use App\Models\StandaloneRedis;
use Livewire\Component;
class ConfigurationChecker extends Component
{
public bool $isConfigurationChanged = false;
public Application|Service|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource;
protected $listeners = ['configurationChanged'];
public function mount()
{
$this->configurationChanged();
}
public function render()
{
return view('livewire.project.shared.configuration-checker');
}
public function configurationChanged()
{
$this->isConfigurationChanged = $this->resource->isConfigurationChanged();
}
}

View File

@ -11,7 +11,7 @@ class Danger extends Component
public $resource;
public $projectUuid;
public $environmentName;
public bool $delete_configurations = false;
public bool $delete_configurations = true;
public ?string $modalId = null;
public function mount()
@ -21,7 +21,6 @@ public function mount()
$this->projectUuid = data_get($parameters, 'project_uuid');
$this->environmentName = data_get($parameters, 'environment_name');
}
public function delete()
{
try {

View File

@ -509,7 +509,7 @@ public function isLogDrainEnabled()
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command . $this->build_command . $this->start_command . $this->port_exposes . $this->port_mappings . $this->base_directory . $this->publish_directory . $this->dockerfile . $this->dockerfile_location . $this->custom_labels;
$newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command . $this->build_command . $this->start_command . $this->ports_exposes . $this->ports_mappings . $this->base_directory . $this->publish_directory . $this->dockerfile . $this->dockerfile_location . $this->custom_labels . $this->custom_docker_run_options . $this->dockerfile_target_build;
if ($this->pull_request_id === 0 || $this->pull_request_id === null) {
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
} else {

View File

@ -11,6 +11,46 @@ class Service extends BaseModel
{
use HasFactory, SoftDeletes;
protected $guarded = [];
public function isConfigurationChanged(bool $save = false)
{
$domains = $this->applications()->get()->pluck('fqdn')->toArray();
$domains = implode(',', $domains);
$applicationImages = $this->applications()->get()->pluck('image');
$databaseImages = $this->databases()->get()->pluck('image');
$images = $applicationImages->merge($databaseImages);
$images = implode(',', $images->toArray());
$applicationStorages = $this->applications()->get()->pluck('persistentStorages')->flatten();
$databaseStorages = $this->databases()->get()->pluck('persistentStorages')->flatten();
$storages = $applicationStorages->merge($databaseStorages)->implode('updated_at');
$newConfigHash = $images . $domains . $images . $storages;
$newConfigHash .= json_encode($this->environment_variables()->get('value'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status())->contains('exited');
}
public function type()
{
return 'service';

View File

@ -42,6 +42,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -41,7 +41,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -41,7 +41,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings . $this->keydb_conf;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -43,6 +43,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings . $this->mariadb_conf;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -46,6 +46,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings . $this->mongo_conf;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -43,6 +43,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings . $this->mysql_conf;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -55,6 +55,33 @@ public function delete_configurations()
instant_remote_process(["rm -rf " . $this->workdir()], $server, false);
}
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings . $this->postgres_initdb_args . $this->postgres_host_auth_method;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function realStatus()
{
return $this->getRawOriginal('status');

View File

@ -38,6 +38,33 @@ protected static function booted()
$database->tags()->detach();
});
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image . $this->ports_mappings . $this->redis_conf;
$newConfigHash .= json_encode($this->environment_variables()->get('updated_at'));
$newConfigHash = md5($newConfigHash);
$oldConfigHash = data_get($this, 'config_hash');
if ($oldConfigHash === null) {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
if ($oldConfigHash === $newConfigHash) {
return false;
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
}
}
public function isExited()
{
return (bool) str($this->status)->startsWith('exited');
}
public function workdir()
{
return database_configuration_dir() . "/{$this->uuid}";

View File

@ -18,7 +18,6 @@ public function up(): void
$table->string('description')->nullable();
$table->text('dragonfly_password');
$table->longText('dragonfly_conf')->nullable();
$table->boolean('is_log_drain_enabled')->default(false);
$table->boolean('is_include_timestamps')->default(false);

View File

@ -0,0 +1,76 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('standalone_postgresqls', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_redis', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_mysqls', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_mariadbs', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_mongodbs', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_keydbs', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_dragonflies', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('standalone_clickhouses', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
Schema::table('services', function (Blueprint $table) {
$table->string('config_hash')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('standalone_postgresqls', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_redis', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_mysqls', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_mariadbs', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_mongodbs', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_keydbs', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_dragonflies', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('standalone_clickhouses', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
Schema::table('services', function (Blueprint $table) {
$table->dropColumn('config_hash');
});
}
};

View File

@ -1,8 +1,8 @@
@props(['title' => 'Default title', 'description' => 'Default Description', 'buttonText' => 'Default Button Text'])
<div x-data="{
bannerVisible: false,
bannerVisible: true,
bannerVisibleAfter: 100
}" x-show="bannerVisible" x-transition:enter="transition ease-out duration-500"
}" x-show="bannerVisible" x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="translate-y-full" x-transition:enter-end="translate-y-0"
x-transition:leave="transition ease-in duration-300" x-transition:leave-start="translate-y-0"
x-transition:leave-end="translate-y-full" x-init="setTimeout(() => { bannerVisible = true }, bannerVisibleAfter);"

View File

@ -1,5 +1,6 @@
<div>
<h1>Configuration</h1>
<livewire:project.shared.configuration-checker :resource="$application" />
<livewire:project.application.heading :application="$application" />
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex h-full pt-6">
<div class="flex flex-col gap-2 xl:w-48">
@ -27,7 +28,7 @@
<a class="menu-item" :class="activeTab === 'source' && 'menu-item-active'"
@click.prevent="activeTab = 'source'; window.location.hash = 'source'" href="#">Source</a>
@endif
<a class="menu-item" :class="activeTab === 'servers' && 'menu-item-active'" class="flex items-center gap-2"
<a class="menu-item" :class="activeTab === 'servers' && 'menu-item-active'" class="flex items-center gap-2"
@click.prevent="activeTab = 'servers'; window.location.hash = 'servers'" href="#">Servers
@if (str($application->status)->contains('degraded'))
<span title="Some servers are unavailable">

View File

@ -1,5 +1,6 @@
<div>
<h1>Deployments</h1>
<livewire:project.shared.configuration-checker :resource="$application" />
<livewire:project.application.heading :application="$application" />
{{-- <livewire:project.application.deployment.show :application="$application" :deployments="$deployments" :deployments_count="$deployments_count" /> --}}
<div class="flex flex-col gap-2 pb-10"

View File

@ -1,5 +1,6 @@
<div>
<h1 class="py-0">Deployment</h1>
<livewire:project.shared.configuration-checker :resource="$application" />
<livewire:project.application.heading :application="$application" />
<div class="pt-4" x-data="{
fullscreen: false,

View File

@ -4,26 +4,7 @@
<h2>General</h2>
<x-forms.button type="submit">
Save
</x-forms.button>
@if ($isConfigurationChanged && !is_null($application->config_hash) && !$application->isExited())
<x-popup-small>
<x-slot:title>
The latest configuration has not been applied.
</x-slot:title>
<x-slot:icon>
<svg class="hidden w-16 h-16 dark:text-warning lg:block" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M240.26 186.1L152.81 34.23a28.74 28.74 0 0 0-49.62 0L15.74 186.1a27.45 27.45 0 0 0 0 27.71A28.31 28.31 0 0 0 40.55 228h174.9a28.31 28.31 0 0 0 24.79-14.19a27.45 27.45 0 0 0 .02-27.71m-20.8 15.7a4.46 4.46 0 0 1-4 2.2H40.55a4.46 4.46 0 0 1-4-2.2a3.56 3.56 0 0 1 0-3.73L124 46.2a4.77 4.77 0 0 1 8 0l87.44 151.87a3.56 3.56 0 0 1 .02 3.73M116 136v-32a12 12 0 0 1 24 0v32a12 12 0 0 1-24 0m28 40a16 16 0 1 1-16-16a16 16 0 0 1 16 16" />
</svg>
</x-slot:icon>
<x-slot:description>
<span>Please restart (or redeploy) to apply the new configuration, especially if you have changed your domains.</span>
</x-slot:description>
<x-slot:button-text @click="disableSponsorship()">
Disable This Popup
</x-slot:button-text>
</x-popup-small>
@endif
</x-forms.button>
</div>
<div>General configuration for your application.</div>
<div class="flex flex-col gap-2 py-4">

View File

@ -1,5 +1,6 @@
<div>
<h1>Backups</h1>
<livewire:project.shared.configuration-checker :resource="$database" />
<livewire:project.database.heading :database="$database" />
<div class="pt-6">
<livewire:project.database.backup-edit :backup="$backup" :s3s="$s3s" :status="data_get($database, 'status')" />

View File

@ -1,5 +1,6 @@
<div>
<h1>Backups</h1>
<livewire:project.shared.configuration-checker :resource="$database" />
<livewire:project.database.heading :database="$database" />
<div class="pt-6">
<div class="flex gap-2 ">

View File

@ -1,5 +1,6 @@
<div>
<h1>Configuration</h1>
<livewire:project.shared.configuration-checker :resource="$database" />
<livewire:project.database.heading :database="$database" />
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex h-full pt-6">
<div class="flex flex-col gap-4 min-w-fit">

View File

@ -1,4 +1,5 @@
<div>
<livewire:project.shared.configuration-checker :resource="$service" />
<x-slide-over @startservice.window="slideOverOpen = true" closeWithX fullScreen>
<x-slot:title>Service Startup</x-slot:title>
<x-slot:content>

View File

@ -0,0 +1,22 @@
<div>
@if ($isConfigurationChanged && !is_null($resource->config_hash) && !$resource->isExited())
<x-popup-small>
<x-slot:title>
The latest configuration has not been applied
</x-slot:title>
<x-slot:icon>
<svg class="hidden w-16 h-16 dark:text-warning lg:block" viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M240.26 186.1L152.81 34.23a28.74 28.74 0 0 0-49.62 0L15.74 186.1a27.45 27.45 0 0 0 0 27.71A28.31 28.31 0 0 0 40.55 228h174.9a28.31 28.31 0 0 0 24.79-14.19a27.45 27.45 0 0 0 .02-27.71m-20.8 15.7a4.46 4.46 0 0 1-4 2.2H40.55a4.46 4.46 0 0 1-4-2.2a3.56 3.56 0 0 1 0-3.73L124 46.2a4.77 4.77 0 0 1 8 0l87.44 151.87a3.56 3.56 0 0 1 .02 3.73M116 136v-32a12 12 0 0 1 24 0v32a12 12 0 0 1-24 0m28 40a16 16 0 1 1-16-16a16 16 0 0 1 16 16" />
</svg>
</x-slot:icon>
<x-slot:description>
<span>Please restart (or redeploy) to apply the new configuration.</span>
</x-slot:description>
<x-slot:button-text @click="disableSponsorship()">
Disable This Popup
</x-slot:button-text>
</x-popup-small>
@endif
</div>

View File

@ -5,10 +5,11 @@
<div class="pb-4">This will stop your containers, delete all related data, etc. Beware! There is no coming
back!
</div>
<x-modal-confirmation isErrorButton buttonTitle="Delete">
<x-modal-confirmation isErrorButton buttonTitle="Delete" confirm={{ $confirm }}>
<div class="px-2">This resource will be deleted. It is not reversible. <strong class="text-error">Please think
again.</strong><br><br></div>
<x-forms.checkbox class="px-0" id="delete_configurations"
label="Also delete configuration files from the server (/data/coolify/...)?"></x-forms.checkbox>
<h4>Actions</h4>
<x-forms.checkbox id="delete_configurations"
label="Permanently delete configuration files of this resource from the server?"></x-forms.checkbox>
</x-modal-confirmation>
</div>

View File

@ -1,4 +1,5 @@
<div>
<livewire:project.shared.configuration-checker :resource="$resource" />
@if ($type === 'application')
<h1>Execute Command</h1>
<livewire:project.application.heading :application="$resource" />

View File

@ -1,4 +1,5 @@
<div>
<livewire:project.shared.configuration-checker :resource="$resource" />
@if ($type === 'application')
<h1>Logs</h1>
<livewire:project.application.heading :application="$resource" />