diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 4e1931919..9d4f563cb 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -67,6 +67,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted // Save original server between phases private Server $original_server; private Server $mainServer; + private bool $is_this_additional_server = false; private ?ApplicationPreview $preview = null; private ?string $git_type = null; private bool $only_this_server = false; @@ -124,6 +125,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->rollback = $this->application_deployment_queue->rollback; $this->force_rebuild = $this->application_deployment_queue->force_rebuild; $this->restart_only = $this->application_deployment_queue->restart_only; + $this->restart_only = $this->restart_only && $this->application->build_pack !== 'dockerimage' && $this->application->build_pack !== 'dockerfile'; $this->only_this_server = $this->application_deployment_queue->only_this_server; $this->git_type = data_get($this->application_deployment_queue, 'git_type'); @@ -137,6 +139,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->destination = $this->server->destinations()->where('id', $this->application_deployment_queue->destination_id)->first(); $this->server = $this->mainServer = $this->destination->server; $this->serverUser = $this->server->user; + $this->is_this_additional_server = $this->application->additional_servers()->wherePivot('server_id', $this->server->id)->count() > 0; + $this->basedir = $this->application->generateBaseDir($this->deployment_uuid); $this->workdir = "{$this->basedir}" . rtrim($this->application->base_directory, '/'); $this->configuration_dir = application_configuration_dir() . "/{$this->application->uuid}"; @@ -150,28 +154,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted // Set preview fqdn if ($this->pull_request_id !== 0) { - $this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id); - if ($this->application->fqdn) { - if (str($this->application->fqdn)->contains(',')) { - $url = Url::fromString(str($this->application->fqdn)->explode(',')[0]); - $preview_fqdn = getFqdnWithoutPort(str($this->application->fqdn)->explode(',')[0]); - } else { - $url = Url::fromString($this->application->fqdn); - if (data_get($this->preview, 'fqdn')) { - $preview_fqdn = getFqdnWithoutPort(data_get($this->preview, 'fqdn')); - } - } - $template = $this->application->preview_url_template; - $host = $url->getHost(); - $schema = $url->getScheme(); - $random = new Cuid2(7); - $preview_fqdn = str_replace('{{random}}', $random, $template); - $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); - $preview_fqdn = str_replace('{{pr_id}}', $this->pull_request_id, $preview_fqdn); - $preview_fqdn = "$schema://$preview_fqdn"; - $this->preview->fqdn = $preview_fqdn; - $this->preview->save(); - } + $this->preview = $this->application->generate_preview_fqdn($this->pull_request_id); if ($this->application->is_github_based()) { ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::IN_PROGRESS); } @@ -285,7 +268,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } private function decide_what_to_do() { - if ($this->restart_only && $this->application->build_pack !== 'dockerimage' && $this->application->build_pack !== 'dockerfile') { + if ($this->restart_only) { $this->just_restart(); return; } else if ($this->pull_request_id !== 0) { @@ -335,18 +318,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted ], ); $this->generate_image_names(); - - // Always rebuild dockerfile based container. - // if (!$this->force_rebuild) { - // $this->check_image_locally_or_remotely(); - // if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { - // $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); - // $this->generate_compose_file(); - // $this->push_to_docker_registry(); - // $this->rolling_update(); - // return; - // } - // } $this->generate_compose_file(); $this->generate_build_env_variables(); $this->add_build_env_variables_to_dockerfile(); @@ -406,6 +377,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted }); $composeFile['services'] = $services->toArray(); } + if (is_null($composeFile)) { + $this->application_deployment_queue->addLogEntry("Failed to parse docker-compose file."); + $this->fail("Failed to parse docker-compose file."); + return; + } $yaml = Yaml::dump($composeFile->toArray(), 10); } $this->docker_compose_base64 = base64_encode($yaml); @@ -499,16 +475,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } $this->prepare_builder_image(); $this->check_git_if_build_needed(); - $this->set_base_dir(); $this->generate_image_names(); $this->clone_repository(); if (!$this->force_rebuild) { $this->check_image_locally_or_remotely(); - if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { - $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); - $this->generate_compose_file(); - $this->push_to_docker_registry(); - $this->rolling_update(); + if ($this->should_skip_build()) { return; } } @@ -528,21 +499,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); - $this->set_base_dir(); $this->generate_image_names(); if (!$this->force_rebuild) { $this->check_image_locally_or_remotely(); - if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { - $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); - $this->generate_compose_file(); - ray('pushing to docker registry'); - $this->push_to_docker_registry(); - $this->rolling_update(); + if ($this->should_skip_build()) { return; } - if ($this->application->isConfigurationChanged()) { - $this->application_deployment_queue->addLogEntry("Configuration changed. Rebuilding image."); - } } $this->clone_repository(); $this->cleanup_git(); @@ -561,15 +523,10 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); - $this->set_base_dir(); $this->generate_image_names(); if (!$this->force_rebuild) { $this->check_image_locally_or_remotely(); - if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { - $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); - $this->generate_compose_file(); - $this->push_to_docker_registry(); - $this->rolling_update(); + if ($this->should_skip_build()) { return; } } @@ -637,7 +594,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted ray('additional_servers'); $forceFail = true; } - if ($this->application->additional_servers()->wherePivot('server_id', $this->server->id)->count() > 0) { + if ($this->is_this_additional_server) { ray('this is an additional_servers, no pushy pushy'); return; } @@ -652,8 +609,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted ], ); if ($this->application->docker_registry_image_tag) { - // Tag image with latest - $this->application_deployment_queue->addLogEntry("Tagging and pushing image with latest tag."); + // Tag image with docker_registry_image_tag + $this->application_deployment_queue->addLogEntry("Tagging and pushing image with {$this->application->docker_registry_image_tag} tag."); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "docker tag {$this->production_image_name} {$this->application->docker_registry_image_name}:{$this->application->docker_registry_image_tag}"), 'ignore_errors' => true, 'hidden' => true @@ -694,9 +651,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } } else { $this->dockerImageTag = str($this->commit)->substr(0, 128); - if ($this->application->docker_registry_image_tag) { - $this->dockerImageTag = $this->application->docker_registry_image_tag; - } + // if ($this->application->docker_registry_image_tag) { + // $this->dockerImageTag = $this->application->docker_registry_image_tag; + // } if ($this->application->docker_registry_image_name) { $this->build_image_name = "{$this->application->docker_registry_image_name}:{$this->dockerImageTag}-build"; $this->production_image_name = "{$this->application->docker_registry_image_name}:{$this->dockerImageTag}"; @@ -711,19 +668,42 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->application_deployment_queue->addLogEntry("Restarting {$this->customRepository}:{$this->application->git_branch} on {$this->server->name}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); - $this->set_base_dir(); $this->generate_image_names(); $this->check_image_locally_or_remotely(); + if ($this->should_skip_build()) { + return; + } + } + private function should_skip_build() + { if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty()) { - $this->application_deployment_queue->addLogEntry("Image found ({$this->production_image_name}) with the same Git Commit SHA. Restarting container."); - $this->generate_compose_file(); - $this->rolling_update(); - $this->post_deployment(); + if ($this->is_this_additional_server) { + $this->application_deployment_queue->addLogEntry("Image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); + $this->generate_compose_file(); + $this->push_to_docker_registry(); + $this->rolling_update(); + if ($this->restart_only) { + $this->post_deployment(); + } + return true; + } + if (!$this->application->isConfigurationChanged()) { + $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); + $this->generate_compose_file(); + $this->push_to_docker_registry(); + $this->rolling_update(); + return true; + } else { + $this->application_deployment_queue->addLogEntry("Configuration changed. Rebuilding image."); + } } else { - $this->application_deployment_queue->addLogEntry("Image not found ({$this->production_image_name}). Redeploying the application."); + $this->application_deployment_queue->addLogEntry("Image not found ({$this->production_image_name}). Building new image."); + } + if ($this->restart_only) { $this->restart_only = false; $this->decide_what_to_do(); } + return false; } private function check_image_locally_or_remotely() { @@ -890,7 +870,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted ] ); } - } } @@ -1057,7 +1036,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->clone_repository(); - $this->set_base_dir(); $this->cleanup_git(); if ($this->application->build_pack === 'nixpacks') { $this->generate_nixpacks_confs(); @@ -1179,10 +1157,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted ])); } } - private function set_base_dir() - { - $this->application_deployment_queue->addLogEntry("Setting base directory to {$this->workdir}."); - } private function set_coolify_variables() { $this->coolify_variables = "SOURCE_COMMIT={$this->commit} "; diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index 718312d2d..cca55d1b0 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -287,7 +287,7 @@ class General extends Component if ($this->application->additional_servers->count() === 0) { foreach ($domains as $domain) { if (!validate_dns_entry($domain, $this->application->destination->server)) { - $showToaster && $this->dispatch('error', "Validating DNS ($domain) failed.", "Make sure you have added the DNS records correctly.

Check this documentation for further help."); + $showToaster && $this->dispatch('error', "Validating DNS failed.", "Make sure you have added the DNS records correctly.

$domain->{$this->application->destination->server->ip}

Check this documentation for further help."); } } } @@ -352,7 +352,7 @@ class General extends Component $domain = data_get($service, 'domain'); if ($domain) { if (!validate_dns_entry($domain, $this->application->destination->server)) { - $showToaster && $this->dispatch('error', "Validating DNS ($domain) failed.", "Make sure you have added the DNS records correctly.

Check this documentation for further help."); + $showToaster && $this->dispatch('error', "Validating DNS failed.", "Make sure you have added the DNS records correctly.

$domain->{$this->application->destination->server->ip}

Check this documentation for further help."); } check_domain_usage(resource: $this->application); } diff --git a/app/Livewire/Project/Application/Previews.php b/app/Livewire/Project/Application/Previews.php index d057479ea..1f4a144a9 100644 --- a/app/Livewire/Project/Application/Previews.php +++ b/app/Livewire/Project/Application/Previews.php @@ -2,10 +2,12 @@ namespace App\Livewire\Project\Application; +use App\Actions\Docker\GetContainersStatus; use App\Models\Application; use App\Models\ApplicationPreview; use Illuminate\Support\Collection; use Livewire\Component; +use Spatie\Url\Url; use Visus\Cuid2\Cuid2; class Previews extends Component @@ -16,6 +18,9 @@ class Previews extends Component public Collection $pull_requests; public int $rate_limit_remaining; + protected $rules = [ + 'application.previews.*.fqdn' => 'string|nullable', + ]; public function mount() { $this->pull_requests = collect(); @@ -33,7 +38,71 @@ class Previews extends Component return handleError($e, $this); } } + public function save_preview($preview_id) + { + try { + $success = true; + $preview = $this->application->previews->find($preview_id); + if (isset($preview->fqdn)) { + $preview->fqdn = str($preview->fqdn)->replaceEnd(',', '')->trim(); + $preview->fqdn = str($preview->fqdn)->replaceStart(',', '')->trim(); + $preview->fqdn = str($preview->fqdn)->trim()->lower(); + if (!validate_dns_entry($preview->fqdn, $this->application->destination->server)) { + $this->dispatch('error', "Validating DNS failed.", "Make sure you have added the DNS records correctly.

$preview->fqdn->{$this->application->destination->server->ip}

Check this documentation for further help."); + $success = false; + } + check_domain_usage(resource: $this->application, domain: $preview->fqdn); + } + if (!$preview) { + throw new \Exception('Preview not found'); + } + $success && $preview->save(); + $success && $this->dispatch('success', 'Preview saved.

Do not forget to redeploy the preview to apply the changes.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function generate_preview($preview_id) + { + $preview = $this->application->previews->find($preview_id); + if (!$preview) { + $this->dispatch('error', 'Preview not found.'); + return; + } + $fqdn = generateFqdn($this->application->destination->server, $this->application->uuid); + + $url = Url::fromString($fqdn); + $template = $this->application->preview_url_template; + $host = $url->getHost(); + $schema = $url->getScheme(); + $random = new Cuid2(7); + $preview_fqdn = str_replace('{{random}}', $random, $template); + $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); + $preview_fqdn = str_replace('{{pr_id}}', $preview_id, $preview_fqdn); + $preview_fqdn = "$schema://$preview_fqdn"; + $preview->fqdn = $preview_fqdn; + $preview->save(); + $this->dispatch('success', 'Domain generated.'); + } + public function add(int $pull_request_id, string|null $pull_request_html_url = null) + { + try { + $this->setDeploymentUuid(); + $found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first(); + if (!$found && !is_null($pull_request_html_url)) { + ApplicationPreview::create([ + 'application_id' => $this->application->id, + 'pull_request_id' => $pull_request_id, + 'pull_request_html_url' => $pull_request_html_url + ]); + } + $this->application->generate_preview_fqdn($pull_request_id); + $this->application->refresh(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } public function deploy(int $pull_request_id, string|null $pull_request_html_url = null) { try { @@ -71,6 +140,25 @@ class Previews extends Component } public function stop(int $pull_request_id) + { + try { + if ($this->application->destination->server->isSwarm()) { + instant_remote_process(["docker stack rm {$this->application->uuid}-{$pull_request_id}"], $this->application->destination->server); + } else { + $containers = getCurrentApplicationContainerStatus($this->application->destination->server, $this->application->id, $pull_request_id); + foreach ($containers as $container) { + $name = str_replace('/', '', $container['Names']); + instant_remote_process(["docker rm -f $name"], $this->application->destination->server, throwError: false); + } + } + GetContainersStatus::dispatchSync($this->application->destination->server); + $this->application->refresh(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function delete(int $pull_request_id) { try { if ($this->application->destination->server->isSwarm()) { diff --git a/app/Livewire/Project/Shared/GetLogs.php b/app/Livewire/Project/Shared/GetLogs.php index e14cd6113..0060fa16e 100644 --- a/app/Livewire/Project/Shared/GetLogs.php +++ b/app/Livewire/Project/Shared/GetLogs.php @@ -43,6 +43,11 @@ class GetLogs extends Component $this->showTimeStamps = $this->resource->is_include_timestamps; } } + if ($this->resource?->getMorphClass() === 'App\Models\Application') { + if (str($this->container)->contains('-pr-')) { + $this->pull_request = "Pull Request: " . str($this->container)->afterLast('-pr-')->beforeLast('_')->value(); + } + } } } public function doSomethingWithThisChunkOfOutput($output) @@ -77,13 +82,6 @@ class GetLogs extends Component if (!$this->server->isFunctional()) { return; } - if ($this->resource?->getMorphClass() === 'App\Models\Application') { - if (str($this->container)->contains('-pr-')) { - $this->pull_request = "Pull Request: " . str($this->container)->afterLast('-pr-')->beforeLast('_')->value(); - } else { - $this->pull_request = 'branch'; - } - } if (!$refresh && ($this->resource?->getMorphClass() === 'App\Models\Service' || str($this->container)->contains('-pr-'))) return; if (!$this->numberOfLines) { $this->numberOfLines = 1000; diff --git a/app/Livewire/Project/Shared/Logs.php b/app/Livewire/Project/Shared/Logs.php index f1d70bf28..52a7b568d 100644 --- a/app/Livewire/Project/Shared/Logs.php +++ b/app/Livewire/Project/Shared/Logs.php @@ -103,6 +103,14 @@ class Logs extends Component } } $this->containers = $this->containers->sort(); + if (data_get($this->query,'pull_request_id')) { + $this->containers = $this->containers->filter(function ($container) { + return str_contains($container, $this->query['pull_request_id']); + }); + ray($this->containers); + + } + $this->loadMetrics(); } catch (\Exception $e) { return handleError($e, $this); diff --git a/app/Livewire/Settings/Configuration.php b/app/Livewire/Settings/Configuration.php index 54dbe1bdb..68dc59a7f 100644 --- a/app/Livewire/Settings/Configuration.php +++ b/app/Livewire/Settings/Configuration.php @@ -70,9 +70,8 @@ class Configuration extends Component $this->validate(); if ($this->settings->is_dns_validation_enabled && $this->settings->fqdn) { - ray('asdf'); if (!validate_dns_entry($this->settings->fqdn, $this->server)) { - $this->dispatch('error', "Validating DNS ({$this->settings->fqdn}) failed.

Make sure you have added the DNS records correctly.

Check this documentation for further help."); + $this->dispatch('error', "Validating DNS failed.

Make sure you have added the DNS records correctly.

{$this->settings->fqdn}->{$this->server->ip}

Check this documentation for further help."); $error_show = true; } } diff --git a/app/Models/Application.php b/app/Models/Application.php index 21c5dfea8..e0ed328f9 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -1052,4 +1052,29 @@ class Application extends BaseModel } } } + function generate_preview_fqdn(int $pull_request_id) { + $preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->id, $pull_request_id); + if (is_null(data_get($preview, 'fqdn')) && $this->fqdn) { + if (str($this->fqdn)->contains(',')) { + $url = Url::fromString(str($this->fqdn)->explode(',')[0]); + $preview_fqdn = getFqdnWithoutPort(str($this->fqdn)->explode(',')[0]); + } else { + $url = Url::fromString($this->fqdn); + if (data_get($preview, 'fqdn')) { + $preview_fqdn = getFqdnWithoutPort(data_get($preview, 'fqdn')); + } + } + $template = $this->preview_url_template; + $host = $url->getHost(); + $schema = $url->getScheme(); + $random = new Cuid2(7); + $preview_fqdn = str_replace('{{random}}', $random, $template); + $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); + $preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn); + $preview_fqdn = "$schema://$preview_fqdn"; + $preview->fqdn = $preview_fqdn; + $preview->save(); + } + return $preview; + } } diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index f6841f6ac..0ce578758 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -465,13 +465,32 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview $appUuid = $appUuid . '-pr-' . $pull_request_id; } $labels = collect([]); - if ($application->fqdn) { - if ($pull_request_id !== 0) { - $domains = Str::of(data_get($preview, 'fqdn'))->explode(','); - } else { + if ($pull_request_id === 0) { + if ($application->fqdn) { $domains = Str::of(data_get($application, 'fqdn'))->explode(','); + $labels = $labels->merge(fqdnLabelsForTraefik( + uuid: $appUuid, + domains: $domains, + onlyPort: $onlyPort, + is_force_https_enabled: $application->isForceHttpsEnabled(), + is_gzip_enabled: $application->isGzipEnabled(), + is_stripprefix_enabled: $application->isStripprefixEnabled() + )); + // Add Caddy labels + $labels = $labels->merge(fqdnLabelsForCaddy( + network: $application->destination->network, + uuid: $appUuid, + domains: $domains, + onlyPort: $onlyPort, + is_force_https_enabled: $application->isForceHttpsEnabled(), + is_gzip_enabled: $application->isGzipEnabled(), + is_stripprefix_enabled: $application->isStripprefixEnabled() + )); + } + } else { + if ($preview->fqdn) { + $domains = Str::of(data_get($preview, 'fqdn'))->explode(','); } - // Add Traefik labels $labels = $labels->merge(fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, @@ -490,6 +509,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() )); + } return $labels->all(); } diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 89e11d0ef..395b03ff4 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -1,54 +1,68 @@ @props([ 'title' => 'Are you sure?', - 'buttonTitle' => 'Open Modal', 'isErrorButton' => false, + 'buttonTitle' => 'REWRITE THIS BUTTON TITLE PLEASSSSEEEE', 'buttonFullWidth' => false, + 'customButton' => null, 'disabled' => false, 'action' => 'delete', 'content' => null, ])
- @if ($content) -
- {{ $content }} -
- @else - @if ($disabled) - @if ($buttonFullWidth) - - {{ $buttonTitle }} - - @else - - {{ $buttonTitle }} - - @endif - @elseif ($isErrorButton) - @if ($buttonFullWidth) - - {{ $buttonTitle }} - - @else - - {{ $buttonTitle }} - - @endif + @if ($customButton) + @if ($buttonFullWidth) + + {{ $customButton }} + @else - @if ($buttonFullWidth) - - {{ $buttonTitle }} - + + {{ $customButton }} + + @endif + @else + @if ($content) +
+ {{ $content }} +
+ @else + @if ($disabled) + @if ($buttonFullWidth) + + {{ $buttonTitle }} + + @else + + {{ $buttonTitle }} + + @endif + @elseif ($isErrorButton) + @if ($buttonFullWidth) + + {{ $buttonTitle }} + + @else + + {{ $buttonTitle }} + + @endif @else - - {{ $buttonTitle }} - + @if ($buttonFullWidth) + + {{ $buttonTitle }} + + @else + + {{ $buttonTitle }} + + @endif @endif @endif @endif