improve boarding
This commit is contained in:
		@@ -43,6 +43,7 @@ class ProjectController extends Controller
 | 
			
		||||
    {
 | 
			
		||||
        $type = request()->query('type');
 | 
			
		||||
        $destination_uuid = request()->query('destination');
 | 
			
		||||
        $server = requesT()->query('server');
 | 
			
		||||
 | 
			
		||||
        $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
 | 
			
		||||
        if (!$project) {
 | 
			
		||||
@@ -59,6 +60,9 @@ class ProjectController extends Controller
 | 
			
		||||
                'environment_name' => $environment->name,
 | 
			
		||||
                'database_uuid' => $standalone_postgresql->uuid,
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
        if ($server) {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        return view('project.new', [
 | 
			
		||||
            'type' => $type
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ use App\Actions\Server\InstallDocker;
 | 
			
		||||
use App\Models\PrivateKey;
 | 
			
		||||
use App\Models\Project;
 | 
			
		||||
use App\Models\Server;
 | 
			
		||||
use Illuminate\Database\Eloquent\Collection;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
 | 
			
		||||
class Index extends Component
 | 
			
		||||
@@ -22,6 +22,8 @@ class Index extends Component
 | 
			
		||||
    public ?string $privateKeyDescription = null;
 | 
			
		||||
    public ?PrivateKey $createdPrivateKey = null;
 | 
			
		||||
 | 
			
		||||
    public ?Collection $servers = null;
 | 
			
		||||
    public ?int $selectedExistingServer = null;
 | 
			
		||||
    public ?string $remoteServerName = null;
 | 
			
		||||
    public ?string $remoteServerDescription = null;
 | 
			
		||||
    public ?string $remoteServerHost = null;
 | 
			
		||||
@@ -29,6 +31,8 @@ class Index extends Component
 | 
			
		||||
    public ?string $remoteServerUser = 'root';
 | 
			
		||||
    public ?Server $createdServer = null;
 | 
			
		||||
 | 
			
		||||
    public Collection|array $projects = [];
 | 
			
		||||
    public ?int $selectedExistingProject = null;
 | 
			
		||||
    public ?Project $createdProject = null;
 | 
			
		||||
 | 
			
		||||
    public function mount()
 | 
			
		||||
@@ -66,25 +70,62 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
 | 
			
		||||
        refreshSession();
 | 
			
		||||
        return redirect()->route('dashboard');
 | 
			
		||||
    }
 | 
			
		||||
    public function setServer(string $type)
 | 
			
		||||
 | 
			
		||||
    public function setServerType(string $type)
 | 
			
		||||
    {
 | 
			
		||||
        if ($type === 'localhost') {
 | 
			
		||||
            $this->createdServer = Server::find(0);
 | 
			
		||||
            if (!$this->createdServer) {
 | 
			
		||||
                return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.');
 | 
			
		||||
            }
 | 
			
		||||
            $this->currentState = 'select-proxy';
 | 
			
		||||
            return $this->validateServer();
 | 
			
		||||
        } elseif ($type === 'remote') {
 | 
			
		||||
            $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->get();
 | 
			
		||||
            $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
 | 
			
		||||
            if ($this->privateKeys->count() > 0) {
 | 
			
		||||
                $this->selectedExistingPrivateKey = $this->privateKeys->first()->id;
 | 
			
		||||
            }
 | 
			
		||||
            $this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
 | 
			
		||||
            if ($this->servers->count() > 0) {
 | 
			
		||||
                $this->selectedExistingServer = $this->servers->first()->id;
 | 
			
		||||
                $this->currentState = 'select-existing-server';
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            $this->currentState = 'private-key';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function selectExistingServer()
 | 
			
		||||
    {
 | 
			
		||||
        $this->createdServer = Server::find($this->selectedExistingServer);
 | 
			
		||||
        if (!$this->createdServer) {
 | 
			
		||||
            $this->emit('error', 'Server is not found.');
 | 
			
		||||
            $this->currentState = 'private-key';
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        $this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
 | 
			
		||||
        $this->validateServer();
 | 
			
		||||
        $this->getProxyType();
 | 
			
		||||
        $this->getProjects();
 | 
			
		||||
    }
 | 
			
		||||
    public function getProxyType() {
 | 
			
		||||
        $proxyTypeSet = $this->createdServer->proxy->type;
 | 
			
		||||
        if (!$proxyTypeSet) {
 | 
			
		||||
            $this->currentState = 'select-proxy';
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        $this->getProjects();
 | 
			
		||||
    }
 | 
			
		||||
    public function selectExistingPrivateKey()
 | 
			
		||||
    {
 | 
			
		||||
        ray($this->selectedExistingPrivateKey);
 | 
			
		||||
        $this->currentState = 'create-server';
 | 
			
		||||
    }
 | 
			
		||||
    public function createNewServer()
 | 
			
		||||
    {
 | 
			
		||||
        $this->selectedExistingServer = null;
 | 
			
		||||
        $this->currentState = 'private-key';
 | 
			
		||||
    }
 | 
			
		||||
    public function setPrivateKey(string $type)
 | 
			
		||||
    {
 | 
			
		||||
        $this->selectedExistingPrivateKey = null;
 | 
			
		||||
        $this->privateKeyType = $type;
 | 
			
		||||
        if ($type === 'create' && !isDev()) {
 | 
			
		||||
            $this->createNewPrivateKey();
 | 
			
		||||
@@ -123,11 +164,12 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
 | 
			
		||||
            'private_key_id' => $this->createdPrivateKey->id,
 | 
			
		||||
            'team_id' => currentTeam()->id
 | 
			
		||||
        ]);
 | 
			
		||||
        $this->validateServer();
 | 
			
		||||
    }
 | 
			
		||||
    public function validateServer() {
 | 
			
		||||
        try {
 | 
			
		||||
            ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->createdServer);
 | 
			
		||||
            if (!$uptime) {
 | 
			
		||||
                $this->createdServer->delete();
 | 
			
		||||
                $this->createdPrivateKey->delete();
 | 
			
		||||
                throw new \Exception('Server is not reachable.');
 | 
			
		||||
            } else {
 | 
			
		||||
                $this->createdServer->settings->update([
 | 
			
		||||
@@ -135,11 +177,14 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
 | 
			
		||||
                ]);
 | 
			
		||||
                $this->emit('success', 'Server is reachable.');
 | 
			
		||||
            }
 | 
			
		||||
            if ($dockerVersion) {
 | 
			
		||||
            ray($dockerVersion, $uptime);
 | 
			
		||||
            if (!$dockerVersion) {
 | 
			
		||||
                $this->emit('error', 'Docker is not installed on the server.');
 | 
			
		||||
                $this->currentState = 'install-docker';
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            $this->getProxyType();
 | 
			
		||||
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
 | 
			
		||||
        }
 | 
			
		||||
@@ -153,13 +198,25 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
 | 
			
		||||
    public function selectProxy(string|null $proxyType = null)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$proxyType) {
 | 
			
		||||
            return $this->currentState = 'create-project';
 | 
			
		||||
            return $this->getProjects();
 | 
			
		||||
        }
 | 
			
		||||
        $this->createdServer->proxy->type = $proxyType;
 | 
			
		||||
        $this->createdServer->proxy->status = 'exited';
 | 
			
		||||
        $this->createdServer->save();
 | 
			
		||||
        $this->getProjects();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getProjects() {
 | 
			
		||||
        $this->projects = Project::ownedByCurrentTeam(['name'])->get();
 | 
			
		||||
        if ($this->projects->count() > 0) {
 | 
			
		||||
            $this->selectedExistingProject = $this->projects->first()->id;
 | 
			
		||||
        }
 | 
			
		||||
        $this->currentState = 'create-project';
 | 
			
		||||
    }
 | 
			
		||||
    public function selectExistingProject() {
 | 
			
		||||
        $this->createdProject = Project::find($this->selectedExistingProject);
 | 
			
		||||
        $this->currentState = 'create-resource';
 | 
			
		||||
    }
 | 
			
		||||
    public function createNewProject()
 | 
			
		||||
    {
 | 
			
		||||
        $this->createdProject = Project::create([
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,12 @@ namespace App\Http\Livewire\Project\New;
 | 
			
		||||
use App\Models\Server;
 | 
			
		||||
use Countable;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
use Route;
 | 
			
		||||
 | 
			
		||||
class Select extends Component
 | 
			
		||||
{
 | 
			
		||||
    public $current_step = 'type';
 | 
			
		||||
    public ?int $server = null;
 | 
			
		||||
    public string $type;
 | 
			
		||||
    public string $server_id;
 | 
			
		||||
    public string $destination_uuid;
 | 
			
		||||
@@ -16,6 +18,9 @@ class Select extends Component
 | 
			
		||||
    public $destinations = [];
 | 
			
		||||
    public array $parameters;
 | 
			
		||||
 | 
			
		||||
    protected $queryString = [
 | 
			
		||||
        'server',
 | 
			
		||||
    ];
 | 
			
		||||
    public function mount()
 | 
			
		||||
    {
 | 
			
		||||
        $this->parameters = get_route_parameters();
 | 
			
		||||
@@ -31,6 +36,12 @@ class Select extends Component
 | 
			
		||||
                $this->set_destination($server->destinations()->first()->uuid);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!is_null($this->server )) {
 | 
			
		||||
            $foundServer = $this->servers->where('id', $this->server)->first();
 | 
			
		||||
            if ($foundServer) {
 | 
			
		||||
                return $this->set_server($foundServer);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $this->current_step = 'servers';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ use App\Models\Server;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
use Masmerise\Toaster\Toaster;
 | 
			
		||||
 | 
			
		||||
class PrivateKey extends Component
 | 
			
		||||
class ShowPrivateKey extends Component
 | 
			
		||||
{
 | 
			
		||||
    public Server $server;
 | 
			
		||||
    public $privateKeys;
 | 
			
		||||
@@ -1,198 +1,279 @@
 | 
			
		||||
@php use App\Enums\ProxyTypes; @endphp
 | 
			
		||||
<div>
 | 
			
		||||
    @if ($currentState === 'welcome')
 | 
			
		||||
        <h1 class="text-5xl font-bold">Welcome to Coolify</h1>
 | 
			
		||||
        <p class="py-6 text-xl text-center">Let me help you to set the basics.</p>
 | 
			
		||||
        <div class="flex justify-center ">
 | 
			
		||||
            <div class="justify-center box" wire:click="$set('currentState', 'select-server')">Get Started
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'welcome')
 | 
			
		||||
            <h1 class="text-5xl font-bold">Welcome to Coolify</h1>
 | 
			
		||||
            <p class="py-6 text-xl text-center">Let me help you to set the basics.</p>
 | 
			
		||||
            <div class="flex justify-center ">
 | 
			
		||||
                <div class="justify-center box" wire:click="$set('currentState', 'select-server-type')">Get Started
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'select-server')
 | 
			
		||||
        <x-boarding-step title="Server">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                Do you want to deploy your resources on your <x-highlighted text="Localhost" />
 | 
			
		||||
                or on a <x-highlighted text="Remote Server" />?
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <div class="justify-center box" wire:click="setServer('localhost')">Localhost
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="justify-center box" wire:click="setServer('remote')">Remote Server
 | 
			
		||||
                </div>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>Servers are the main building blocks, as they will host your applications, databases,
 | 
			
		||||
                    services, called resources. Any CPU intensive process will use the server's CPU where you
 | 
			
		||||
                    are deploying your resources.</p>
 | 
			
		||||
                <p>Localhost is the server where Coolify is running on. It is not recommended to use one server
 | 
			
		||||
                    for everyting.</p>
 | 
			
		||||
                <p>Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud
 | 
			
		||||
                    provider.</p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'private-key')
 | 
			
		||||
        <x-boarding-step title="SSH Key">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                Do you have your own SSH Private Key?
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <div class="justify-center box" wire:click="setPrivateKey('own')">Yes
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="justify-center box" wire:click="setPrivateKey('create')">No (create one for me)
 | 
			
		||||
                </div>
 | 
			
		||||
                <form wire:submit.prevent='selectExistingPrivateKey'>
 | 
			
		||||
                    <x-forms.select wire:model.defer='selectedExistingPrivateKey'>
 | 
			
		||||
                        @foreach ($privateKeys as $privateKey)
 | 
			
		||||
                            <option value="{{ $privateKey->id }}">{{ $privateKey->name }}</option>
 | 
			
		||||
                        @endforeach
 | 
			
		||||
                    </x-forms.select>
 | 
			
		||||
                    <x-forms.button type="submit">Select this</x-forms.button>
 | 
			
		||||
                </form>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>SSH Keys are used to connect to a remote server through a secure shell, called SSH.</p>
 | 
			
		||||
                <p>You can use your own ssh private key, or you can let Coolify to create one for you.</p>
 | 
			
		||||
                <p>In both ways, you need to add the public version of your ssh private key to the remote
 | 
			
		||||
                    server's
 | 
			
		||||
                    <code class="text-warning">~/.ssh/authorized_keys</code> file.
 | 
			
		||||
                </p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'create-private-key')
 | 
			
		||||
        <x-boarding-step title="Create Private Key">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                Please let me know your key details.
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <form wire:submit.prevent='savePrivateKey' class="flex flex-col w-full gap-4 pr-10">
 | 
			
		||||
                    <x-forms.input required placeholder="Choose a name for your Private Key. Could be anything."
 | 
			
		||||
                        label="Name" id="privateKeyName" />
 | 
			
		||||
                    <x-forms.input placeholder="Description, so others will know more about this." label="Description"
 | 
			
		||||
                        id="privateKeyDescription" />
 | 
			
		||||
                    <x-forms.textarea required placeholder="-----BEGIN OPENSSH PRIVATE KEY-----" label="Private Key"
 | 
			
		||||
                        id="privateKey" />
 | 
			
		||||
                    @if ($privateKeyType === 'create' && !isDev())
 | 
			
		||||
                        <span class="font-bold text-warning">Copy this to your server's ~/.ssh/authorized_keys
 | 
			
		||||
                            file.</span>
 | 
			
		||||
                        <x-forms.textarea rows="7" readonly label="Public Key" id="publicKey" />
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'select-server-type')
 | 
			
		||||
            <x-boarding-step title="Server">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    Do you want to deploy your resources on your <x-highlighted text="Localhost" />
 | 
			
		||||
                    or on a <x-highlighted text="Remote Server" />?
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <div class="justify-center box" wire:click="setServerType('localhost')">Localhost
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="justify-center box" wire:click="setServerType('remote')">Remote Server
 | 
			
		||||
                    </div>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>Servers are the main building blocks, as they will host your applications, databases,
 | 
			
		||||
                        services, called resources. Any CPU intensive process will use the server's CPU where you
 | 
			
		||||
                        are deploying your resources.</p>
 | 
			
		||||
                    <p>Localhost is the server where Coolify is running on. It is not recommended to use one server
 | 
			
		||||
                        for everyting.</p>
 | 
			
		||||
                    <p>Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud
 | 
			
		||||
                        provider.</p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'private-key')
 | 
			
		||||
            <x-boarding-step title="SSH Key">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    Do you have your own SSH Private Key?
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <div class="justify-center box" wire:click="setPrivateKey('own')">Yes
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="justify-center box" wire:click="setPrivateKey('create')">No (create one for me)
 | 
			
		||||
                    </div>
 | 
			
		||||
                    @if (count($privateKeys) > 0)
 | 
			
		||||
                        <form wire:submit.prevent='selectExistingPrivateKey' class="flex flex-col w-full gap-4 pr-10">
 | 
			
		||||
                            <x-forms.select label="Existing SSH Keys" id='selectedExistingPrivateKey'>
 | 
			
		||||
                                @foreach ($privateKeys as $privateKey)
 | 
			
		||||
                                    <option wire:key="{{ $loop->index }}" value="{{ $privateKey->id }}">
 | 
			
		||||
                                        {{ $privateKey->name }}</option>
 | 
			
		||||
                                @endforeach
 | 
			
		||||
                            </x-forms.select>
 | 
			
		||||
                            <x-forms.button type="submit">Use this SSH Key</x-forms.button>
 | 
			
		||||
                        </form>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    <x-forms.button type="submit">Save</x-forms.button>
 | 
			
		||||
                </form>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p>
 | 
			
		||||
                <p>You can use your own private key, or you can let Coolify to create one for you.</p>
 | 
			
		||||
                <p>In both ways, you need to add the public version of your private key to the remote server's
 | 
			
		||||
                    <code>~/.ssh/authorized_keys</code> file.
 | 
			
		||||
                </p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'create-server')
 | 
			
		||||
        <x-boarding-step title="Create Server">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                Please let me know your server details.
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <form wire:submit.prevent='saveServer' class="flex flex-col w-full gap-4 pr-10">
 | 
			
		||||
                    <div class="flex gap-2">
 | 
			
		||||
                        <x-forms.input required placeholder="Choose a name for your Server. Could be anything."
 | 
			
		||||
                            label="Name" id="remoteServerName" />
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>SSH Keys are used to connect to a remote server through a secure shell, called SSH.</p>
 | 
			
		||||
                    <p>You can use your own ssh private key, or you can let Coolify to create one for you.</p>
 | 
			
		||||
                    <p>In both ways, you need to add the public version of your ssh private key to the remote
 | 
			
		||||
                        server's
 | 
			
		||||
                        <code class="text-warning">~/.ssh/authorized_keys</code> file.
 | 
			
		||||
                    </p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'select-existing-server')
 | 
			
		||||
            <x-boarding-step title="Select a server">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    There are already servers available for your Team. Do you want to use one of them?
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <div class="justify-center box" wire:click="createNewServer">No (create a new one)
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div>
 | 
			
		||||
                        <form wire:submit.prevent='selectExistingServer' class="flex flex-col w-full gap-4 lg:w-96">
 | 
			
		||||
                            <x-forms.select label="Existing servers" class="w-96" id='selectedExistingServer'>
 | 
			
		||||
                                @foreach ($servers as $server)
 | 
			
		||||
                                    <option wire:key="{{ $loop->index }}" value="{{ $server->id }}">
 | 
			
		||||
                                        {{ $server->name }}</option>
 | 
			
		||||
                                @endforeach
 | 
			
		||||
                            </x-forms.select>
 | 
			
		||||
                            <x-forms.button type="submit">Use this Server</x-forms.button>
 | 
			
		||||
                        </form>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p>
 | 
			
		||||
                    <p>You can use your own private key, or you can let Coolify to create one for you.</p>
 | 
			
		||||
                    <p>In both ways, you need to add the public version of your private key to the remote server's
 | 
			
		||||
                        <code>~/.ssh/authorized_keys</code> file.
 | 
			
		||||
                    </p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'create-private-key')
 | 
			
		||||
            <x-boarding-step title="Create Private Key">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    Please let me know your key details.
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <form wire:submit.prevent='savePrivateKey' class="flex flex-col w-full gap-4 pr-10">
 | 
			
		||||
                        <x-forms.input required placeholder="Choose a name for your Private Key. Could be anything."
 | 
			
		||||
                            label="Name" id="privateKeyName" />
 | 
			
		||||
                        <x-forms.input placeholder="Description, so others will know more about this."
 | 
			
		||||
                            label="Description" id="remoteServerDescription" />
 | 
			
		||||
                            label="Description" id="privateKeyDescription" />
 | 
			
		||||
                        <x-forms.textarea required placeholder="-----BEGIN OPENSSH PRIVATE KEY-----" label="Private Key"
 | 
			
		||||
                            id="privateKey" />
 | 
			
		||||
                        @if ($privateKeyType === 'create' && !isDev())
 | 
			
		||||
                            <span class="font-bold text-warning">Copy this to your server's ~/.ssh/authorized_keys
 | 
			
		||||
                                file.</span>
 | 
			
		||||
                            <x-forms.textarea rows="7" readonly label="Public Key" id="publicKey" />
 | 
			
		||||
                        @endif
 | 
			
		||||
                        <x-forms.button type="submit">Save</x-forms.button>
 | 
			
		||||
                    </form>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p>
 | 
			
		||||
                    <p>You can use your own private key, or you can let Coolify to create one for you.</p>
 | 
			
		||||
                    <p>In both ways, you need to add the public version of your private key to the remote server's
 | 
			
		||||
                        <code>~/.ssh/authorized_keys</code> file.
 | 
			
		||||
                    </p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'create-server')
 | 
			
		||||
            <x-boarding-step title="Create Server">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    Please let me know your server details.
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <form wire:submit.prevent='saveServer' class="flex flex-col w-full gap-4 pr-10">
 | 
			
		||||
                        <div class="flex gap-2">
 | 
			
		||||
                            <x-forms.input required placeholder="Choose a name for your Server. Could be anything."
 | 
			
		||||
                                label="Name" id="remoteServerName" />
 | 
			
		||||
                            <x-forms.input placeholder="Description, so others will know more about this."
 | 
			
		||||
                                label="Description" id="remoteServerDescription" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="flex gap-2">
 | 
			
		||||
                            <x-forms.input required placeholder="Hostname or IP address" label="Hostname or IP Address"
 | 
			
		||||
                                id="remoteServerHost" />
 | 
			
		||||
                            <x-forms.input required placeholder="Port number of your server. Default is 22."
 | 
			
		||||
                                label="Port" id="remoteServerPort" />
 | 
			
		||||
                            <x-forms.input required readonly
 | 
			
		||||
                                placeholder="Username to connect to your server. Default is root." label="Username"
 | 
			
		||||
                                id="remoteServerUser" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <x-forms.button type="submit">Save</x-forms.button>
 | 
			
		||||
                    </form>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>Username should be <x-highlighted text="root" /> for now. We are working on to use
 | 
			
		||||
                        non-root users.</p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'install-docker')
 | 
			
		||||
            <x-modal modalId="installDocker">
 | 
			
		||||
                <x-slot:modalBody>
 | 
			
		||||
                    <livewire:activity-monitor header="Docker Installation Logs" />
 | 
			
		||||
                </x-slot:modalBody>
 | 
			
		||||
                <x-slot:modalSubmit>
 | 
			
		||||
                    <x-forms.button onclick="installDocker.close()" type="submit">
 | 
			
		||||
                        Close
 | 
			
		||||
                    </x-forms.button>
 | 
			
		||||
                </x-slot:modalSubmit>
 | 
			
		||||
            </x-modal>
 | 
			
		||||
            <x-boarding-step title="Install Docker">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    Could not find Docker Engine on your server. Do you want me to install it for you?
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <div class="justify-center box" wire:click="installDocker" onclick="installDocker.showModal()">
 | 
			
		||||
                        Let's do
 | 
			
		||||
                        it!</div>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>This will install the latest Docker Engine on your server, configure a few things to be able
 | 
			
		||||
                        to run optimal.</p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'select-proxy')
 | 
			
		||||
            <x-boarding-step title="Select a Proxy">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    If you would like to attach any kind of domain to your resources, you need a proxy.
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <x-forms.button wire:click="selectProxy" class="w-64 box">
 | 
			
		||||
                        Decide later
 | 
			
		||||
                    </x-forms.button>
 | 
			
		||||
                    <x-forms.button class="w-32 box" wire:click="selectProxy('{{ ProxyTypes::TRAEFIK_V2 }}')">
 | 
			
		||||
                        Traefik
 | 
			
		||||
                        v2
 | 
			
		||||
                    </x-forms.button>
 | 
			
		||||
                    <x-forms.button disabled class="w-32 box">
 | 
			
		||||
                        Nginx
 | 
			
		||||
                    </x-forms.button>
 | 
			
		||||
                    <x-forms.button disabled class="w-32 box">
 | 
			
		||||
                        Caddy
 | 
			
		||||
                    </x-forms.button>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>This will install the latest Docker Engine on your server, configure a few things to be able
 | 
			
		||||
                        to run optimal.</p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'create-project')
 | 
			
		||||
            <x-boarding-step title="Project">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    @if (count($projects) > 0)
 | 
			
		||||
                        You already have some projects. Do you want to use one of them or should I create a new one for
 | 
			
		||||
                        you?
 | 
			
		||||
                    @else
 | 
			
		||||
                        I will create an initial project for you. You can change all the details later on.
 | 
			
		||||
                    @endif
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <div class="justify-center box" wire:click="createNewProject">Let's create a new one!</div>
 | 
			
		||||
                    <div>
 | 
			
		||||
                        @if (count($projects) > 0)
 | 
			
		||||
                            <form wire:submit.prevent='selectExistingProject'
 | 
			
		||||
                                class="flex flex-col w-full gap-4 lg:w-96">
 | 
			
		||||
                                <x-forms.select label="Existing projects" class="w-96" id='selectedExistingProject'>
 | 
			
		||||
                                    @foreach ($projects as $project)
 | 
			
		||||
                                        <option wire:key="{{ $loop->index }}" value="{{ $project->id }}">
 | 
			
		||||
                                            {{ $project->name }}</option>
 | 
			
		||||
                                    @endforeach
 | 
			
		||||
                                </x-forms.select>
 | 
			
		||||
                                <x-forms.button type="submit">Use this Project</x-forms.button>
 | 
			
		||||
                            </form>
 | 
			
		||||
                        @endif
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="flex gap-2">
 | 
			
		||||
                        <x-forms.input required placeholder="Hostname or IP address" label="Hostname or IP Address"
 | 
			
		||||
                            id="remoteServerHost" />
 | 
			
		||||
                        <x-forms.input required placeholder="Port number of your server. Default is 22." label="Port"
 | 
			
		||||
                            id="remoteServerPort" />
 | 
			
		||||
                        <x-forms.input required readonly
 | 
			
		||||
                            placeholder="Username to connect to your server. Default is root." label="Username"
 | 
			
		||||
                            id="remoteServerUser" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <x-forms.button type="submit">Save</x-forms.button>
 | 
			
		||||
                </form>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>Username should be <x-highlighted text="root" /> for now. We are working on to use
 | 
			
		||||
                    non-root users.</p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'install-docker')
 | 
			
		||||
        <x-boarding-step title="Install Docker">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                Could not find Docker Engine on your server. Do you want me to install it for you?
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <div class="justify-center box" wire:click="installDocker" onclick="installDocker.showModal()">
 | 
			
		||||
                    Let's do
 | 
			
		||||
                    it!</div>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>This will install the latest Docker Engine on your server, configure a few things to be able
 | 
			
		||||
                    to run optimal.</p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'select-proxy')
 | 
			
		||||
        <x-boarding-step title="Select a Proxy">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                If you would like to attach any kind of domain to your resources, you need a proxy.
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <x-forms.button wire:click="selectProxy" class="w-64 box">
 | 
			
		||||
                    Decide later
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
                <x-forms.button class="w-32 box" wire:click="selectProxy('{{ ProxyTypes::TRAEFIK_V2 }}')">
 | 
			
		||||
                    Traefik
 | 
			
		||||
                    v2
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
                <x-forms.button disabled class="w-32 box">
 | 
			
		||||
                    Nginx
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
                <x-forms.button disabled class="w-32 box">
 | 
			
		||||
                    Caddy
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>This will install the latest Docker Engine on your server, configure a few things to be able
 | 
			
		||||
                    to run optimal.</p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'create-project')
 | 
			
		||||
        <x-boarding-step title="Project">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                I will create an initial project for you. You can change all the details later on.
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <div class="justify-center box" wire:click="createNewProject">Let's do it!</div>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>Projects are bound together several resources into one virtual group. There are no
 | 
			
		||||
                    limitations on the number of projects you could have.</p>
 | 
			
		||||
                <p>Each project should have at least one environment. This helps you to create a production &
 | 
			
		||||
                    staging version of the same application, but grouped separately.</p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if ($currentState === 'create-resource')
 | 
			
		||||
        <x-boarding-step title="Resources">
 | 
			
		||||
            <x-slot:question>
 | 
			
		||||
                I will redirect you to the new resource page, where you can create your first resource.
 | 
			
		||||
            </x-slot:question>
 | 
			
		||||
            <x-slot:actions>
 | 
			
		||||
                <div class="justify-center box" wire:click="showNewResource">Let's do
 | 
			
		||||
                    it!</div>
 | 
			
		||||
            </x-slot:actions>
 | 
			
		||||
            <x-slot:explanation>
 | 
			
		||||
                <p>A resource could be an application, a database or a service (like WordPress).</p>
 | 
			
		||||
            </x-slot:explanation>
 | 
			
		||||
        </x-boarding-step>
 | 
			
		||||
    @endif
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>Projects are bound together several resources into one virtual group. There are no
 | 
			
		||||
                        limitations on the number of projects you could have.</p>
 | 
			
		||||
                    <p>Each project should have at least one environment. This helps you to create a production &
 | 
			
		||||
                        staging version of the same application, but grouped separately.</p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
        @if ($currentState === 'create-resource')
 | 
			
		||||
            <x-boarding-step title="Resources">
 | 
			
		||||
                <x-slot:question>
 | 
			
		||||
                    I will redirect you to the new resource page, where you can create your first resource.
 | 
			
		||||
                </x-slot:question>
 | 
			
		||||
                <x-slot:actions>
 | 
			
		||||
                    <div class="justify-center box" wire:click="showNewResource">Let's do
 | 
			
		||||
                        it!</div>
 | 
			
		||||
                </x-slot:actions>
 | 
			
		||||
                <x-slot:explanation>
 | 
			
		||||
                    <p>A resource could be an application, a database or a service (like WordPress).</p>
 | 
			
		||||
                </x-slot:explanation>
 | 
			
		||||
            </x-boarding-step>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="flex justify-center gap-2 pt-4">
 | 
			
		||||
        <a wire:click='skipBoarding'>Skip boarding process</a>
 | 
			
		||||
        <a wire:click='restartBoarding'>Restart boarding process</a>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
<x-layout>
 | 
			
		||||
    <x-server.navbar :server="$server" />
 | 
			
		||||
    <livewire:server.private-key :server="$server" :privateKeys="$privateKeys" />
 | 
			
		||||
    <livewire:server.show-private-key :server="$server" :privateKeys="$privateKeys" />
 | 
			
		||||
</x-layout>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user