Merge branch 'next' into main
This commit is contained in:
		@@ -266,6 +266,10 @@ class Github extends Controller
 | 
				
			|||||||
                if (Str::isMatch('/refs\/heads\/*/', $branch)) {
 | 
					                if (Str::isMatch('/refs\/heads\/*/', $branch)) {
 | 
				
			||||||
                    $branch = Str::after($branch, 'refs/heads/');
 | 
					                    $branch = Str::after($branch, 'refs/heads/');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                $added_files = data_get($payload, 'commits.*.added');
 | 
				
			||||||
 | 
					                $removed_files = data_get($payload, 'commits.*.removed');
 | 
				
			||||||
 | 
					                $modified_files = data_get($payload, 'commits.*.modified');
 | 
				
			||||||
 | 
					                $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten();
 | 
				
			||||||
                ray('Webhook GitHub Push Event: ' . $id . ' with branch: ' . $branch);
 | 
					                ray('Webhook GitHub Push Event: ' . $id . ' with branch: ' . $branch);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if ($x_github_event === 'pull_request') {
 | 
					            if ($x_github_event === 'pull_request') {
 | 
				
			||||||
@@ -298,32 +302,50 @@ class Github extends Controller
 | 
				
			|||||||
                $isFunctional = $application->destination->server->isFunctional();
 | 
					                $isFunctional = $application->destination->server->isFunctional();
 | 
				
			||||||
                if (!$isFunctional) {
 | 
					                if (!$isFunctional) {
 | 
				
			||||||
                    $return_payloads->push([
 | 
					                    $return_payloads->push([
 | 
				
			||||||
                        'application' => $application->name,
 | 
					 | 
				
			||||||
                        'status' => 'failed',
 | 
					                        'status' => 'failed',
 | 
				
			||||||
                        'message' => 'Server is not functional.',
 | 
					                        'message' => 'Server is not functional.',
 | 
				
			||||||
 | 
					                        'application_uuid' => $application->uuid,
 | 
				
			||||||
 | 
					                        'application_name' => $application->name,
 | 
				
			||||||
                    ]);
 | 
					                    ]);
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if ($x_github_event === 'push') {
 | 
					                if ($x_github_event === 'push') {
 | 
				
			||||||
                    if ($application->isDeployable()) {
 | 
					                    if ($application->isDeployable()) {
 | 
				
			||||||
                        ray('Deploying ' . $application->name . ' with branch ' . $branch);
 | 
					                        $watch_files_trigger = $application->watchPathCheck($changed_files);
 | 
				
			||||||
                        $deployment_uuid = new Cuid2(7);
 | 
					                        if (!$watch_files_trigger) {
 | 
				
			||||||
                        queue_application_deployment(
 | 
					                            $paths = str($application->watch_paths)->explode("\n");
 | 
				
			||||||
                            application: $application,
 | 
					                            $return_payloads->push([
 | 
				
			||||||
                            deployment_uuid: $deployment_uuid,
 | 
					                                'status' => 'failed',
 | 
				
			||||||
                            force_rebuild: false,
 | 
					                                'message' => 'Changed files do not match watch paths. Ignoring deployment.',
 | 
				
			||||||
                            is_webhook: true
 | 
					                                'application_uuid' => $application->uuid,
 | 
				
			||||||
                        );
 | 
					                                'application_name' => $application->name,
 | 
				
			||||||
                        $return_payloads->push([
 | 
					                                'details' => [
 | 
				
			||||||
                            'application' => $application->name,
 | 
					                                    'changed_files' => $changed_files,
 | 
				
			||||||
                            'status' => 'success',
 | 
					                                    'watch_paths' => $paths,
 | 
				
			||||||
                            'message' => 'Deployment queued.',
 | 
					                                ],
 | 
				
			||||||
                        ]);
 | 
					                            ]);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            ray('Deploying ' . $application->name . ' with branch ' . $branch);
 | 
				
			||||||
 | 
					                            $deployment_uuid = new Cuid2(7);
 | 
				
			||||||
 | 
					                            queue_application_deployment(
 | 
				
			||||||
 | 
					                                application: $application,
 | 
				
			||||||
 | 
					                                deployment_uuid: $deployment_uuid,
 | 
				
			||||||
 | 
					                                force_rebuild: false,
 | 
				
			||||||
 | 
					                                is_webhook: true,
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
 | 
					                            $return_payloads->push([
 | 
				
			||||||
 | 
					                                'status' => 'success',
 | 
				
			||||||
 | 
					                                'message' => 'Deployment queued.',
 | 
				
			||||||
 | 
					                                'application_uuid' => $application->uuid,
 | 
				
			||||||
 | 
					                                'application_name' => $application->name,
 | 
				
			||||||
 | 
					                            ]);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        $return_payloads->push([
 | 
					                        $return_payloads->push([
 | 
				
			||||||
                            'application' => $application->name,
 | 
					 | 
				
			||||||
                            'status' => 'failed',
 | 
					                            'status' => 'failed',
 | 
				
			||||||
                            'message' => 'Deployments disabled.',
 | 
					                            'message' => 'Deployments disabled.',
 | 
				
			||||||
 | 
					                            'application_uuid' => $application->uuid,
 | 
				
			||||||
 | 
					                            'application_name' => $application->name,
 | 
				
			||||||
                        ]);
 | 
					                        ]);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -234,7 +234,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
                $this->build_server = $this->server;
 | 
					                $this->build_server = $this->server;
 | 
				
			||||||
                $this->original_server = $this->server;
 | 
					                $this->original_server = $this->server;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if ($this->restart_only && $this->application->build_pack !== 'dockerimage') {
 | 
					            if ($this->restart_only && $this->application->build_pack !== 'dockerimage' && $this->application->build_pack !== 'dockerfile') {
 | 
				
			||||||
                $this->just_restart();
 | 
					                $this->just_restart();
 | 
				
			||||||
                if ($this->server->isProxyShouldRun()) {
 | 
					                if ($this->server->isProxyShouldRun()) {
 | 
				
			||||||
                    dispatch(new ContainerStatusJob($this->server));
 | 
					                    dispatch(new ContainerStatusJob($this->server));
 | 
				
			||||||
@@ -326,17 +326,19 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        $this->generate_image_names();
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        if (!$this->force_rebuild) {
 | 
					
 | 
				
			||||||
            $this->check_image_locally_or_remotely();
 | 
					        // Always rebuild dockerfile based container.
 | 
				
			||||||
            if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) {
 | 
					        // if (!$this->force_rebuild) {
 | 
				
			||||||
                $this->create_workdir();
 | 
					        //     $this->check_image_locally_or_remotely();
 | 
				
			||||||
                $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped.");
 | 
					        //     if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) {
 | 
				
			||||||
                $this->generate_compose_file();
 | 
					        //         $this->create_workdir();
 | 
				
			||||||
                $this->push_to_docker_registry();
 | 
					        //         $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped.");
 | 
				
			||||||
                $this->rolling_update();
 | 
					        //         $this->generate_compose_file();
 | 
				
			||||||
                return;
 | 
					        //         $this->push_to_docker_registry();
 | 
				
			||||||
            }
 | 
					        //         $this->rolling_update();
 | 
				
			||||||
        }
 | 
					        //         return;
 | 
				
			||||||
 | 
					        //     }
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
        $this->generate_compose_file();
 | 
					        $this->generate_compose_file();
 | 
				
			||||||
        $this->generate_build_env_variables();
 | 
					        $this->generate_build_env_variables();
 | 
				
			||||||
        $this->add_build_env_variables_to_dockerfile();
 | 
					        $this->add_build_env_variables_to_dockerfile();
 | 
				
			||||||
@@ -467,17 +469,17 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        $this->set_base_dir();
 | 
					        $this->set_base_dir();
 | 
				
			||||||
        $this->generate_image_names();
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        $this->clone_repository();
 | 
					        $this->clone_repository();
 | 
				
			||||||
        if (!$this->force_rebuild) {
 | 
					        // if (!$this->force_rebuild) {
 | 
				
			||||||
            $this->check_image_locally_or_remotely();
 | 
					        //     $this->check_image_locally_or_remotely();
 | 
				
			||||||
            if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) {
 | 
					        //     if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) {
 | 
				
			||||||
                $this->create_workdir();
 | 
					        //         $this->create_workdir();
 | 
				
			||||||
                $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped.");
 | 
					        //         $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->generate_compose_file();
 | 
				
			||||||
                $this->push_to_docker_registry();
 | 
					        //         $this->push_to_docker_registry();
 | 
				
			||||||
                $this->rolling_update();
 | 
					        //         $this->rolling_update();
 | 
				
			||||||
                return;
 | 
					        //         return;
 | 
				
			||||||
            }
 | 
					        //     }
 | 
				
			||||||
        }
 | 
					        // }
 | 
				
			||||||
        $this->cleanup_git();
 | 
					        $this->cleanup_git();
 | 
				
			||||||
        $this->generate_compose_file();
 | 
					        $this->generate_compose_file();
 | 
				
			||||||
        $this->generate_build_env_variables();
 | 
					        $this->generate_build_env_variables();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,31 @@ use Livewire\Component;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Index extends Component
 | 
					class Index extends Component
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public $users = [];
 | 
					    public $active_subscribers = [];
 | 
				
			||||||
 | 
					    public $inactive_subscribers = [];
 | 
				
			||||||
 | 
					    public $search = '';
 | 
				
			||||||
 | 
					    public function submitSearch() {
 | 
				
			||||||
 | 
					        if ($this->search !== "") {
 | 
				
			||||||
 | 
					            $this->inactive_subscribers = User::whereDoesntHave('teams', function ($query) {
 | 
				
			||||||
 | 
					                $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
 | 
				
			||||||
 | 
					            })->where(function ($query) {
 | 
				
			||||||
 | 
					                $query->where('name', 'like', "%{$this->search}%")
 | 
				
			||||||
 | 
					                    ->orWhere('email', 'like', "%{$this->search}%");
 | 
				
			||||||
 | 
					            })->get()->filter(function ($user) {
 | 
				
			||||||
 | 
					                return $user->id !== 0;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            $this->active_subscribers = User::whereHas('teams', function ($query) {
 | 
				
			||||||
 | 
					                $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
 | 
				
			||||||
 | 
					            })->where(function ($query) {
 | 
				
			||||||
 | 
					                $query->where('name', 'like', "%{$this->search}%")
 | 
				
			||||||
 | 
					                    ->orWhere('email', 'like', "%{$this->search}%");
 | 
				
			||||||
 | 
					            })->get()->filter(function ($user) {
 | 
				
			||||||
 | 
					                return $user->id !== 0;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $this->getSubscribers();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public function mount()
 | 
					    public function mount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!isCloud()) {
 | 
					        if (!isCloud()) {
 | 
				
			||||||
@@ -17,7 +41,15 @@ class Index extends Component
 | 
				
			|||||||
        if (auth()->user()->id !== 0) {
 | 
					        if (auth()->user()->id !== 0) {
 | 
				
			||||||
            return redirect()->route('dashboard');
 | 
					            return redirect()->route('dashboard');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->users = User::whereHas('teams', function ($query) {
 | 
					        $this->getSubscribers();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public function getSubscribers() {
 | 
				
			||||||
 | 
					        $this->inactive_subscribers = User::whereDoesntHave('teams', function ($query) {
 | 
				
			||||||
 | 
					            $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
 | 
				
			||||||
 | 
					        })->get()->filter(function ($user) {
 | 
				
			||||||
 | 
					            return $user->id !== 0;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        $this->active_subscribers = User::whereHas('teams', function ($query) {
 | 
				
			||||||
            $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
 | 
					            $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
 | 
				
			||||||
        })->get()->filter(function ($user) {
 | 
					        })->get()->filter(function ($user) {
 | 
				
			||||||
            return $user->id !== 0;
 | 
					            return $user->id !== 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,6 +73,7 @@ class General extends Component
 | 
				
			|||||||
        'application.settings.is_static' => 'boolean|required',
 | 
					        'application.settings.is_static' => 'boolean|required',
 | 
				
			||||||
        'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
 | 
					        'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
 | 
				
			||||||
        'application.settings.is_build_server_enabled' => 'boolean|required',
 | 
					        'application.settings.is_build_server_enabled' => 'boolean|required',
 | 
				
			||||||
 | 
					        'application.watch_paths' => 'nullable',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    protected $validationAttributes = [
 | 
					    protected $validationAttributes = [
 | 
				
			||||||
        'application.name' => 'name',
 | 
					        'application.name' => 'name',
 | 
				
			||||||
@@ -108,6 +109,7 @@ class General extends Component
 | 
				
			|||||||
        'application.settings.is_static' => 'Is static',
 | 
					        'application.settings.is_static' => 'Is static',
 | 
				
			||||||
        'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled',
 | 
					        'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled',
 | 
				
			||||||
        'application.settings.is_build_server_enabled' => 'Is build server enabled',
 | 
					        'application.settings.is_build_server_enabled' => 'Is build server enabled',
 | 
				
			||||||
 | 
					        'application.watch_paths' => 'Watch paths',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    public function mount()
 | 
					    public function mount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,14 +7,12 @@ use App\Models\GithubApp;
 | 
				
			|||||||
use App\Models\Project;
 | 
					use App\Models\Project;
 | 
				
			||||||
use App\Models\StandaloneDocker;
 | 
					use App\Models\StandaloneDocker;
 | 
				
			||||||
use App\Models\SwarmDocker;
 | 
					use App\Models\SwarmDocker;
 | 
				
			||||||
use App\Traits\SaveFromRedirect;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Http;
 | 
					use Illuminate\Support\Facades\Http;
 | 
				
			||||||
use Illuminate\Support\Facades\Route;
 | 
					use Illuminate\Support\Facades\Route;
 | 
				
			||||||
use Livewire\Component;
 | 
					use Livewire\Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GithubPrivateRepository extends Component
 | 
					class GithubPrivateRepository extends Component
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use SaveFromRedirect;
 | 
					 | 
				
			||||||
    public $current_step = 'github_apps';
 | 
					    public $current_step = 'github_apps';
 | 
				
			||||||
    public $github_apps;
 | 
					    public $github_apps;
 | 
				
			||||||
    public GithubApp $github_app;
 | 
					    public GithubApp $github_app;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,10 @@ class Select extends Component
 | 
				
			|||||||
    //     }
 | 
					    //     }
 | 
				
			||||||
    // }
 | 
					    // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function updatedSearch()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->loadServices();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public function loadServices(bool $force = false)
 | 
					    public function loadServices(bool $force = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,11 @@ class ServiceApplicationView extends Component
 | 
				
			|||||||
            $this->validate();
 | 
					            $this->validate();
 | 
				
			||||||
            $this->application->save();
 | 
					            $this->application->save();
 | 
				
			||||||
            updateCompose($this->application);
 | 
					            updateCompose($this->application);
 | 
				
			||||||
            $this->dispatch('success', 'Service saved.');
 | 
					            if (str($this->application->fqdn)->contains(',')) {
 | 
				
			||||||
 | 
					                $this->dispatch('warning', 'Some services do not support multiple domains, which can lead to problems and is NOT RECOMMENDED.');
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $this->dispatch('success', 'Service saved.');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } catch (\Throwable $e) {
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
            return handleError($e, $this);
 | 
					            return handleError($e, $this);
 | 
				
			||||||
        } finally {
 | 
					        } finally {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ use Livewire\Component;
 | 
				
			|||||||
class Show extends Component
 | 
					class Show extends Component
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public PrivateKey $private_key;
 | 
					    public PrivateKey $private_key;
 | 
				
			||||||
    public $public_key;
 | 
					    public $public_key = "Loading...";
 | 
				
			||||||
    protected $rules = [
 | 
					    protected $rules = [
 | 
				
			||||||
        'private_key.name' => 'required|string',
 | 
					        'private_key.name' => 'required|string',
 | 
				
			||||||
        'private_key.description' => 'nullable|string',
 | 
					        'private_key.description' => 'nullable|string',
 | 
				
			||||||
@@ -25,11 +25,13 @@ class Show extends Component
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail();
 | 
					            $this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail();
 | 
				
			||||||
            $this->public_key = $this->private_key->publicKey();
 | 
					 | 
				
			||||||
        }catch(\Throwable $e) {
 | 
					        }catch(\Throwable $e) {
 | 
				
			||||||
            return handleError($e, $this);
 | 
					            return handleError($e, $this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    public function loadPublicKey() {
 | 
				
			||||||
 | 
					        $this->public_key = $this->private_key->publicKey();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public function delete()
 | 
					    public function delete()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,11 @@ class Resources extends Component
 | 
				
			|||||||
        $this->dispatch('success', 'Resource statuses refreshed.');
 | 
					        $this->dispatch('success', 'Resource statuses refreshed.');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public function loadUnmanagedContainers() {
 | 
					    public function loadUnmanagedContainers() {
 | 
				
			||||||
        $this->unmanagedContainers = $this->server->loadUnmanagedContainers();
 | 
					        try {
 | 
				
			||||||
 | 
					            $this->unmanagedContainers = $this->server->loadUnmanagedContainers();
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            return handleError($e, $this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public function mount() {
 | 
					    public function mount() {
 | 
				
			||||||
        $this->unmanagedContainers = collect();
 | 
					        $this->unmanagedContainers = collect();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@ class Index extends Component
 | 
				
			|||||||
        if (!isCloud()) {
 | 
					        if (!isCloud()) {
 | 
				
			||||||
            return redirect(RouteServiceProvider::HOME);
 | 
					            return redirect(RouteServiceProvider::HOME);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (data_get(currentTeam(), 'subscription')) {
 | 
					        if (data_get(currentTeam(), 'subscription') && isSubscriptionActive()) {
 | 
				
			||||||
            return redirect()->route('subscription.show');
 | 
					            return redirect()->route('subscription.show');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->settings = InstanceSettings::get();
 | 
					        $this->settings = InstanceSettings::get();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ use App\Enums\ApplicationDeploymentStatus;
 | 
				
			|||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
					use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
				
			||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
 | 
					use Illuminate\Database\Eloquent\Relations\HasMany;
 | 
				
			||||||
use Illuminate\Database\Eloquent\SoftDeletes;
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
 | 
					use Illuminate\Support\Collection;
 | 
				
			||||||
use Spatie\Activitylog\Models\Activity;
 | 
					use Spatie\Activitylog\Models\Activity;
 | 
				
			||||||
use Illuminate\Support\Str;
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
use RuntimeException;
 | 
					use RuntimeException;
 | 
				
			||||||
@@ -903,4 +904,24 @@ class Application extends BaseModel
 | 
				
			|||||||
                : explode(',', $this->fqdn),
 | 
					                : explode(',', $this->fqdn),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    public function watchPaths(): Attribute
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Attribute::make(
 | 
				
			||||||
 | 
					            set: function ($value) {
 | 
				
			||||||
 | 
					                if ($value) {
 | 
				
			||||||
 | 
					                    return trim($value);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public function watchPathCheck(Collection $modified_files): bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $watch_paths = collect(explode("\n", $this->watch_paths));
 | 
				
			||||||
 | 
					        $matches = $modified_files->filter(function ($file) use ($watch_paths) {
 | 
				
			||||||
 | 
					            return $watch_paths->contains(function ($glob) use ($file) {
 | 
				
			||||||
 | 
					                return fnmatch($glob, $file);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return $matches->count() > 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,19 +25,18 @@ class EnvironmentVariable extends Model
 | 
				
			|||||||
        static::created(function (EnvironmentVariable $environment_variable) {
 | 
					        static::created(function (EnvironmentVariable $environment_variable) {
 | 
				
			||||||
            if ($environment_variable->application_id && !$environment_variable->is_preview) {
 | 
					            if ($environment_variable->application_id && !$environment_variable->is_preview) {
 | 
				
			||||||
                $found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
 | 
					                $found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
 | 
				
			||||||
                $application = Application::find($environment_variable->application_id);
 | 
					 | 
				
			||||||
                if ($application->build_pack === 'dockerfile') {
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if (!$found) {
 | 
					                if (!$found) {
 | 
				
			||||||
                    ModelsEnvironmentVariable::create([
 | 
					                    $application = Application::find($environment_variable->application_id);
 | 
				
			||||||
                        'key' => $environment_variable->key,
 | 
					                    if ($application->build_pack !== 'dockerfile') {
 | 
				
			||||||
                        'value' => $environment_variable->value,
 | 
					                        ModelsEnvironmentVariable::create([
 | 
				
			||||||
                        'is_build_time' => $environment_variable->is_build_time,
 | 
					                            'key' => $environment_variable->key,
 | 
				
			||||||
                        'is_multiline' => $environment_variable->is_multiline,
 | 
					                            'value' => $environment_variable->value,
 | 
				
			||||||
                        'application_id' => $environment_variable->application_id,
 | 
					                            'is_build_time' => $environment_variable->is_build_time,
 | 
				
			||||||
                        'is_preview' => true
 | 
					                            'is_multiline' => $environment_variable->is_multiline,
 | 
				
			||||||
                    ]);
 | 
					                            'application_id' => $environment_variable->application_id,
 | 
				
			||||||
 | 
					                            'is_preview' => true
 | 
				
			||||||
 | 
					                        ]);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $environment_variable->update([
 | 
					            $environment_variable->update([
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -550,21 +550,21 @@ $schema://$host {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    public function loadUnmanagedContainers()
 | 
					    public function loadUnmanagedContainers()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->isFunctional()) {
 | 
					            if ($this->isFunctional()) {
 | 
				
			||||||
            $containers = instant_remote_process(["docker ps -a  --format '{{json .}}' "], $this);
 | 
					                $containers = instant_remote_process(["docker ps -a  --format '{{json .}}' "], $this);
 | 
				
			||||||
            $containers = format_docker_command_output_to_json($containers);
 | 
					                $containers = format_docker_command_output_to_json($containers);
 | 
				
			||||||
            $containers = $containers->map(function ($container) {
 | 
					                $containers = $containers->map(function ($container) {
 | 
				
			||||||
                $labels = data_get($container, 'Labels');
 | 
					                    $labels = data_get($container, 'Labels');
 | 
				
			||||||
                if (!str($labels)->contains("coolify.managed")) {
 | 
					                    if (!str($labels)->contains("coolify.managed")) {
 | 
				
			||||||
                    return $container;
 | 
					                        return $container;
 | 
				
			||||||
                }
 | 
					                    }
 | 
				
			||||||
                return null;
 | 
					                    return null;
 | 
				
			||||||
            });
 | 
					                });
 | 
				
			||||||
            $containers = $containers->filter();
 | 
					                $containers = $containers->filter();
 | 
				
			||||||
            return collect($containers);
 | 
					                return collect($containers);
 | 
				
			||||||
        } else {
 | 
					            } else {
 | 
				
			||||||
            return collect([]);
 | 
					                return collect([]);
 | 
				
			||||||
        }
 | 
					            }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public function hasDefinedResources()
 | 
					    public function hasDefinedResources()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ use App\Models\Application;
 | 
				
			|||||||
use App\Models\ApplicationDeploymentQueue;
 | 
					use App\Models\ApplicationDeploymentQueue;
 | 
				
			||||||
use App\Models\Server;
 | 
					use App\Models\Server;
 | 
				
			||||||
use App\Models\StandaloneDocker;
 | 
					use App\Models\StandaloneDocker;
 | 
				
			||||||
 | 
					use Illuminate\Support\Collection;
 | 
				
			||||||
use Spatie\Url\Url;
 | 
					use Spatie\Url\Url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null, bool $only_this_server = false)
 | 
					function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null, bool $only_this_server = false)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,7 +282,7 @@ function base_url(bool $withPort = true): string
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function isSubscribed()
 | 
					function isSubscribed()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return auth()->user()->currentTeam()->subscription()->exists() || auth()->user()->isInstanceAdmin();
 | 
					    return isSubscriptionActive() || auth()->user()->isInstanceAdmin();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
function isDev(): bool
 | 
					function isDev(): bool
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,7 +66,7 @@ function isSubscriptionActive()
 | 
				
			|||||||
    //     return $subscription->paddle_status === 'active';
 | 
					    //     return $subscription->paddle_status === 'active';
 | 
				
			||||||
    // }
 | 
					    // }
 | 
				
			||||||
    if (isStripe()) {
 | 
					    if (isStripe()) {
 | 
				
			||||||
        return $subscription->stripe_invoice_paid === true && $subscription->stripe_cancel_at_period_end === false;
 | 
					        return $subscription->stripe_invoice_paid === true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ return [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // The release version of your application
 | 
					    // The release version of your application
 | 
				
			||||||
    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
					    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
				
			||||||
    'release' => '4.0.0-beta.248',
 | 
					    'release' => '4.0.0-beta.249',
 | 
				
			||||||
    // When left empty or `null` the Laravel environment will be used
 | 
					    // When left empty or `null` the Laravel environment will be used
 | 
				
			||||||
    'environment' => config('app.env'),
 | 
					    'environment' => config('app.env'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,3 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return '4.0.0-beta.248';
 | 
					return '4.0.0-beta.249';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?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('applications', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->longText('watch_paths')->nullable();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function down(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('applications', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->dropColumn('watch_paths');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -13,7 +13,7 @@ body {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.input,
 | 
					.input,
 | 
				
			||||||
.select {
 | 
					.select {
 | 
				
			||||||
    @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-300 dark:ring-coolgray-300;
 | 
					    @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Readonly */
 | 
					/* Readonly */
 | 
				
			||||||
@@ -41,7 +41,7 @@ option {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.button {
 | 
					.button {
 | 
				
			||||||
    @apply flex items-center justify-center gap-2 px-3 py-1 text-sm text-white normal-case rounded cursor-pointer hover:bg-black/80 bg-coolgray-200 hover:bg-coolgray-500 hover:text-white disabled:bg-coolgray-100/10 disabled:cursor-not-allowed min-w-fit focus:outline-1 dark:disabled:text-neutral-600;
 | 
					    @apply flex items-center justify-center gap-2 px-2 py-1 text-sm text-black normal-case border rounded cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-black hover:text-black disabled:bg-coolgray-100/10 disabled:cursor-not-allowed min-w-fit focus:outline-1 dark:disabled:text-neutral-600;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
button[isError]:not(:disabled) {
 | 
					button[isError]:not(:disabled) {
 | 
				
			||||||
@@ -78,7 +78,7 @@ label {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
table {
 | 
					table {
 | 
				
			||||||
    @apply min-w-full divide-y dark:divide-coolgray-200 divide-neutral-300;
 | 
					    @apply min-w-full divide-y dark:divide-coolgray-200 divide-neutral-300 ;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
thead {
 | 
					thead {
 | 
				
			||||||
@@ -90,7 +90,7 @@ tbody {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tr {
 | 
					tr {
 | 
				
			||||||
    @apply text-neutral-400;
 | 
					    @apply text-black dark:text-neutral-400 dark:hover:bg-black hover:bg-neutral-200;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tr th {
 | 
					tr th {
 | 
				
			||||||
@@ -203,6 +203,9 @@ tr td:first-child {
 | 
				
			|||||||
.box-without-bg {
 | 
					.box-without-bg {
 | 
				
			||||||
    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem]   border border-neutral-200 dark:border-black;
 | 
					    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem]   border border-neutral-200 dark:border-black;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.box-without-bg-without-border {
 | 
				
			||||||
 | 
					    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem]   ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.on-box {
 | 
					.on-box {
 | 
				
			||||||
    @apply rounded hover:bg-neutral-300 dark:hover:bg-coolgray-500/20;
 | 
					    @apply rounded hover:bg-neutral-300 dark:hover:bg-coolgray-500/20;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,3 @@
 | 
				
			|||||||
<img class="inline-flex w-4 h-4" src="{{ asset('svgs/internal-link.svg') }}">
 | 
					<svg class="inline-flex w-4 h-4 text-black dark:text-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 | 
				
			||||||
 | 
					    <path fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14m-6 6l6-6m-6-6l6 6"/>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
 
 | 
				
			|||||||
| 
		 Before Width: | Height: | Size: 78 B After Width: | Height: | Size: 272 B  | 
@@ -48,7 +48,7 @@
 | 
				
			|||||||
            <div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a
 | 
					            <div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a
 | 
				
			||||||
                    class="font-bold underline dark:text-white" href="https://coolify.io">coolify.io</a></div>
 | 
					                    class="font-bold underline dark:text-white" href="https://coolify.io">coolify.io</a></div>
 | 
				
			||||||
            <div
 | 
					            <div
 | 
				
			||||||
                class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-3 lg:divide-x lg:divide-y-0 xl:-mx-4">
 | 
					                class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-3 lg:divide-x lg:divide-y-0 xl:-mx-4">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
 | 
					                <div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
 | 
				
			||||||
                    <h3 id="tier-basic" class="text-base font-semibold leading-7 dark:text-white">Basic</h3>
 | 
					                    <h3 id="tier-basic" class="text-base font-semibold leading-7 dark:text-white">Basic</h3>
 | 
				
			||||||
@@ -186,7 +186,7 @@
 | 
				
			|||||||
                        </li>
 | 
					                        </li>
 | 
				
			||||||
                    </ul>
 | 
					                    </ul>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
 | 
					                <div class="pt-16 lg:px-8 lg:pt-0 xl:px-12">
 | 
				
			||||||
                    <h3 id="tier-ultimate" class="text-base font-semibold leading-7 dark:text-white">Ultimate</h3>
 | 
					                    <h3 id="tier-ultimate" class="text-base font-semibold leading-7 dark:text-white">Ultimate</h3>
 | 
				
			||||||
                   <p class="flex items-baseline mt-6 gap-x-1">
 | 
					                   <p class="flex items-baseline mt-6 gap-x-1">
 | 
				
			||||||
                        <span x-show="selected === 'monthly'" x-cloak>
 | 
					                        <span x-show="selected === 'monthly'" x-cloak>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,31 @@
 | 
				
			|||||||
<div>
 | 
					<div>
 | 
				
			||||||
    <h1>Admin Dashboard</h1>
 | 
					    <h1>Admin Dashboard</h1>
 | 
				
			||||||
    <h3 class="pt-4">Who am I now?</h3>
 | 
					    <h3 class="pt-4">Who am I now?</h3>
 | 
				
			||||||
    {{ auth()->user()->name }}
 | 
					    <div class="pb-4">{{ auth()->user()->name }}</div>
 | 
				
			||||||
    <h3 class="pt-4">Users</h3>
 | 
					    <form wire:submit="submitSearch" class="flex flex-col gap-2 lg:flex-row">
 | 
				
			||||||
 | 
					        <x-forms.input wire:model="search" placeholder="Search for a user" />
 | 
				
			||||||
 | 
					        <x-forms.button type="submit">Search</x-forms.button>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    <h3 class="pt-4">Active Subscribers</h3>
 | 
				
			||||||
    <div class="flex flex-wrap gap-2">
 | 
					    <div class="flex flex-wrap gap-2">
 | 
				
			||||||
        <div class="dark:text-white cursor-pointer w-96 box-without-bg bg-coollabs-100" wire:click="switchUser('0')">
 | 
					        @forelse ($active_subscribers as $user)
 | 
				
			||||||
            Root
 | 
					            <div class="flex gap-2 box" wire:click="switchUser('{{ $user->id }}')">
 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        @foreach ($users as $user)
 | 
					 | 
				
			||||||
            <div class="w-96 box" wire:click="switchUser('{{ $user->id }}')">
 | 
					 | 
				
			||||||
                <p>{{ $user->name }}</p>
 | 
					                <p>{{ $user->name }}</p>
 | 
				
			||||||
                <p>{{ $user->email }}</p>
 | 
					                <p>{{ $user->email }}</p>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        @endforeach
 | 
					        @empty
 | 
				
			||||||
 | 
					            <p>No active subscribers</p>
 | 
				
			||||||
 | 
					        @endforelse
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <h3 class="pt-4">Inactive Subscribers</h3>
 | 
				
			||||||
 | 
					    <div class="flex flex-col flex-wrap gap-2">
 | 
				
			||||||
 | 
					        @forelse ($inactive_subscribers as $user)
 | 
				
			||||||
 | 
					            <div class="flex gap-2 box" wire:click="switchUser('{{ $user->id }}')">
 | 
				
			||||||
 | 
					                <p>{{ $user->name }}</p>
 | 
				
			||||||
 | 
					                <p>{{ $user->email }}</p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        @empty
 | 
				
			||||||
 | 
					            <p>No inactive subscribers</p>
 | 
				
			||||||
 | 
					        @endforelse
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@
 | 
				
			|||||||
        @endif
 | 
					        @endif
 | 
				
			||||||
        @forelse ($deployments as $deployment)
 | 
					        @forelse ($deployments as $deployment)
 | 
				
			||||||
            <a @class([
 | 
					            <a @class([
 | 
				
			||||||
                'dark:bg-coolgray-100 p-2 border-l border-dashed transition-colors hover:no-underline box-without-bg bg-white',
 | 
					                'dark:bg-coolgray-100 p-2 border-l border-dashed transition-colors hover:no-underline box-without-bg-without-border bg-white flex-col',
 | 
				
			||||||
                'dark:hover:bg-coolgray-200' =>
 | 
					                'dark:hover:bg-coolgray-200' =>
 | 
				
			||||||
                    data_get($deployment, 'status') === 'queued',
 | 
					                    data_get($deployment, 'status') === 'queued',
 | 
				
			||||||
                'border-warning hover:bg-warning hover:text-black' =>
 | 
					                'border-warning hover:bg-warning hover:text-black' =>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,7 @@
 | 
				
			|||||||
                            <div @class([
 | 
					                            <div @class([
 | 
				
			||||||
                                'font-mono',
 | 
					                                'font-mono',
 | 
				
			||||||
                                'dark:text-warning whitespace-pre-line' => $line['hidden'],
 | 
					                                'dark:text-warning whitespace-pre-line' => $line['hidden'],
 | 
				
			||||||
                                'text-red-500 whitespace-pre-line' => $line['type'] == 'stderr',
 | 
					                                'text-red-500 font-bold whitespace-pre-line' => $line['type'] == 'stderr',
 | 
				
			||||||
                            ])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
 | 
					                            ])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
 | 
				
			||||||
                                    <br>COMMAND: <br>{{ $line['command'] }} <br><br>OUTPUT:
 | 
					                                    <br>COMMAND: <br>{{ $line['command'] }} <br><br>OUTPUT:
 | 
				
			||||||
                                    @endif @if (str($line['output'])->contains('http://') || str($line['output'])->contains('https://'))
 | 
					                                    @endif @if (str($line['output'])->contains('http://') || str($line['output'])->contains('https://'))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,7 +148,8 @@
 | 
				
			|||||||
                                id="application.start_command" label="Start Command" />
 | 
					                                id="application.start_command" label="Start Command" />
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div>Nixpacks will detect the required configuration automatically.
 | 
					                        <div>Nixpacks will detect the required configuration automatically.
 | 
				
			||||||
                            <a class="underline" href="https://coolify.io/docs/resources/introduction">Framework Specific Docs</a>
 | 
					                            <a class="underline" href="https://coolify.io/docs/resources/introduction">Framework
 | 
				
			||||||
 | 
					                                Specific Docs</a>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    @endif
 | 
					                    @endif
 | 
				
			||||||
                @endif
 | 
					                @endif
 | 
				
			||||||
@@ -201,7 +202,12 @@
 | 
				
			|||||||
                                    label="Publish Directory" />
 | 
					                                    label="Publish Directory" />
 | 
				
			||||||
                            @endif
 | 
					                            @endif
 | 
				
			||||||
                        @endif
 | 
					                        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    @if ($this->application->is_github_based())
 | 
				
			||||||
 | 
					                        <x-forms.textarea helper="Gitignore-style rules to filter Git based webhook deployments."
 | 
				
			||||||
 | 
					                            placeholder="src/pages/**" id="application.watch_paths" label="Watch Paths" />
 | 
				
			||||||
 | 
					                    @endif
 | 
				
			||||||
                    <div>The following options are for advanced use cases. Only modify them if you
 | 
					                    <div>The following options are for advanced use cases. Only modify them if you
 | 
				
			||||||
                        know what are
 | 
					                        know what are
 | 
				
			||||||
                        you doing.</div>
 | 
					                        you doing.</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
<div class="flex flex-col-reverse gap-2">
 | 
					<div class="flex flex-col-reverse gap-2">
 | 
				
			||||||
    @forelse($executions as $execution)
 | 
					    @forelse($executions as $execution)
 | 
				
			||||||
        <form wire:key="{{ data_get($execution, 'id') }}"
 | 
					        <form wire:key="{{ data_get($execution, 'id') }}"
 | 
				
			||||||
            class="relative flex flex-col p-4 border-dotted border-1 bg-coolgray-100" @class([
 | 
					            class="relative flex flex-col p-4 bg-white box-without-bg dark:bg-coolgray-100" @class([
 | 
				
			||||||
                'border-green-500' => data_get($execution, 'status') === 'success',
 | 
					                'border-green-500' => data_get($execution, 'status') === 'success',
 | 
				
			||||||
                'border-red-500' => data_get($execution, 'status') === 'failed',
 | 
					                'border-red-500' => data_get($execution, 'status') === 'failed',
 | 
				
			||||||
            ])>
 | 
					            ])>
 | 
				
			||||||
@@ -23,7 +23,7 @@
 | 
				
			|||||||
            <div class="flex gap-2">
 | 
					            <div class="flex gap-2">
 | 
				
			||||||
                <div class="flex-1"></div>
 | 
					                <div class="flex-1"></div>
 | 
				
			||||||
                @if (data_get($execution, 'status') === 'success')
 | 
					                @if (data_get($execution, 'status') === 'success')
 | 
				
			||||||
                    <x-forms.button class=" hover:bg-coolgray-400"
 | 
					                    <x-forms.button class=" dark:hover:bg-coolgray-400"
 | 
				
			||||||
                        wire:click="download({{ data_get($execution, 'id') }})">Download</x-forms.button>
 | 
					                        wire:click="download({{ data_get($execution, 'id') }})">Download</x-forms.button>
 | 
				
			||||||
                @endif
 | 
					                @endif
 | 
				
			||||||
                <x-modal-confirmation isErrorButton action="deleteBackup({{ data_get($execution, 'id') }})">
 | 
					                <x-modal-confirmation isErrorButton action="deleteBackup({{ data_get($execution, 'id') }})">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
<div>
 | 
					<div>
 | 
				
			||||||
    <div class="flex items-end gap-2">
 | 
					    <div class="flex items-end gap-2">
 | 
				
			||||||
        <h1>Create a new Application</h1>
 | 
					        <h1>Create a new Application</h1>
 | 
				
			||||||
        <x-forms.button wire:click="saveFromRedirect('source.new')" class="group-hover:dark:text-white">
 | 
					        <x-modal-input buttonTitle="+ Add GitHub App" title="New GitHub App">
 | 
				
			||||||
            + Add New GitHub App
 | 
					            <livewire:source.github.create />
 | 
				
			||||||
        </x-forms.button>
 | 
					        </x-modal-input>
 | 
				
			||||||
        @if ($repositories->count() > 0)
 | 
					        @if ($repositories->count() > 0)
 | 
				
			||||||
            <a target="_blank" class="flex hover:no-underline" href="{{ get_installation_path($github_app) }}">
 | 
					            <a target="_blank" class="flex hover:no-underline" href="{{ get_installation_path($github_app) }}">
 | 
				
			||||||
                <x-forms.button>
 | 
					                <x-forms.button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
<div x-data x-init="$wire.loadServers" x-init="$wire.loadServices">
 | 
					<div x-data x-init="$wire.loadServers">
 | 
				
			||||||
    <div class="flex flex-col gap-4 lg:flex-row ">
 | 
					    <div class="flex flex-col gap-4 lg:flex-row ">
 | 
				
			||||||
        <h1>New Resource</h1>
 | 
					        <h1>New Resource</h1>
 | 
				
			||||||
        <div class="w-full pb-4 lg:w-96 lg:pb-0">
 | 
					        <div class="w-full pb-4 lg:w-96 lg:pb-0">
 | 
				
			||||||
@@ -377,12 +377,12 @@
 | 
				
			|||||||
            <div class="flex items-center gap-4" wire:init='loadServices'>
 | 
					            <div class="flex items-center gap-4" wire:init='loadServices'>
 | 
				
			||||||
                <h2 class="py-4">Services</h2>
 | 
					                <h2 class="py-4">Services</h2>
 | 
				
			||||||
                <x-forms.button wire:click="loadServices('force')">Reload List</x-forms.button>
 | 
					                <x-forms.button wire:click="loadServices('force')">Reload List</x-forms.button>
 | 
				
			||||||
                <input class="input" autofocus wire:model.live.debounce.200ms="search" autofocus
 | 
					 | 
				
			||||||
                    placeholder="Search...">
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="pb-4 text-xs">Trademarks Policy: The respective trademarks mentioned here are owned by the
 | 
					            <div class="pb-4 text-xs">Trademarks Policy: The respective trademarks mentioned here are owned by the
 | 
				
			||||||
                respective
 | 
					                respective
 | 
				
			||||||
                companies, and use of them does not imply any affiliation or endorsement.</div>
 | 
					                companies, and use of them does not imply any affiliation or endorsement.</div>
 | 
				
			||||||
 | 
					            <input class="input" autofocus wire:model.live.debounce.200ms="search" autofocus
 | 
				
			||||||
 | 
					                placeholder="Search...">
 | 
				
			||||||
            @if ($loadingServices)
 | 
					            @if ($loadingServices)
 | 
				
			||||||
                <x-loading text="Loading services..." />
 | 
					                <x-loading text="Loading services..." />
 | 
				
			||||||
            @else
 | 
					            @else
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
<div>
 | 
					<div x-init="$wire.loadPublicKey()">
 | 
				
			||||||
    <x-security.navbar />
 | 
					    <x-security.navbar />
 | 
				
			||||||
    <div x-data="{ showPrivateKey: false }">
 | 
					    <div x-data="{ showPrivateKey: false }">
 | 
				
			||||||
        <form class="flex flex-col gap-2" wire:submit='changePrivateKey'>
 | 
					        <form class="flex flex-col gap-2" wire:submit='changePrivateKey'>
 | 
				
			||||||
@@ -22,11 +22,11 @@
 | 
				
			|||||||
                <x-forms.input readonly id="public_key" />
 | 
					                <x-forms.input readonly id="public_key" />
 | 
				
			||||||
                <div class="flex items-end gap-2 py-2 ">
 | 
					                <div class="flex items-end gap-2 py-2 ">
 | 
				
			||||||
                    <div class="pl-1 ">Private Key <span class='text-helper'>*</span></div>
 | 
					                    <div class="pl-1 ">Private Key <span class='text-helper'>*</span></div>
 | 
				
			||||||
                    <div class="text-xs dark:text-white underline cursor-pointer" x-cloak x-show="!showPrivateKey"
 | 
					                    <div class="text-xs underline cursor-pointer dark:text-white" x-cloak x-show="!showPrivateKey"
 | 
				
			||||||
                        x-on:click="showPrivateKey = true">
 | 
					                        x-on:click="showPrivateKey = true">
 | 
				
			||||||
                        Edit
 | 
					                        Edit
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <div class="text-xs dark:text-white underline cursor-pointer" x-cloak x-show="showPrivateKey"
 | 
					                    <div class="text-xs underline cursor-pointer dark:text-white" x-cloak x-show="showPrivateKey"
 | 
				
			||||||
                        x-on:click="showPrivateKey = false">
 | 
					                        x-on:click="showPrivateKey = false">
 | 
				
			||||||
                        Hide
 | 
					                        Hide
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,165 +1,159 @@
 | 
				
			|||||||
<div>
 | 
					<div>
 | 
				
			||||||
    <x-server.navbar :server="$server" :parameters="$parameters" />
 | 
					    <x-server.navbar :server="$server" :parameters="$parameters" />
 | 
				
			||||||
    @if ($server->isFunctional())
 | 
					    <div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'managed' }" class="flex h-full">
 | 
				
			||||||
        <div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'managed' }" class="flex h-full">
 | 
					        <div class="flex flex-col gap-4">
 | 
				
			||||||
            <div class="flex flex-col gap-4">
 | 
					            <a :class="activeTab === 'managed' && 'dark:text-white'"
 | 
				
			||||||
                <a :class="activeTab === 'managed' && 'dark:text-white'"
 | 
					                @click.prevent="activeTab = 'managed'; window.location.hash = 'managed'" href="#">Managed</a>
 | 
				
			||||||
                    @click.prevent="activeTab = 'managed'; window.location.hash = 'managed'" href="#">Managed</a>
 | 
					            <a :class="activeTab === 'unmanaged' && 'dark:text-white'"
 | 
				
			||||||
                <a :class="activeTab === 'unmanaged' && 'dark:text-white'"
 | 
					                @click.prevent="activeTab = 'unmanaged'; window.location.hash = 'unmanaged'" href="#">Unmanaged</a>
 | 
				
			||||||
                    @click.prevent="activeTab = 'unmanaged'; window.location.hash = 'unmanaged'"
 | 
					        </div>
 | 
				
			||||||
                    href="#">Unmanaged</a>
 | 
					        <div class="w-full pl-8">
 | 
				
			||||||
            </div>
 | 
					            <div x-cloak x-show="activeTab === 'managed'" class="h-full">
 | 
				
			||||||
            <div class="w-full pl-8">
 | 
					                <div class="flex flex-col">
 | 
				
			||||||
                <div x-cloak x-show="activeTab === 'managed'" class="h-full">
 | 
					                    <div class="flex gap-2">
 | 
				
			||||||
 | 
					                        <h2>Resources</h2>
 | 
				
			||||||
 | 
					                        <x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="subtitle">Here you can find all resources that are managed by Coolify.</div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                @if ($server->definedResources()->count() > 0)
 | 
				
			||||||
                    <div class="flex flex-col">
 | 
					                    <div class="flex flex-col">
 | 
				
			||||||
                        <div class="flex gap-2">
 | 
					 | 
				
			||||||
                            <h2>Resources</h2>
 | 
					 | 
				
			||||||
                            <x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div class="subtitle">Here you can find all resources that are managed by Coolify.</div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    @if ($server->definedResources()->count() > 0)
 | 
					 | 
				
			||||||
                        <div class="flex flex-col">
 | 
					                        <div class="flex flex-col">
 | 
				
			||||||
                            <div class="flex flex-col">
 | 
					                            <div class="overflow-x-auto">
 | 
				
			||||||
                                <div class="overflow-x-auto">
 | 
					                                <div class="inline-block min-w-full">
 | 
				
			||||||
                                    <div class="inline-block min-w-full">
 | 
					                                    <div class="overflow-hidden">
 | 
				
			||||||
                                        <div class="overflow-hidden">
 | 
					                                        <table class="min-w-full">
 | 
				
			||||||
                                            <table class="min-w-full divide-y divide-coolgray-400">
 | 
					                                            <thead>
 | 
				
			||||||
                                                <thead>
 | 
					                                                <tr>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Project
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Environment</th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Name
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Type
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Status
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                </tr>
 | 
				
			||||||
 | 
					                                            </thead>
 | 
				
			||||||
 | 
					                                            <tbody>
 | 
				
			||||||
 | 
					                                                @forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource)
 | 
				
			||||||
                                                    <tr>
 | 
					                                                    <tr>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Project
 | 
					                                                            {{ data_get($resource->project(), 'name') }}
 | 
				
			||||||
                                                        </th>
 | 
					                                                        </td>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Environment</th>
 | 
					                                                            {{ data_get($resource, 'environment.name') }}
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        </td>
 | 
				
			||||||
                                                            Name
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap hover:underline">
 | 
				
			||||||
                                                        </th>
 | 
					                                                            <a class=""
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                                href="{{ $resource->link() }}">{{ $resource->name }}
 | 
				
			||||||
                                                            Type
 | 
					                                                                <x-internal-link /></a>
 | 
				
			||||||
                                                        </th>
 | 
					                                                        </td>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Status
 | 
					                                                            {{ str($resource->type())->headline() }}</td>
 | 
				
			||||||
                                                        </th>
 | 
					                                                        <td class="px-5 py-4 text-sm font-medium whitespace-nowrap">
 | 
				
			||||||
 | 
					                                                            @if ($resource->type() === 'service')
 | 
				
			||||||
 | 
					                                                                <x-status.services :service="$resource"
 | 
				
			||||||
 | 
					                                                                    :showRefreshButton="false" />
 | 
				
			||||||
 | 
					                                                            @else
 | 
				
			||||||
 | 
					                                                                <x-status.index :resource="$resource" :showRefreshButton="false" />
 | 
				
			||||||
 | 
					                                                            @endif
 | 
				
			||||||
 | 
					                                                        </td>
 | 
				
			||||||
                                                    </tr>
 | 
					                                                    </tr>
 | 
				
			||||||
                                                </thead>
 | 
					                                                @empty
 | 
				
			||||||
                                                <tbody class="divide-y divide-coolgray-400">
 | 
					                                                @endforelse
 | 
				
			||||||
                                                    @forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource)
 | 
					                                            </tbody>
 | 
				
			||||||
                                                        <tr class="dark:text-white bg-coolblack hover:bg-coolgray-100">
 | 
					                                        </table>
 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                {{ data_get($resource->project(), 'name') }}
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                {{ data_get($resource, 'environment.name') }}
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap"><a
 | 
					 | 
				
			||||||
                                                                    class=""
 | 
					 | 
				
			||||||
                                                                    href="{{ $resource->link() }}">{{ $resource->name }}
 | 
					 | 
				
			||||||
                                                                    <x-internal-link /></a>
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                {{ str($resource->type())->headline() }}</td>
 | 
					 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm font-medium whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                @if ($resource->type() === 'service')
 | 
					 | 
				
			||||||
                                                                    <x-status.services :service="$resource"
 | 
					 | 
				
			||||||
                                                                        :showRefreshButton="false" />
 | 
					 | 
				
			||||||
                                                                @else
 | 
					 | 
				
			||||||
                                                                    <x-status.index :resource="$resource"
 | 
					 | 
				
			||||||
                                                                        :showRefreshButton="false" />
 | 
					 | 
				
			||||||
                                                                @endif
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                        </tr>
 | 
					 | 
				
			||||||
                                                    @empty
 | 
					 | 
				
			||||||
                                                    @endforelse
 | 
					 | 
				
			||||||
                                                </tbody>
 | 
					 | 
				
			||||||
                                            </table>
 | 
					 | 
				
			||||||
                                        </div>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					                                    </div>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    @else
 | 
					 | 
				
			||||||
                        <div>No resources found.</div>
 | 
					 | 
				
			||||||
                    @endif
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div x-cloak x-show="activeTab === 'unmanaged'" class="h-full">
 | 
					 | 
				
			||||||
                    <div class="flex flex-col" x-init="$wire.loadUnmanagedContainers()">
 | 
					 | 
				
			||||||
                        <div class="flex gap-2">
 | 
					 | 
				
			||||||
                            <h2>Resources</h2>
 | 
					 | 
				
			||||||
                            <x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div class="subtitle">Here you can find all other containers running on the server.</div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    @if ($unmanagedContainers->count() > 0)
 | 
					                @else
 | 
				
			||||||
 | 
					                    <div>No resources found.</div>
 | 
				
			||||||
 | 
					                @endif
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div x-cloak x-show="activeTab === 'unmanaged'" class="h-full">
 | 
				
			||||||
 | 
					                <div class="flex flex-col" x-init="$wire.loadUnmanagedContainers()">
 | 
				
			||||||
 | 
					                    <div class="flex gap-2">
 | 
				
			||||||
 | 
					                        <h2>Resources</h2>
 | 
				
			||||||
 | 
					                        <x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="subtitle">Here you can find all other containers running on the server.</div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                @if ($unmanagedContainers->count() > 0)
 | 
				
			||||||
 | 
					                    <div class="flex flex-col">
 | 
				
			||||||
                        <div class="flex flex-col">
 | 
					                        <div class="flex flex-col">
 | 
				
			||||||
                            <div class="flex flex-col">
 | 
					                            <div class="overflow-x-auto">
 | 
				
			||||||
                                <div class="overflow-x-auto">
 | 
					                                <div class="inline-block min-w-full">
 | 
				
			||||||
                                    <div class="inline-block min-w-full">
 | 
					                                    <div class="overflow-hidden">
 | 
				
			||||||
                                        <div class="overflow-hidden">
 | 
					                                        <table class="min-w-full">
 | 
				
			||||||
                                            <table class="min-w-full divide-y divide-coolgray-400">
 | 
					                                            <thead>
 | 
				
			||||||
                                                <thead>
 | 
					                                                <tr>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Name
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Image
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Status
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
 | 
					                                                        Action
 | 
				
			||||||
 | 
					                                                    </th>
 | 
				
			||||||
 | 
					                                                </tr>
 | 
				
			||||||
 | 
					                                            </thead>
 | 
				
			||||||
 | 
					                                            <tbody>
 | 
				
			||||||
 | 
					                                                @forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource)
 | 
				
			||||||
                                                    <tr>
 | 
					                                                    <tr>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Name
 | 
					                                                            {{ data_get($resource, 'Names') }}
 | 
				
			||||||
                                                        </th>
 | 
					                                                        </td>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Image
 | 
					                                                            {{ data_get($resource, 'Image') }}
 | 
				
			||||||
                                                        </th>
 | 
					                                                        </td>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Status
 | 
					                                                            {{ data_get($resource, 'State') }}
 | 
				
			||||||
                                                        </th>
 | 
					                                                        </td>
 | 
				
			||||||
                                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                        <td class="flex gap-2 px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            Action
 | 
					                                                            @if (data_get($resource, 'State') === 'running')
 | 
				
			||||||
                                                        </th>
 | 
					                                                                <x-forms.button
 | 
				
			||||||
 | 
					                                                                    wire:click="restartUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
				
			||||||
 | 
					                                                                    wire:key="{{ data_get($resource, 'ID') }}">Restart</x-forms.button>
 | 
				
			||||||
 | 
					                                                                <x-forms.button isError
 | 
				
			||||||
 | 
					                                                                    wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
				
			||||||
 | 
					                                                                    wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
 | 
				
			||||||
 | 
					                                                            @elseif (data_get($resource, 'State') === 'exited')
 | 
				
			||||||
 | 
					                                                                <x-forms.button
 | 
				
			||||||
 | 
					                                                                    wire:click="startUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
				
			||||||
 | 
					                                                                    wire:key="{{ data_get($resource, 'ID') }}">Start</x-forms.button>
 | 
				
			||||||
 | 
					                                                            @elseif (data_get($resource, 'State') === 'restarting')
 | 
				
			||||||
 | 
					                                                                <x-forms.button
 | 
				
			||||||
 | 
					                                                                    wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
				
			||||||
 | 
					                                                                    wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
 | 
				
			||||||
 | 
					                                                            @endif
 | 
				
			||||||
 | 
					                                                        </td>
 | 
				
			||||||
                                                    </tr>
 | 
					                                                    </tr>
 | 
				
			||||||
                                                </thead>
 | 
					                                                @empty
 | 
				
			||||||
                                                <tbody class="divide-y divide-coolgray-400">
 | 
					                                                @endforelse
 | 
				
			||||||
                                                    @forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource)
 | 
					                                            </tbody>
 | 
				
			||||||
                                                        <tr class="dark:text-white bg-coolblack hover:bg-coolgray-100">
 | 
					                                        </table>
 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                {{ data_get($resource, 'Names') }}
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                {{ data_get($resource, 'Image') }}
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                            <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                {{ data_get($resource, 'State') }}
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                            <td class="flex gap-2 px-5 py-4 text-sm whitespace-nowrap">
 | 
					 | 
				
			||||||
                                                                @if (data_get($resource, 'State') === 'running')
 | 
					 | 
				
			||||||
                                                                    <x-forms.button
 | 
					 | 
				
			||||||
                                                                        wire:click="restartUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
					 | 
				
			||||||
                                                                        wire:key="{{ data_get($resource, 'ID') }}">Restart</x-forms.button>
 | 
					 | 
				
			||||||
                                                                    <x-forms.button isError
 | 
					 | 
				
			||||||
                                                                        wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
					 | 
				
			||||||
                                                                        wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
 | 
					 | 
				
			||||||
                                                                @elseif (data_get($resource, 'State') === 'exited')
 | 
					 | 
				
			||||||
                                                                    <x-forms.button
 | 
					 | 
				
			||||||
                                                                        wire:click="startUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
					 | 
				
			||||||
                                                                        wire:key="{{ data_get($resource, 'ID') }}">Start</x-forms.button>
 | 
					 | 
				
			||||||
                                                                @elseif (data_get($resource, 'State') === 'restarting')
 | 
					 | 
				
			||||||
                                                                    <x-forms.button
 | 
					 | 
				
			||||||
                                                                        wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
 | 
					 | 
				
			||||||
                                                                        wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
 | 
					 | 
				
			||||||
                                                                @endif
 | 
					 | 
				
			||||||
                                                            </td>
 | 
					 | 
				
			||||||
                                                        </tr>
 | 
					 | 
				
			||||||
                                                    @empty
 | 
					 | 
				
			||||||
                                                    @endforelse
 | 
					 | 
				
			||||||
                                                </tbody>
 | 
					 | 
				
			||||||
                                            </table>
 | 
					 | 
				
			||||||
                                        </div>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					                                    </div>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    @else
 | 
					                    </div>
 | 
				
			||||||
                        <div>No resources found.</div>
 | 
					                @else
 | 
				
			||||||
                    @endif
 | 
					                    <div>No resources found.</div>
 | 
				
			||||||
                </div>
 | 
					                @endif
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    @else
 | 
					    </div>
 | 
				
			||||||
        <div>Server is not validated. Validate first.</div>
 | 
					 | 
				
			||||||
    @endif
 | 
					 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,7 +107,7 @@
 | 
				
			|||||||
                            <div class="overflow-x-auto">
 | 
					                            <div class="overflow-x-auto">
 | 
				
			||||||
                                <div class="inline-block min-w-full">
 | 
					                                <div class="inline-block min-w-full">
 | 
				
			||||||
                                    <div class="overflow-hidden">
 | 
					                                    <div class="overflow-hidden">
 | 
				
			||||||
                                        <table class="min-w-full divide-y divide-coolgray-400">
 | 
					                                        <table class="min-w-full">
 | 
				
			||||||
                                            <thead>
 | 
					                                            <thead>
 | 
				
			||||||
                                                <tr>
 | 
					                                                <tr>
 | 
				
			||||||
                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
					                                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">
 | 
				
			||||||
@@ -121,9 +121,9 @@
 | 
				
			|||||||
                                                    </th>
 | 
					                                                    </th>
 | 
				
			||||||
                                                </tr>
 | 
					                                                </tr>
 | 
				
			||||||
                                            </thead>
 | 
					                                            </thead>
 | 
				
			||||||
                                            <tbody class="divide-y divide-coolgray-400">
 | 
					                                            <tbody class="divide-y">
 | 
				
			||||||
                                                @forelse ($applications->sortBy('name',SORT_NATURAL) as $resource)
 | 
					                                                @forelse ($applications->sortBy('name',SORT_NATURAL) as $resource)
 | 
				
			||||||
                                                    <tr class="dark:text-white bg-coolblack hover:bg-coolgray-100">
 | 
					                                                    <tr>
 | 
				
			||||||
                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
					                                                        <td class="px-5 py-4 text-sm whitespace-nowrap">
 | 
				
			||||||
                                                            {{ data_get($resource->project(), 'name') }}
 | 
					                                                            {{ data_get($resource->project(), 'name') }}
 | 
				
			||||||
                                                        </td>
 | 
					                                                        </td>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
                <div class="overflow-x-auto">
 | 
					                <div class="overflow-x-auto">
 | 
				
			||||||
                    <div class="inline-block min-w-full">
 | 
					                    <div class="inline-block min-w-full">
 | 
				
			||||||
                        <div class="overflow-hidden">
 | 
					                        <div class="overflow-hidden">
 | 
				
			||||||
                            <table class="min-w-full divide-y divide-coolgray-400">
 | 
					                            <table class="min-w-full">
 | 
				
			||||||
                                <thead>
 | 
					                                <thead>
 | 
				
			||||||
                                    <tr>
 | 
					                                    <tr>
 | 
				
			||||||
                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">Email
 | 
					                                        <th class="px-5 py-3 text-xs font-medium text-left uppercase">Email
 | 
				
			||||||
@@ -20,9 +20,9 @@
 | 
				
			|||||||
                                        </th>
 | 
					                                        </th>
 | 
				
			||||||
                                    </tr>
 | 
					                                    </tr>
 | 
				
			||||||
                                </thead>
 | 
					                                </thead>
 | 
				
			||||||
                                <tbody class="divide-y divide-coolgray-400">
 | 
					                                <tbody>
 | 
				
			||||||
                                    @foreach ($invitations as $invite)
 | 
					                                    @foreach ($invitations as $invite)
 | 
				
			||||||
                                        <tr class="dark:text-white bg-coolblack hover:bg-coolgray-100/40">
 | 
					                                        <tr>
 | 
				
			||||||
                                            <td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->email }}</td>
 | 
					                                            <td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->email }}</td>
 | 
				
			||||||
                                            <td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->via }}</td>
 | 
					                                            <td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->via }}</td>
 | 
				
			||||||
                                            <td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->role }}</td>
 | 
					                                            <td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->role }}</td>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
            <div class="overflow-x-auto">
 | 
					            <div class="overflow-x-auto">
 | 
				
			||||||
                <div class="inline-block min-w-full">
 | 
					                <div class="inline-block min-w-full">
 | 
				
			||||||
                    <div class="overflow-hidden">
 | 
					                    <div class="overflow-hidden">
 | 
				
			||||||
                        <table class="min-w-full divide-y dark:divide-coolgray-400 divide-neutral-400">
 | 
					                        <table class="min-w-full">
 | 
				
			||||||
                            <thead>
 | 
					                            <thead>
 | 
				
			||||||
                                <tr>
 | 
					                                <tr>
 | 
				
			||||||
                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">Name
 | 
					                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">Name
 | 
				
			||||||
@@ -17,7 +17,7 @@
 | 
				
			|||||||
                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">Actions</th>
 | 
					                                    <th class="px-5 py-3 text-xs font-medium text-left uppercase">Actions</th>
 | 
				
			||||||
                                </tr>
 | 
					                                </tr>
 | 
				
			||||||
                            </thead>
 | 
					                            </thead>
 | 
				
			||||||
                            <tbody class="divide-y dark:divide-coolgray-400 divide-neutral-200">
 | 
					                            <tbody>
 | 
				
			||||||
                                @foreach (currentTeam()->members as $member)
 | 
					                                @foreach (currentTeam()->members as $member)
 | 
				
			||||||
                                    <livewire:team.member :member="$member" :wire:key="$member->id" />
 | 
					                                    <livewire:team.member :member="$member" :wire:key="$member->id" />
 | 
				
			||||||
                                @endforeach
 | 
					                                @endforeach
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "coolify": {
 | 
					    "coolify": {
 | 
				
			||||||
        "v4": {
 | 
					        "v4": {
 | 
				
			||||||
            "version": "4.0.0-beta.248"
 | 
					            "version": "4.0.0-beta.249"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user