diff --git a/README.md b/README.md index 0a3ce0132..dac48d127 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Special thanks to our biggest sponsors! ### Special Sponsors -![image](https://github.com/user-attachments/assets/152bd1e0-e0c1-4d47-8a4f-0eb3700d2e61) +![image](https://github.com/user-attachments/assets/726fb63e-c3b8-4260-b3ac-06780605ec5d) * [CCCareers](https://cccareers.org/) - A career development platform connecting coding bootcamp graduates with job opportunities in the tech industry. * [Hetzner](http://htznr.li/CoolifyXHetzner) - A German web hosting company offering affordable dedicated servers, cloud services, and web hosting solutions. @@ -50,6 +50,7 @@ Special thanks to our biggest sponsors! * [QuantCDN](https://www.quantcdn.io/?ref=coolify.io) - A content delivery network (CDN) optimizing website performance through global content distribution. * [Arcjet](https://arcjet.com/?ref=coolify.io) - A cloud-based platform providing real-time protection against API abuse and bot attacks. * [SupaGuide](https://supa.guide/?ref=coolify.io) - A comprehensive resource hub offering guides and tutorials for web development using Supabase. +* [GoldenVM](https://billing.goldenvm.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes. * [Tigris](https://tigrisdata.com/?ref=coolify.io) - A fully managed serverless object storage service compatible with Amazon S3 API. Offers high performance, scalability, and built-in search capabilities for efficient data management. * [Advin](https://coolify.ad.vin/?ref=coolify.io) - A digital advertising agency specializing in programmatic advertising and data-driven marketing strategies. * [Treive](https://trieve.ai/?ref=coolify.io) - An AI-powered search and discovery platform for enhancing information retrieval in large datasets. @@ -90,7 +91,6 @@ Special thanks to our biggest sponsors! Paweł Pierścionek Michael Mazurczak Formbricks -Adith Suhas StartupFame Jonas Jaeger JP @@ -147,10 +147,10 @@ By subscribing to the cloud version, you get the Coolify server for the same pri # Core Maintainers -| Andras Bacsai | Peak | +| Andras Bacsai | 🏔️ Peak | |------------|------------| -| Andras Bacsai | Peak Labs | -| | | +| Andras Bacsai | peaklabs-dev | +| | | # Repo Activity diff --git a/app/Console/Commands/Emails.php b/app/Console/Commands/Emails.php index cda4ca84f..f0e0e7fa0 100644 --- a/app/Console/Commands/Emails.php +++ b/app/Console/Commands/Emails.php @@ -187,7 +187,7 @@ class Emails extends Command 'team_id' => 0, ]); } - $this->mail = (new BackupSuccess($backup, $db))->toMail(); + // $this->mail = (new BackupSuccess($backup->frequency, $db->name))->toMail(); $this->sendEmail(); break; // case 'invitation-link': diff --git a/app/Console/Commands/ServicesGenerate.php b/app/Console/Commands/ServicesGenerate.php index 1559e5f6d..b45707c5c 100644 --- a/app/Console/Commands/ServicesGenerate.php +++ b/app/Console/Commands/ServicesGenerate.php @@ -20,7 +20,10 @@ class ServicesGenerate extends Command public function handle(): int { - $serviceTemplatesJson = collect(glob(base_path('templates/compose/*.yaml'))) + $serviceTemplatesJson = collect(array_merge( + glob(base_path('templates/compose/*.yaml')), + glob(base_path('templates/compose/*.yml')) + )) ->mapWithKeys(function ($file): array { $file = basename($file); $parsed = $this->processFile($file); @@ -68,7 +71,7 @@ class ServicesGenerate extends Command 'slogan' => $data->get('slogan', str($file)->headline()), 'compose' => $compose, 'tags' => $tags, - 'logo' => $data->get('logo', 'svgs/coolify.png'), + 'logo' => $data->get('logo', 'svgs/default.webp'), 'minversion' => $data->get('minversion', '0.0.0'), ]; diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 832dcf58b..19d22ae21 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -132,7 +132,7 @@ class Kernel extends ConsoleKernel } foreach ($servers as $server) { - $serverTimezone = $server->settings->server_timezone; + $serverTimezone = data_get($server->settings, 'server_timezone', $this->instanceTimezone); // Sentinel check $lastSentinelUpdate = $server->sentinel_updated_at; @@ -141,8 +141,12 @@ class Kernel extends ConsoleKernel if (validate_timezone($serverTimezone) === false) { $serverTimezone = config('app.timezone'); } - $this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyMinute()->onOneServer(); - // $this->scheduleInstance->job(new \App\Jobs\ServerCheckNewJob($server))->everyMinute()->onOneServer(); + if (isCloud()) { + $this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyFiveMinutes()->onOneServer(); + } else { + $this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyMinute()->onOneServer(); + } + // $this->scheduleInstance->job(new \App\Jobs\ServerCheckNewJob($server))->everyFiveMinutes()->onOneServer(); // Check storage usage every 10 minutes if Sentinel does not activated $this->scheduleInstance->job(new ServerStorageCheckJob($server))->everyTenMinutes()->onOneServer(); diff --git a/app/Jobs/ServerCheckJob.php b/app/Jobs/ServerCheckJob.php index 9818d5c6a..49d8dfe08 100644 --- a/app/Jobs/ServerCheckJob.php +++ b/app/Jobs/ServerCheckJob.php @@ -31,7 +31,12 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue return [(new WithoutOverlapping($this->server->uuid))->dontRelease()]; } - public function __construct(public Server $server) {} + public function __construct(public Server $server) + { + if (isDev()) { + $this->handle(); + } + } public function handle() { diff --git a/app/Livewire/Project/Application/Configuration.php b/app/Livewire/Project/Application/Configuration.php index d4ec8f581..5e7f83772 100644 --- a/app/Livewire/Project/Application/Configuration.php +++ b/app/Livewire/Project/Application/Configuration.php @@ -16,24 +16,33 @@ class Configuration extends Component public function mount() { - $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); - if (! $project) { - return redirect()->route('dashboard'); - } - $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); - if (! $environment) { - return redirect()->route('dashboard'); - } - $application = $environment->applications->where('uuid', request()->route('application_uuid'))->first(); - if (! $application) { - return redirect()->route('dashboard'); - } + $project = currentTeam() + ->projects() + ->select('id', 'uuid', 'team_id') + ->where('uuid', request()->route('project_uuid')) + ->firstOrFail(); + + $environment = $project->environments() + ->select('id', 'name', 'project_id') + ->where('name', request()->route('environment_name')) + ->firstOrFail(); + + $application = $environment->applications() + ->with(['destination']) + ->where('uuid', request()->route('application_uuid')) + ->firstOrFail(); + $this->application = $application; - $mainServer = $this->application->destination->server; - $servers = Server::ownedByCurrentTeam()->get(); - $this->servers = $servers->filter(function ($server) use ($mainServer) { - return $server->id != $mainServer->id; - }); + + if ($application->destination && $application->destination->server) { + $mainServer = $application->destination->server; + $this->servers = Server::ownedByCurrentTeam() + ->select('id', 'name') + ->where('id', '!=', $mainServer->id) + ->get(); + } else { + $this->servers = collect(); + } } public function render() diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index 3dedc11af..0b6d075a4 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -91,12 +91,16 @@ class Select extends Component { $services = get_service_templates(true); $services = collect($services)->map(function ($service, $key) { - $logo = data_get($service, 'logo', 'svgs/coolify.png'); + $default_logo = 'images/default.webp'; + $logo = data_get($service, 'logo', $default_logo); + $local_logo_path = public_path($logo); return [ 'name' => str($key)->headline(), 'logo' => asset($logo), - 'logo_github_url' => 'https://raw.githubusercontent.com/coollabsio/coolify/refs/heads/main/public/a'.$logo, + 'logo_github_url' => file_exists($local_logo_path) + ? 'https://raw.githubusercontent.com/coollabsio/coolify/refs/heads/main/public/'.$logo + : asset($default_logo), ] + (array) $service; })->all(); $gitBasedApplications = [ @@ -144,14 +148,14 @@ class Select extends Component 'id' => 'postgresql', 'name' => 'PostgreSQL', 'description' => 'PostgreSQL is an object-relational database known for its robustness, advanced features, and strong standards compliance.', - 'logo' => ' + 'logo' => ' ', ], [ 'id' => 'mysql', 'name' => 'MySQL', 'description' => 'MySQL is an open-source relational database management system. ', - 'logo' => ' + 'logo' => ' @@ -162,37 +166,37 @@ class Select extends Component 'id' => 'mariadb', 'name' => 'MariaDB', 'description' => 'MariaDB is a community-developed, commercially supported fork of the MySQL relational database management system, intended to remain free and open-source.', - 'logo' => '', + 'logo' => '', ], [ 'id' => 'redis', 'name' => 'Redis', 'description' => 'Redis is a source-available, in-memory storage, used as a distributed, in-memory key–value database, cache and message broker, with optional durability.', - 'logo' => '', + 'logo' => '', ], [ 'id' => 'keydb', 'name' => 'KeyDB', 'description' => 'KeyDB is a database that offers high performance, low latency, and scalability for various data structures and workloads.', - 'logo' => '
', + 'logo' => '
', ], [ 'id' => 'dragonfly', 'name' => 'Dragonfly', 'description' => 'Dragonfly DB is a drop-in Redis replacement that delivers 25x more throughput and 12x faster snapshotting than Redis.', - 'logo' => '
', + 'logo' => '
', ], [ 'id' => 'mongodb', 'name' => 'MongoDB', 'description' => 'MongoDB is a source-available, cross-platform, document-oriented database program.', - 'logo' => '', + 'logo' => '', ], [ 'id' => 'clickhouse', 'name' => 'ClickHouse', 'description' => 'ClickHouse is a column-oriented database that supports real-time analytics, business intelligence, observability, ML and GenAI, and more.', - 'logo' => '
', + 'logo' => '
', ], ]; diff --git a/app/Livewire/Server/Advanced.php b/app/Livewire/Server/Advanced.php index 0852abebf..0650de9a0 100644 --- a/app/Livewire/Server/Advanced.php +++ b/app/Livewire/Server/Advanced.php @@ -22,7 +22,7 @@ class Advanced extends Component #[Validate('boolean')] public bool $forceDockerCleanup = false; - #[Validate('string')] + #[Validate(['string', 'required'])] public string $dockerCleanupFrequency = '*/10 * * * *'; #[Validate(['integer', 'min:1', 'max:99'])] @@ -78,7 +78,6 @@ class Advanced extends Component try { $this->syncData(true); $this->dispatch('success', 'Server updated.'); - // $this->dispatch('refreshServerShow'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index 6599149c4..edddfc755 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -49,33 +49,73 @@ class LogDrains extends Component } } - public function syncData(bool $toModel = false) + public function syncDataNewRelic(bool $toModel = false) + { + if ($toModel) { + $this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled; + $this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey; + $this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri; + } else { + $this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled; + $this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key; + $this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri; + } + } + + public function syncDataAxiom(bool $toModel = false) + { + if ($toModel) { + $this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled; + $this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName; + $this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey; + } else { + $this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled; + $this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name; + $this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key; + } + } + + public function syncDataCustom(bool $toModel = false) + { + if ($toModel) { + $this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled; + $this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig; + $this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser; + } else { + $this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled; + $this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config; + $this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser; + } + } + + public function syncData(bool $toModel = false, ?string $type = null) { if ($toModel) { $this->customValidation(); - $this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled; - $this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled; - $this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled; - - $this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey; - $this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri; - $this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName; - $this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey; - $this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig; - $this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser; - + if ($type === 'newrelic') { + $this->syncDataNewRelic($toModel); + } elseif ($type === 'axiom') { + $this->syncDataAxiom($toModel); + } elseif ($type === 'custom') { + $this->syncDataCustom($toModel); + } else { + $this->syncDataNewRelic($toModel); + $this->syncDataAxiom($toModel); + $this->syncDataCustom($toModel); + } $this->server->settings->save(); } else { - $this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled; - $this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled; - $this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled; - - $this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key; - $this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri; - $this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name; - $this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key; - $this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config; - $this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser; + if ($type === 'newrelic') { + $this->syncDataNewRelic($toModel); + } elseif ($type === 'axiom') { + $this->syncDataAxiom($toModel); + } elseif ($type === 'custom') { + $this->syncDataCustom($toModel); + } else { + $this->syncDataNewRelic($toModel); + $this->syncDataAxiom($toModel); + $this->syncDataCustom($toModel); + } } } @@ -136,7 +176,7 @@ class LogDrains extends Component public function submit(string $type) { try { - $this->syncData(true); + $this->syncData(true, $type); $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php index 55ba49867..31dd13c52 100644 --- a/app/Livewire/Settings/Index.php +++ b/app/Livewire/Settings/Index.php @@ -53,7 +53,7 @@ class Index extends Component #[Validate('string')] public string $auto_update_frequency; - #[Validate('string')] + #[Validate('string|required')] public string $update_check_frequency; #[Validate('required|string|timezone')] @@ -109,6 +109,13 @@ class Index extends Component public function instantSave($isSave = true) { + $this->validate(); + if ($this->settings->is_auto_update_enabled === true) { + $this->validate([ + 'auto_update_frequency' => ['required', 'string'], + ]); + } + $this->settings->fqdn = $this->fqdn; $this->settings->resale_license = $this->resale_license; $this->settings->public_port_min = $this->public_port_min; diff --git a/app/Notifications/Application/DeploymentFailed.php b/app/Notifications/Application/DeploymentFailed.php index fae8951fd..ce1f99d77 100644 --- a/app/Notifications/Application/DeploymentFailed.php +++ b/app/Notifications/Application/DeploymentFailed.php @@ -4,18 +4,12 @@ namespace App\Notifications\Application; use App\Models\Application; use App\Models\ApplicationPreview; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class DeploymentFailed extends Notification implements ShouldQueue +class DeploymentFailed extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public Application $application; public ?ApplicationPreview $preview = null; diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php index bfdef9f25..391601257 100644 --- a/app/Notifications/Application/DeploymentSuccess.php +++ b/app/Notifications/Application/DeploymentSuccess.php @@ -4,18 +4,12 @@ namespace App\Notifications\Application; use App\Models\Application; use App\Models\ApplicationPreview; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class DeploymentSuccess extends Notification implements ShouldQueue +class DeploymentSuccess extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public Application $application; public ?ApplicationPreview $preview = null; diff --git a/app/Notifications/Application/StatusChanged.php b/app/Notifications/Application/StatusChanged.php index 3b062effb..c757495cb 100644 --- a/app/Notifications/Application/StatusChanged.php +++ b/app/Notifications/Application/StatusChanged.php @@ -3,18 +3,12 @@ namespace App\Notifications\Application; use App\Models\Application; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class StatusChanged extends Notification implements ShouldQueue +class StatusChanged extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public string $resource_name; public string $project_uuid; diff --git a/app/Notifications/Container/ContainerRestarted.php b/app/Notifications/Container/ContainerRestarted.php index 90dae63d4..eb709535f 100644 --- a/app/Notifications/Container/ContainerRestarted.php +++ b/app/Notifications/Container/ContainerRestarted.php @@ -3,18 +3,12 @@ namespace App\Notifications\Container; use App\Models\Server; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class ContainerRestarted extends Notification implements ShouldQueue +class ContainerRestarted extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public function __construct(public string $name, public Server $server, public ?string $url = null) { $this->onQueue('high'); diff --git a/app/Notifications/Container/ContainerStopped.php b/app/Notifications/Container/ContainerStopped.php index 3c8103568..a73e984a0 100644 --- a/app/Notifications/Container/ContainerStopped.php +++ b/app/Notifications/Container/ContainerStopped.php @@ -3,18 +3,12 @@ namespace App\Notifications\Container; use App\Models\Server; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class ContainerStopped extends Notification implements ShouldQueue +class ContainerStopped extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public function __construct(public string $name, public Server $server, public ?string $url = null) { $this->onQueue('high'); diff --git a/app/Notifications/CustomEmailNotification.php b/app/Notifications/CustomEmailNotification.php new file mode 100644 index 000000000..c3c89b30f --- /dev/null +++ b/app/Notifications/CustomEmailNotification.php @@ -0,0 +1,18 @@ +onQueue('high'); + $this->name = $database->name; $this->frequency = $backup->frequency; } diff --git a/app/Notifications/ScheduledTask/TaskFailed.php b/app/Notifications/ScheduledTask/TaskFailed.php index efdb8dccf..701f61277 100644 --- a/app/Notifications/ScheduledTask/TaskFailed.php +++ b/app/Notifications/ScheduledTask/TaskFailed.php @@ -3,20 +3,12 @@ namespace App\Notifications\ScheduledTask; use App\Models\ScheduledTask; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class TaskFailed extends Notification implements ShouldQueue +class TaskFailed extends CustomEmailNotification { - use Queueable; - - public $backoff = 10; - - public $tries = 2; - public ?string $url = null; public function __construct(public ScheduledTask $task, public string $output) diff --git a/app/Notifications/Server/DockerCleanup.php b/app/Notifications/Server/DockerCleanup.php index 7e9425bb3..2d007a262 100644 --- a/app/Notifications/Server/DockerCleanup.php +++ b/app/Notifications/Server/DockerCleanup.php @@ -5,17 +5,11 @@ namespace App\Notifications\Server; use App\Models\Server; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\TelegramChannel; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Notifications\Notification; -class DockerCleanup extends Notification implements ShouldQueue +class DockerCleanup extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public function __construct(public Server $server, public string $message) { $this->onQueue('high'); diff --git a/app/Notifications/Server/ForceDisabled.php b/app/Notifications/Server/ForceDisabled.php index 0008e3ed7..eabf8b334 100644 --- a/app/Notifications/Server/ForceDisabled.php +++ b/app/Notifications/Server/ForceDisabled.php @@ -6,18 +6,12 @@ use App\Models\Server; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; use App\Notifications\Channels\TelegramChannel; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class ForceDisabled extends Notification implements ShouldQueue +class ForceDisabled extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public function __construct(public Server $server) { $this->onQueue('high'); diff --git a/app/Notifications/Server/ForceEnabled.php b/app/Notifications/Server/ForceEnabled.php index 15288ddcf..0c21ed6b8 100644 --- a/app/Notifications/Server/ForceEnabled.php +++ b/app/Notifications/Server/ForceEnabled.php @@ -6,18 +6,12 @@ use App\Models\Server; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; use App\Notifications\Channels\TelegramChannel; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class ForceEnabled extends Notification implements ShouldQueue +class ForceEnabled extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public function __construct(public Server $server) { $this->onQueue('high'); diff --git a/app/Notifications/Server/HighDiskUsage.php b/app/Notifications/Server/HighDiskUsage.php index d07af0f24..7cec2e892 100644 --- a/app/Notifications/Server/HighDiskUsage.php +++ b/app/Notifications/Server/HighDiskUsage.php @@ -3,18 +3,12 @@ namespace App\Notifications\Server; use App\Models\Server; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class HighDiskUsage extends Notification implements ShouldQueue +class HighDiskUsage extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - public function __construct(public Server $server, public int $disk_usage, public int $server_disk_usage_notification_threshold) { $this->onQueue('high'); diff --git a/app/Notifications/Server/Reachable.php b/app/Notifications/Server/Reachable.php index dc8ff6bad..44189c3b5 100644 --- a/app/Notifications/Server/Reachable.php +++ b/app/Notifications/Server/Reachable.php @@ -6,18 +6,12 @@ use App\Models\Server; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; use App\Notifications\Channels\TelegramChannel; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class Reachable extends Notification implements ShouldQueue +class Reachable extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - protected bool $isRateLimited = false; public function __construct(public Server $server) diff --git a/app/Notifications/Server/Unreachable.php b/app/Notifications/Server/Unreachable.php index c28877aa0..6fb792bdc 100644 --- a/app/Notifications/Server/Unreachable.php +++ b/app/Notifications/Server/Unreachable.php @@ -6,18 +6,12 @@ use App\Models\Server; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; use App\Notifications\Channels\TelegramChannel; +use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class Unreachable extends Notification implements ShouldQueue +class Unreachable extends CustomEmailNotification { - use Queueable; - - public $tries = 1; - protected bool $isRateLimited = false; public function __construct(public Server $server) diff --git a/app/Notifications/TransactionalEmails/InvitationLink.php b/app/Notifications/TransactionalEmails/InvitationLink.php index eef7ba0e5..30ace99dc 100644 --- a/app/Notifications/TransactionalEmails/InvitationLink.php +++ b/app/Notifications/TransactionalEmails/InvitationLink.php @@ -6,17 +6,11 @@ use App\Models\Team; use App\Models\TeamInvitation; use App\Models\User; use App\Notifications\Channels\TransactionalEmailChannel; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; +use App\Notifications\CustomEmailNotification; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class InvitationLink extends Notification implements ShouldQueue +class InvitationLink extends CustomEmailNotification { - use Queueable; - - public $tries = 5; - public function via(): array { return [TransactionalEmailChannel::class]; diff --git a/app/Notifications/TransactionalEmails/Test.php b/app/Notifications/TransactionalEmails/Test.php index b3cc79604..eeb32a254 100644 --- a/app/Notifications/TransactionalEmails/Test.php +++ b/app/Notifications/TransactionalEmails/Test.php @@ -3,17 +3,11 @@ namespace App\Notifications\TransactionalEmails; use App\Notifications\Channels\EmailChannel; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; +use App\Notifications\CustomEmailNotification; use Illuminate\Notifications\Messages\MailMessage; -use Illuminate\Notifications\Notification; -class Test extends Notification implements ShouldQueue +class Test extends CustomEmailNotification { - use Queueable; - - public $tries = 5; - public function __construct(public string $emails) { $this->onQueue('high'); diff --git a/bootstrap/getVersion.php b/bootstrap/getVersion.php index d65cc92e6..8fa27a332 100644 --- a/bootstrap/getVersion.php +++ b/bootstrap/getVersion.php @@ -1,4 +1,10 @@ [ - 'version' => '4.0.0-beta.372', + 'version' => '4.0.0-beta.374', 'self_hosted' => env('SELF_HOSTED', true), 'autoupdate' => env('AUTOUPDATE'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), diff --git a/public/svgs/default.webp b/public/svgs/default.webp new file mode 100644 index 000000000..e47383469 Binary files /dev/null and b/public/svgs/default.webp differ diff --git a/resources/css/app.css b/resources/css/app.css index e378d4640..c3d46cc04 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -4,9 +4,23 @@ @tailwind components; @tailwind utilities; +html { + font-size: 93.75%; +} + +:root { + --vh: 1vh; +} + +@screen lg { + html { + font-size: 87.5%; + } +} + html, body { - @apply h-full bg-neutral-50 text-neutral-800 dark:bg-base dark:text-neutral-400; + @apply h-full bg-neutral-50 text-neutral-800 dark:bg-base dark:text-neutral-400 w-full; } body { @@ -30,6 +44,14 @@ body { @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300; } +.input-sticky { + @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 dark:focus:ring-coolgray-300 focus:ring-neutral-400 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset; +} + +.input-sticky-active { + @apply border-2 border-coollabs text-black dark:text-white focus:bg-neutral-200 dark:focus:bg-coolgray-400 focus:border-coollabs; +} + /* Readonly */ .input { @apply dark:read-only:text-neutral-500 dark:read-only:ring-0 dark:read-only:bg-coolgray-100/40 placeholder:text-neutral-300 dark:placeholder:text-neutral-700 read-only:text-neutral-500 read-only:bg-neutral-200; diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index 19cb4bdfc..4812fd4ba 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -162,7 +162,7 @@
Nixpacks will detect the required configuration automatically. Framework + href="https://coolify.io/docs/applications">Framework Specific Docs
@endif diff --git a/resources/views/livewire/project/application/source.blade.php b/resources/views/livewire/project/application/source.blade.php index 4095c63e0..4aab498e9 100644 --- a/resources/views/livewire/project/application/source.blade.php +++ b/resources/views/livewire/project/application/source.blade.php @@ -43,7 +43,7 @@

Select another Private Key

@foreach ($privateKeys as $key) - {{ $key->name }} + {{ $key->name }} @endforeach
diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index 78d3a3443..323191bfd 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -12,9 +12,10 @@
Deploy resources, like Applications, Databases, Services...
@if ($current_step === 'type') -
- +
+
Loading...
@@ -30,8 +31,7 @@ - @@ -47,8 +47,7 @@
@@ -100,7 +99,7 @@