Update UI elements and text content
This commit is contained in:
parent
6b49d32102
commit
fafc4fb71e
@ -2,22 +2,27 @@
|
|||||||
|
|
||||||
namespace App\Livewire\Boarding;
|
namespace App\Livewire\Boarding;
|
||||||
|
|
||||||
use App\Actions\Server\InstallDocker;
|
|
||||||
use App\Enums\ProxyTypes;
|
use App\Enums\ProxyTypes;
|
||||||
use App\Models\PrivateKey;
|
use App\Models\PrivateKey;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Livewire\Attributes\Url;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
protected $listeners = ['serverInstalled' => 'validateServer'];
|
protected $listeners = ['serverInstalled' => 'validateServer'];
|
||||||
public string $currentState = 'welcome';
|
|
||||||
|
|
||||||
|
#[Url()]
|
||||||
|
public string $state = 'welcome';
|
||||||
|
|
||||||
|
#[Url()]
|
||||||
public ?string $selectedServerType = null;
|
public ?string $selectedServerType = null;
|
||||||
public ?Collection $privateKeys = null;
|
public ?Collection $privateKeys = null;
|
||||||
|
|
||||||
|
#[Url()]
|
||||||
public ?int $selectedExistingPrivateKey = null;
|
public ?int $selectedExistingPrivateKey = null;
|
||||||
public ?string $privateKeyType = null;
|
public ?string $privateKeyType = null;
|
||||||
public ?string $privateKey = null;
|
public ?string $privateKey = null;
|
||||||
@ -27,6 +32,8 @@ class Index extends Component
|
|||||||
public ?PrivateKey $createdPrivateKey = null;
|
public ?PrivateKey $createdPrivateKey = null;
|
||||||
|
|
||||||
public ?Collection $servers = null;
|
public ?Collection $servers = null;
|
||||||
|
|
||||||
|
#[Url()]
|
||||||
public ?int $selectedExistingServer = null;
|
public ?int $selectedExistingServer = null;
|
||||||
public ?string $remoteServerName = null;
|
public ?string $remoteServerName = null;
|
||||||
public ?string $remoteServerDescription = null;
|
public ?string $remoteServerDescription = null;
|
||||||
@ -38,7 +45,9 @@ class Index extends Component
|
|||||||
public ?Server $createdServer = null;
|
public ?Server $createdServer = null;
|
||||||
|
|
||||||
public Collection $projects;
|
public Collection $projects;
|
||||||
public ?int $selectedExistingProject = null;
|
|
||||||
|
#[Url()]
|
||||||
|
public ?int $selectedProject = null;
|
||||||
public ?Project $createdProject = null;
|
public ?Project $createdProject = null;
|
||||||
|
|
||||||
public bool $dockerInstallationStarted = false;
|
public bool $dockerInstallationStarted = false;
|
||||||
@ -62,13 +71,33 @@ public function mount()
|
|||||||
$this->remoteServerDescription = 'Created by Coolify';
|
$this->remoteServerDescription = 'Created by Coolify';
|
||||||
$this->remoteServerHost = 'coolify-testing-host';
|
$this->remoteServerHost = 'coolify-testing-host';
|
||||||
}
|
}
|
||||||
|
if ($this->state === 'create-project') {
|
||||||
|
$this->getProjects();
|
||||||
|
}
|
||||||
|
if ($this->state === 'create-resource') {
|
||||||
|
$this->selectExistingServer();
|
||||||
|
$this->selectExistingProject();
|
||||||
|
}
|
||||||
|
if ($this->state === 'private-key') {
|
||||||
|
$this->setServerType('remote');
|
||||||
|
}
|
||||||
|
if ($this->state === 'create-server') {
|
||||||
|
$this->selectExistingPrivateKey();
|
||||||
|
}
|
||||||
|
if ($this->state === 'validate-server') {
|
||||||
|
$this->selectExistingServer();
|
||||||
|
}
|
||||||
|
if ($this->state === 'select-existing-server') {
|
||||||
|
$this->selectExistingServer();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public function explanation()
|
public function explanation()
|
||||||
{
|
{
|
||||||
if (isCloud()) {
|
if (isCloud()) {
|
||||||
return $this->setServerType('remote');
|
return $this->setServerType('remote');
|
||||||
}
|
}
|
||||||
$this->currentState = 'select-server-type';
|
$this->state = 'select-server-type';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restartBoarding()
|
public function restartBoarding()
|
||||||
@ -89,6 +118,7 @@ public function setServerType(string $type)
|
|||||||
$this->selectedServerType = $type;
|
$this->selectedServerType = $type;
|
||||||
if ($this->selectedServerType === 'localhost') {
|
if ($this->selectedServerType === 'localhost') {
|
||||||
$this->createdServer = Server::find(0);
|
$this->createdServer = Server::find(0);
|
||||||
|
$this->selectedExistingServer = 0;
|
||||||
if (!$this->createdServer) {
|
if (!$this->createdServer) {
|
||||||
return $this->dispatch('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.');
|
return $this->dispatch('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.');
|
||||||
}
|
}
|
||||||
@ -106,10 +136,10 @@ public function setServerType(string $type)
|
|||||||
$this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
|
$this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
|
||||||
if ($this->servers->count() > 0) {
|
if ($this->servers->count() > 0) {
|
||||||
$this->selectedExistingServer = $this->servers->first()->id;
|
$this->selectedExistingServer = $this->servers->first()->id;
|
||||||
$this->currentState = 'select-existing-server';
|
$this->state = 'select-existing-server';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->currentState = 'private-key';
|
$this->state = 'private-key';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public function selectExistingServer()
|
public function selectExistingServer()
|
||||||
@ -117,12 +147,12 @@ public function selectExistingServer()
|
|||||||
$this->createdServer = Server::find($this->selectedExistingServer);
|
$this->createdServer = Server::find($this->selectedExistingServer);
|
||||||
if (!$this->createdServer) {
|
if (!$this->createdServer) {
|
||||||
$this->dispatch('error', 'Server is not found.');
|
$this->dispatch('error', 'Server is not found.');
|
||||||
$this->currentState = 'private-key';
|
$this->state = 'private-key';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
|
$this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
|
||||||
$this->serverPublicKey = $this->createdServer->privateKey->publicKey();
|
$this->serverPublicKey = $this->createdServer->privateKey->publicKey();
|
||||||
$this->currentState = 'validate-server';
|
$this->state = 'validate-server';
|
||||||
}
|
}
|
||||||
public function getProxyType()
|
public function getProxyType()
|
||||||
{
|
{
|
||||||
@ -130,7 +160,7 @@ public function getProxyType()
|
|||||||
$this->selectProxy(ProxyTypes::TRAEFIK_V2->value);
|
$this->selectProxy(ProxyTypes::TRAEFIK_V2->value);
|
||||||
// $proxyTypeSet = $this->createdServer->proxy->type;
|
// $proxyTypeSet = $this->createdServer->proxy->type;
|
||||||
// if (!$proxyTypeSet) {
|
// if (!$proxyTypeSet) {
|
||||||
// $this->currentState = 'select-proxy';
|
// $this->state = 'select-proxy';
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
$this->getProjects();
|
$this->getProjects();
|
||||||
@ -139,12 +169,12 @@ public function selectExistingPrivateKey()
|
|||||||
{
|
{
|
||||||
$this->createdPrivateKey = PrivateKey::find($this->selectedExistingPrivateKey);
|
$this->createdPrivateKey = PrivateKey::find($this->selectedExistingPrivateKey);
|
||||||
$this->privateKey = $this->createdPrivateKey->private_key;
|
$this->privateKey = $this->createdPrivateKey->private_key;
|
||||||
$this->currentState = 'create-server';
|
$this->state = 'create-server';
|
||||||
}
|
}
|
||||||
public function createNewServer()
|
public function createNewServer()
|
||||||
{
|
{
|
||||||
$this->selectedExistingServer = null;
|
$this->selectedExistingServer = null;
|
||||||
$this->currentState = 'private-key';
|
$this->state = 'private-key';
|
||||||
}
|
}
|
||||||
public function setPrivateKey(string $type)
|
public function setPrivateKey(string $type)
|
||||||
{
|
{
|
||||||
@ -153,7 +183,7 @@ public function setPrivateKey(string $type)
|
|||||||
if ($type === 'create') {
|
if ($type === 'create') {
|
||||||
$this->createNewPrivateKey();
|
$this->createNewPrivateKey();
|
||||||
}
|
}
|
||||||
$this->currentState = 'create-private-key';
|
$this->state = 'create-private-key';
|
||||||
}
|
}
|
||||||
public function savePrivateKey()
|
public function savePrivateKey()
|
||||||
{
|
{
|
||||||
@ -168,7 +198,7 @@ public function savePrivateKey()
|
|||||||
'team_id' => currentTeam()->id
|
'team_id' => currentTeam()->id
|
||||||
]);
|
]);
|
||||||
$this->createdPrivateKey->save();
|
$this->createdPrivateKey->save();
|
||||||
$this->currentState = 'create-server';
|
$this->state = 'create-server';
|
||||||
}
|
}
|
||||||
public function saveServer()
|
public function saveServer()
|
||||||
{
|
{
|
||||||
@ -196,7 +226,8 @@ public function saveServer()
|
|||||||
$this->createdServer->settings->is_cloudflare_tunnel = $this->isCloudflareTunnel;
|
$this->createdServer->settings->is_cloudflare_tunnel = $this->isCloudflareTunnel;
|
||||||
$this->createdServer->settings->save();
|
$this->createdServer->settings->save();
|
||||||
$this->createdServer->addInitialNetwork();
|
$this->createdServer->addInitialNetwork();
|
||||||
$this->currentState = 'validate-server';
|
$this->selectedExistingServer = $this->createdServer->id;
|
||||||
|
$this->state = 'validate-server';
|
||||||
}
|
}
|
||||||
public function installServer()
|
public function installServer()
|
||||||
{
|
{
|
||||||
@ -223,7 +254,7 @@ public function validateServer()
|
|||||||
$dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true);
|
$dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true);
|
||||||
$dockerVersion = checkMinimumDockerEngineVersion($dockerVersion);
|
$dockerVersion = checkMinimumDockerEngineVersion($dockerVersion);
|
||||||
if (is_null($dockerVersion)) {
|
if (is_null($dockerVersion)) {
|
||||||
$this->currentState = 'validate-server';
|
$this->state = 'validate-server';
|
||||||
throw new \Exception('Docker not found or old version is installed.');
|
throw new \Exception('Docker not found or old version is installed.');
|
||||||
}
|
}
|
||||||
$this->createdServer->settings()->update([
|
$this->createdServer->settings()->update([
|
||||||
@ -249,14 +280,14 @@ public function getProjects()
|
|||||||
{
|
{
|
||||||
$this->projects = Project::ownedByCurrentTeam(['name'])->get();
|
$this->projects = Project::ownedByCurrentTeam(['name'])->get();
|
||||||
if ($this->projects->count() > 0) {
|
if ($this->projects->count() > 0) {
|
||||||
$this->selectedExistingProject = $this->projects->first()->id;
|
$this->selectedProject = $this->projects->first()->id;
|
||||||
}
|
}
|
||||||
$this->currentState = 'create-project';
|
$this->state = 'create-project';
|
||||||
}
|
}
|
||||||
public function selectExistingProject()
|
public function selectExistingProject()
|
||||||
{
|
{
|
||||||
$this->createdProject = Project::find($this->selectedExistingProject);
|
$this->createdProject = Project::find($this->selectedProject);
|
||||||
$this->currentState = 'create-resource';
|
$this->state = 'create-resource';
|
||||||
}
|
}
|
||||||
public function createNewProject()
|
public function createNewProject()
|
||||||
{
|
{
|
||||||
@ -264,7 +295,7 @@ public function createNewProject()
|
|||||||
'name' => "My first project",
|
'name' => "My first project",
|
||||||
'team_id' => currentTeam()->id
|
'team_id' => currentTeam()->id
|
||||||
]);
|
]);
|
||||||
$this->currentState = 'create-resource';
|
$this->state = 'create-resource';
|
||||||
}
|
}
|
||||||
public function showNewResource()
|
public function showNewResource()
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@ protected function rules() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function mount() {
|
public function mount() {
|
||||||
$this->oauth_settings_map = OauthSetting::all()->reduce(function($carry, $setting) {
|
$this->oauth_settings_map = OauthSetting::all()->sortBy('provider')->reduce(function($carry, $setting) {
|
||||||
$carry[$setting->provider] = $setting;
|
$carry[$setting->provider] = $setting;
|
||||||
return $carry;
|
return $carry;
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"auth.confirm_password": "Confirm password",
|
"auth.confirm_password": "Confirm password",
|
||||||
"auth.forgot_password": "Forgot password",
|
"auth.forgot_password": "Forgot password",
|
||||||
"auth.forgot_password_send_email": "Send password reset email",
|
"auth.forgot_password_send_email": "Send password reset email",
|
||||||
"auth.register_now": "Register a new account",
|
"auth.register_now": "Register",
|
||||||
"auth.logout": "Logout",
|
"auth.logout": "Logout",
|
||||||
"auth.register": "Register",
|
"auth.register": "Register",
|
||||||
"auth.registration_disabled": "Registration is disabled. Please contact the administrator.",
|
"auth.registration_disabled": "Registration is disabled. Please contact the administrator.",
|
||||||
|
@ -11,6 +11,9 @@ body {
|
|||||||
@apply text-sm antialiased scrollbar;
|
@apply text-sm antialiased scrollbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
@apply px-3 py-1.5 text-sm font-normal normal-case rounded bg-neutral-200 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:bg-coolgray-100 dark:disabled:bg-coolgray-100/40 dark:disabled:text-neutral-800 min-w-fit flex items-center justify-center;
|
||||||
|
}
|
||||||
button[isError]:not(:disabled) {
|
button[isError]:not(:disabled) {
|
||||||
@apply bg-red-600 hover:bg-red-700;
|
@apply bg-red-600 hover:bg-red-700;
|
||||||
}
|
}
|
||||||
@ -19,9 +22,7 @@ button[isHighlighted]:not(:disabled) {
|
|||||||
@apply bg-coollabs hover:bg-coollabs-100;
|
@apply bg-coollabs hover:bg-coollabs-100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
|
||||||
@apply px-3 py-1.5 text-sm font-normal normal-case rounded dark:bg-coolgray-200 dark:text-white dark:hover:bg-coolgray-100 dark:disabled:bg-coolgray-100/40 dark:disabled:text-neutral-800 min-w-fit flex items-center justify-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-2xl font-bold dark:text-white text-neutral-800;
|
@apply text-2xl font-bold dark:text-white text-neutral-800;
|
||||||
@ -82,6 +83,7 @@ tr td:first-child {
|
|||||||
input {
|
input {
|
||||||
@apply pr-10;
|
@apply pr-10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
@apply block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:bg-coolgray-100 dark:text-white text-black focus:ring-2 dark:focus:ring-coolgray-300 dark:ring-coolgray-300 dark:read-only:text-neutral-500 dark:read-only:ring-0 dark:read-only:bg-coolgray-100/40 dark:placeholder:text-neutral-700;
|
@apply block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:bg-coolgray-100 dark:text-white text-black focus:ring-2 dark:focus:ring-coolgray-300 dark:ring-coolgray-300 dark:read-only:text-neutral-500 dark:read-only:ring-0 dark:read-only:bg-coolgray-100/40 dark:placeholder:text-neutral-700;
|
||||||
}
|
}
|
||||||
@ -89,12 +91,15 @@ .input {
|
|||||||
option {
|
option {
|
||||||
@apply text-white;
|
@apply text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-success {
|
.alert-success {
|
||||||
@apply flex items-center gap-2 text-success;
|
@apply flex items-center gap-2 text-success;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-error {
|
.alert-error {
|
||||||
@apply flex items-center gap-2 text-error;
|
@apply flex items-center gap-2 text-error;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
@apply relative flex cursor-pointer select-none dark:hover:text-white dark:hover:bg-coollabs items-center px-2 py-1.5 text-xs justify-center outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 gap-2
|
@apply relative flex cursor-pointer select-none dark:hover:text-white dark:hover:bg-coollabs items-center px-2 py-1.5 text-xs justify-center outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 gap-2
|
||||||
}
|
}
|
||||||
@ -115,8 +120,6 @@ .badge-error {
|
|||||||
@apply bg-error;
|
@apply bg-error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[type='checkbox']:checked {
|
[type='checkbox']:checked {
|
||||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
@ -126,11 +129,11 @@ .menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
@apply flex items-center w-full gap-2 px-4 py-1 min-w-48 hover:bg-coolgray-100 dark:hover:text-white;
|
@apply flex items-center w-full gap-2 py-1 pl-2 dark:hover:bg-coolgray-100 dark:hover:text-white hover:bg-neutral-300;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item-active {
|
.menu-item-active {
|
||||||
@apply rounded-none dark:bg-coolgray-200 dark:text-warning;
|
@apply text-black rounded-none dark:bg-coolgray-200 dark:text-warning bg-neutral-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
@ -170,15 +173,21 @@ .icon:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
@apply flex p-2 transition-colors cursor-pointer min-h-[4rem] bg-coolgray-100 hover:bg-coollabs-100 hover:text-white hover:no-underline;
|
@apply flex p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 bg-neutral-50 hover:bg-neutral-200 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-without-bg {
|
.box-without-bg {
|
||||||
@apply flex p-2 transition-colors hover:text-white hover:no-underline min-h-[4rem];
|
@apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box-title {
|
||||||
|
@apply font-bold text-black dark:text-white group-hover:dark:text-white;
|
||||||
|
}
|
||||||
|
.box-description {
|
||||||
|
@apply text-xs font-bold text-neutral-500 group-hover:dark:text-white group-hover:text-black;
|
||||||
|
}
|
||||||
.description {
|
.description {
|
||||||
@apply text-xs font-bold text-neutral-500 group-hover:text-white;
|
@apply text-xs font-bold text-neutral-500 group-hover:dark:text-white group-hover:text-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lds-heart {
|
.lds-heart {
|
||||||
@ -224,8 +233,9 @@ .buyme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@apply hidden pb-0 lg:block lg:pb-8 ;
|
@apply hidden pb-0 lg:block lg:pb-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
@apply pt-2 pb-10;
|
@apply pt-2 pb-10;
|
||||||
}
|
}
|
||||||
@ -237,4 +247,3 @@ .fullscreen {
|
|||||||
.toast {
|
.toast {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,29 +1,15 @@
|
|||||||
<x-layout-simple>
|
<x-layout-simple>
|
||||||
<div class="min-h-screen hero">
|
<section class="bg-gray-50 dark:bg-base">
|
||||||
<div class="w-96 min-w-fit">
|
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
|
||||||
<div class="flex flex-col items-center pb-8">
|
<a class="flex items-center mb-6 text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white">
|
||||||
<div class="text-5xl font-extrabold tracking-tight text-center text-white">Coolify</div>
|
Coolify
|
||||||
</div>
|
</a>
|
||||||
<div class="flex items-center gap-2">
|
<div
|
||||||
<h1>{{ __('auth.login') }}</h1>
|
class="w-full bg-white rounded shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-base dark:border-coolgray-200">
|
||||||
@if ($is_registration_enabled)
|
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
||||||
@if (config('coolify.waitlist'))
|
<form action="/login" method="POST" class="flex flex-col gap-2">
|
||||||
<a href="/waitlist"
|
@csrf
|
||||||
class="text-xs text-center text-white normal-case bg-transparent border-none rounded no-animation hover:no-underline btn btn-sm bg-coollabs-gradient">
|
@env('local')
|
||||||
Join the waitlist
|
|
||||||
</a>
|
|
||||||
@else
|
|
||||||
<a href="/register"
|
|
||||||
class="text-xs text-center text-white normal-case bg-transparent border-none rounded no-animation hover:no-underline btn btn-sm bg-coollabs-gradient">
|
|
||||||
{{ __('auth.register_now') }}
|
|
||||||
</a>
|
|
||||||
@endif
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<form action="/login" method="POST" class="flex flex-col gap-2">
|
|
||||||
@csrf
|
|
||||||
@env('local')
|
|
||||||
<x-forms.input value="test@example.com" type="email" name="email" required
|
<x-forms.input value="test@example.com" type="email" name="email" required
|
||||||
label="{{ __('input.email') }}" autofocus />
|
label="{{ __('input.email') }}" autofocus />
|
||||||
|
|
||||||
@ -33,40 +19,59 @@ class="text-xs text-center text-white normal-case bg-transparent border-none rou
|
|||||||
{{ __('auth.forgot_password') }}?
|
{{ __('auth.forgot_password') }}?
|
||||||
</a>
|
</a>
|
||||||
@else
|
@else
|
||||||
<x-forms.input type="email" name="email" required label="{{ __('input.email') }}" autofocus />
|
<x-forms.input type="email" name="email" required label="{{ __('input.email') }}"
|
||||||
|
autofocus />
|
||||||
<x-forms.input type="password" name="password" required label="{{ __('input.password') }}" />
|
<x-forms.input type="password" name="password" required label="{{ __('input.password') }}" />
|
||||||
<a href="/forgot-password" class="text-xs">
|
<a href="/forgot-password" class="text-xs">
|
||||||
{{ __('auth.forgot_password') }}?
|
{{ __('auth.forgot_password') }}?
|
||||||
</a>
|
</a>
|
||||||
@endenv
|
@endenv
|
||||||
<x-forms.button type="submit">{{ __('auth.login') }}</x-forms.button>
|
<x-forms.button class="mt-10" type="submit">{{ __('auth.login') }}</x-forms.button>
|
||||||
@foreach ($enabled_oauth_providers as $provider_setting)
|
@if ($is_registration_enabled)
|
||||||
<x-forms.button type="button" onclick="document.location.href='/auth/{{$provider_setting->provider}}/redirect'">
|
<a href="/register"
|
||||||
{{ __("auth.login.$provider_setting->provider") }}
|
class="button bg-coollabs-gradient">
|
||||||
</x-forms.button>
|
{{ __('auth.register_now') }}
|
||||||
@endforeach
|
</a>
|
||||||
@if (!$is_registration_enabled)
|
@endif
|
||||||
<div class="text-center ">{{ __('auth.registration_disabled') }}</div>
|
@if ($enabled_oauth_providers->isNotEmpty())
|
||||||
@endif
|
<div class="relative">
|
||||||
@if ($errors->any())
|
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
||||||
<div class="text-xs text-center text-error">
|
<div class="w-full border-t dark:border-coolgray-200"></div>
|
||||||
@foreach ($errors->all() as $error)
|
</div>
|
||||||
<p>{{ $error }}</p>
|
<div class="relative flex justify-center">
|
||||||
@endforeach
|
<span class="px-2 text-sm dark:text-neutral-500 dark:bg-base">or</span>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
</div>
|
||||||
@if (session('status'))
|
@endif
|
||||||
<div class="mb-4 font-medium text-green-600">
|
@foreach ($enabled_oauth_providers as $provider_setting)
|
||||||
{{ session('status') }}
|
<x-forms.button type="button"
|
||||||
</div>
|
onclick="document.location.href='/auth/{{ $provider_setting->provider }}/redirect'">
|
||||||
@endif
|
{{ __("auth.login.$provider_setting->provider") }}
|
||||||
@if (session('error'))
|
</x-forms.button>
|
||||||
<div class="mb-4 font-medium text-red-600">
|
@endforeach
|
||||||
{{ session('error') }}
|
@if (!$is_registration_enabled)
|
||||||
</div>
|
<div class="text-center text-neutral-500">{{ __('auth.registration_disabled') }}</div>
|
||||||
@endif
|
@endif
|
||||||
</form>
|
@if ($errors->any())
|
||||||
|
<div class="text-xs text-center text-error">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<p>{{ $error }}</p>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if (session('status'))
|
||||||
|
<div class="mb-4 font-medium text-green-600">
|
||||||
|
{{ session('status') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if (session('error'))
|
||||||
|
<div class="mb-4 font-medium text-red-600">
|
||||||
|
{{ session('error') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</x-layout-simple>
|
</x-layout-simple>
|
||||||
|
@ -1,48 +1,53 @@
|
|||||||
<x-layout-simple>
|
<x-layout-simple>
|
||||||
<div class="flex items-center justify-center min-h-screen ">
|
<section class="bg-gray-50 dark:bg-base">
|
||||||
<div class="w-1/2">
|
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
|
||||||
<div class="flex flex-col items-center pb-8">
|
<a class="flex items-center mb-6 text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white">
|
||||||
<div class="text-5xl font-bold tracking-tight text-center text-white">Coolify</div>
|
Coolify
|
||||||
<x-version />
|
</a>
|
||||||
|
<div
|
||||||
|
class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-base dark:border-coolgray-200">
|
||||||
|
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
||||||
|
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
|
||||||
|
Create an account
|
||||||
|
</h1>
|
||||||
|
<form action="/register" method="POST" class="flex flex-col gap-2">
|
||||||
|
@csrf
|
||||||
|
@env('local')
|
||||||
|
<x-forms.input required value="test3 normal user" type="text" name="name"
|
||||||
|
label="{{ __('input.name') }}" />
|
||||||
|
<x-forms.input required value="test3@example.com" type="email" name="email"
|
||||||
|
label="{{ __('input.email') }}" />
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input required value="password" type="password" name="password"
|
||||||
|
label="{{ __('input.password') }}" />
|
||||||
|
<x-forms.input required value="password" type="password" name="password_confirmation"
|
||||||
|
label="{{ __('input.password.again') }}" />
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<x-forms.input required type="text" name="name" label="{{ __('input.name') }}" />
|
||||||
|
<x-forms.input required type="email" name="email" label="{{ __('input.email') }}" />
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input required type="password" name="password"
|
||||||
|
label="{{ __('input.password') }}" />
|
||||||
|
<x-forms.input required type="password" name="password_confirmation"
|
||||||
|
label="{{ __('input.password.again') }}" />
|
||||||
|
</div>
|
||||||
|
@endenv
|
||||||
|
<x-forms.button class="mb-4" type="submit">Register</x-forms.button>
|
||||||
|
<a href="/login" class="button bg-coollabs-gradient">
|
||||||
|
{{ __('auth.already_registered') }}
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
@if ($errors->any())
|
||||||
|
<div class="text-xs text-center text-error">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<p>{{ $error }}</p>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<h1>{{ __('auth.register') }}</h1>
|
|
||||||
<a href="/login"
|
|
||||||
class="text-xs text-center text-white normal-case bg-transparent border-none rounded no-animation hover:no-underline btn btn-sm bg-coollabs-gradient">
|
|
||||||
{{ __('auth.already_registered') }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<form action="/register" method="POST" class="flex flex-col gap-2">
|
|
||||||
@csrf
|
|
||||||
@env('local')
|
|
||||||
<x-forms.input required value="test3 normal user" type="text" name="name"
|
|
||||||
label="{{ __('input.name') }}" />
|
|
||||||
<x-forms.input required value="test3@example.com" type="email" name="email"
|
|
||||||
label="{{ __('input.email') }}" />
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<x-forms.input required value="password" type="password" name="password"
|
|
||||||
label="{{ __('input.password') }}" />
|
|
||||||
<x-forms.input required value="password" type="password" name="password_confirmation"
|
|
||||||
label="{{ __('input.password.again') }}" />
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<x-forms.input required type="text" name="name" label="{{ __('input.name') }}" />
|
|
||||||
<x-forms.input required type="email" name="email" label="{{ __('input.email') }}" />
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<x-forms.input required type="password" name="password" label="{{ __('input.password') }}" />
|
|
||||||
<x-forms.input required type="password" name="password_confirmation"
|
|
||||||
label="{{ __('input.password.again') }}" />
|
|
||||||
</div>
|
|
||||||
@endenv
|
|
||||||
<x-forms.button type="submit">{{ __('auth.register') }}</x-forms.button>
|
|
||||||
</form>
|
|
||||||
@if ($errors->any())
|
|
||||||
<div class="text-xs text-center text-error">
|
|
||||||
@foreach ($errors->all() as $error)
|
|
||||||
<p>{{ $error }}</p>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</x-layout-simple>
|
</x-layout-simple>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||||
<div class="box-border col-span-2 min-w-[24rem] min-h-[21rem]">
|
<div class="box-border col-span-2 min-w-[24rem] min-h-[21rem]">
|
||||||
<h1 class="text-5xl font-bold">{{ $title }}</h1>
|
<h1 class="text-5xl font-bold">{{ $title }}</h1>
|
||||||
<div class="py-6 ">
|
<div class="py-6">
|
||||||
@isset($question)
|
@isset($question)
|
||||||
<p class="text-base">
|
<p class="text-base dark:text-neutral-400">
|
||||||
{{ $question }}
|
{{ $question }}
|
||||||
</p>
|
</p>
|
||||||
@endisset
|
@endisset
|
||||||
|
@ -1 +1 @@
|
|||||||
<span class="inline-block text-warning">{{ $text }}</span>
|
<span class="inline-block font-bold text-warning">{{ $text }}</span>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
@props(['text' => null])
|
@props(['text' => null])
|
||||||
<div class="inline-flex items-center justify-center" {{ $attributes }}>
|
<div class="inline-flex items-center justify-center" {{ $attributes }}>
|
||||||
|
<div>{{ $text }}</div>
|
||||||
<svg class="w-4 h-4 mx-1 ml-3 text-warning animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none"
|
<svg class="w-4 h-4 mx-1 ml-3 text-warning animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||||
viewBox="0 0 24 24">
|
viewBox="0 0 24 24">
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
@ -7,5 +8,4 @@
|
|||||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
|
||||||
</path>
|
</path>
|
||||||
</svg>
|
</svg>
|
||||||
<div>{{ $text }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
<div class="flex items-center h-16 pt-2 lg:pt-4 shrink-0">
|
<nav class="flex flex-col flex-1 pl-4 border-r dark:border-coolgray-300 dark:bg-coolgray-100 bg-neutral-50">
|
||||||
<a href="/" class="flex items-center w-12 h-12 -mx-1 text-xl font-bold text-white"><img
|
<div class="flex w-full px-2 pt-6 pb-4">
|
||||||
class="transition rounded " src="{{ asset('coolify-transparent.png') }}"></a>
|
<div class="flex flex-col">
|
||||||
</div>
|
<div class="text-2xl font-bold tracking-wide dark:text-white">Coolify</div>
|
||||||
<nav class="flex flex-col flex-1">
|
<x-version />
|
||||||
|
</div>
|
||||||
|
<button onclick="changeTheme()">Dark/light</button>
|
||||||
|
</div>
|
||||||
<ul role="list" class="flex flex-col flex-1 gap-y-7">
|
<ul role="list" class="flex flex-col flex-1 gap-y-7">
|
||||||
<li class="flex-1">
|
<li class="flex-1 ">
|
||||||
<ul role="list" class="flex flex-col h-full -mx-2 space-y-1">
|
<ul role="list" class="flex flex-col h-full space-y-1.5">
|
||||||
<li>
|
<li>
|
||||||
<a title="Dashboard" href="/"
|
<a title="Dashboard" href="/"
|
||||||
class="{{ request()->is('/') ? 'menu-item-active menu-item' : 'menu-item' }}">
|
class="{{ request()->is('/') ? 'menu-item-active menu-item' : 'menu-item' }}">
|
||||||
@ -278,8 +281,8 @@ class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li> --}}
|
</li>
|
||||||
{{-- <li class="mt-auto -mx-6">
|
<li class="mt-auto -mx-6">
|
||||||
<a href="#"
|
<a href="#"
|
||||||
class="flex items-center px-6 py-3 text-sm font-semibold leading-6 text-gray-900 gap-x-4 hover:bg-gray-50">
|
class="flex items-center px-6 py-3 text-sm font-semibold leading-6 text-gray-900 gap-x-4 hover:bg-gray-50">
|
||||||
<img class="w-8 h-8 rounded-full bg-gray-50"
|
<img class="w-8 h-8 rounded-full bg-gray-50"
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
<a {{ $attributes->merge(['class' => 'text-xs cursor-pointer opacity-60 hover:opacity-100 hover:text-white z-[60]']) }}
|
<a {{ $attributes->merge(['class' => 'text-xs cursor-pointer opacity-60 hover:opacity-100 dark:hover:text-white hover:text-black z-[60]']) }}
|
||||||
href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('version') }}">v{{ config('version') }}</a>
|
href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('version') }}">v{{ config('version') }}</a>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<div class="relative z-50 lg:hidden" :class="open ? 'block' : 'hidden'" role="dialog" aria-modal="true">
|
<div class="relative z-50 lg:hidden" :class="open ? 'block' : 'hidden'" role="dialog" aria-modal="true">
|
||||||
<div class="fixed inset-0 bg-black/80"></div>
|
<div class="fixed inset-0 bg-black/80"></div>
|
||||||
<div class="fixed inset-0 flex">
|
<div class="fixed inset-0 flex">
|
||||||
<div class="relative flex flex-1 w-full mr-16 max-w-56 ">
|
<div class="relative flex flex-1 w-full mr-16 max-w-48 ">
|
||||||
<div class="absolute top-0 flex justify-center w-16 pt-5 left-full">
|
<div class="absolute top-0 flex justify-center w-16 pt-5 left-full">
|
||||||
<button type="button" class="-m-2.5 p-2.5" x-on:click="open = !open">
|
<button type="button" class="-m-2.5 p-2.5" x-on:click="open = !open">
|
||||||
<span class="sr-only">Close sidebar</span>
|
<span class="sr-only">Close sidebar</span>
|
||||||
@ -21,21 +21,20 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col px-6 pb-2 overflow-y-auto dark:bg-coolgray-100 gap-y-5 scrollbar">
|
<div class="flex flex-col pb-2 overflow-y-auto min-w-48 dark:bg-coolgray-100 gap-y-5 scrollbar">
|
||||||
<x-navbar />
|
<x-navbar />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-56 lg:flex-col">
|
<div class="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-48 lg:flex-col">
|
||||||
<div class="flex flex-col px-4 overflow-y-auto grow gap-y-5 scrollbar">
|
<div class="flex flex-col overflow-y-auto grow gap-y-5 scrollbar">
|
||||||
<x-navbar />
|
<x-navbar />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="sticky top-0 z-40 flex items-center px-4 py-4 gap-x-6 sm:px-6 lg:hidden">
|
||||||
class="sticky top-0 z-40 flex items-center px-4 py-4 gap-x-6 sm:px-6 lg:hidden">
|
|
||||||
<button type="button" class="-m-2.5 p-2.5 dark:text-warning lg:hidden" x-on:click="open = !open">
|
<button type="button" class="-m-2.5 p-2.5 dark:text-warning lg:hidden" x-on:click="open = !open">
|
||||||
<span class="sr-only">Open sidebar</span>
|
<span class="sr-only">Open sidebar</span>
|
||||||
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 24 24">
|
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 24 24">
|
||||||
@ -52,7 +51,7 @@ class="sticky top-0 z-40 flex items-center px-4 py-4 gap-x-6 sm:px-6 lg:hidden">
|
|||||||
</a> --}}
|
</a> --}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main class="lg:pl-56">
|
<main class="lg:pl-48">
|
||||||
<div>
|
<div>
|
||||||
<div class="p-4 sm:px-6 lg:px-8 lg:py-6">
|
<div class="p-4 sm:px-6 lg:px-8 lg:py-6">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
|
@ -38,10 +38,9 @@
|
|||||||
@section('body')
|
@section('body')
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{{-- <button onclick="changeTheme()" class="fixed z-50 left-52">Dark/light</button> --}}
|
|
||||||
@livewire('wire-elements-modal')
|
@livewire('wire-elements-modal')
|
||||||
<x-toast />
|
<x-toast />
|
||||||
<x-version class="fixed left-7 bottom-1" />
|
{{-- <x-version class="fixed left-7 bottom-1" /> --}}
|
||||||
<script data-navigate-once>
|
<script data-navigate-once>
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia(
|
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia(
|
||||||
'(prefers-color-scheme: dark)').matches)) {
|
'(prefers-color-scheme: dark)').matches)) {
|
||||||
|
@ -1,350 +1,335 @@
|
|||||||
@php use App\Enums\ProxyTypes; @endphp
|
@php use App\Enums\ProxyTypes; @endphp
|
||||||
<div>
|
<section class="bg-gray-50 dark:bg-base">
|
||||||
<div>
|
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto max-w-7xl md:h-screen lg:py-0">
|
||||||
@if ($currentState === 'welcome')
|
@if ($state === 'welcome')
|
||||||
<h1 class="text-5xl font-bold">Welcome to Coolify</h1>
|
<h1 class="text-5xl font-bold">Welcome to Coolify</h1>
|
||||||
<p class="py-6 text-xl text-center">Let me help you set up the basics.</p>
|
<p class="py-6 text-xl text-center">Let me help you set up the basics.</p>
|
||||||
<div class="flex justify-center ">
|
<div class="flex justify-center ">
|
||||||
<x-forms.button class="justify-center w-64 box" wire:click="$set('currentState','explanation')">Get
|
<x-forms.button class="justify-center w-64 box" wire:click="$set('state','explanation')">Get
|
||||||
Started
|
Started
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
<div>
|
||||||
<div>
|
@if ($state === 'explanation')
|
||||||
@if ($currentState === 'explanation')
|
<x-boarding-step title="What is Coolify?">
|
||||||
<x-boarding-step title="What is Coolify?">
|
<x-slot:question>
|
||||||
<x-slot:question>
|
Coolify is an all-in-one application to automate tasks on your servers, deploy application with
|
||||||
Coolify is an all-in-one application to automate tasks on your servers, deploy application with Git
|
Git
|
||||||
integrations, deploy databases and services, monitor these resources with notifications and alerts
|
integrations, deploy databases and services, monitor these resources with notifications and
|
||||||
without vendor lock-in
|
alerts
|
||||||
and <a href="https://coolify.io" class="text-white hover:underline">much much more</a>.
|
without vendor lock-in
|
||||||
<br><br>
|
and <a href="https://coolify.io" class="text-white hover:underline">much much more</a>.
|
||||||
<span class="text-xl">
|
<br><br>
|
||||||
<x-highlighted text="Self-hosting with superpowers!" /></span>
|
<span class="text-xl">
|
||||||
</x-slot:question>
|
<x-highlighted text="Self-hosting with superpowers!" /></span>
|
||||||
<x-slot:explanation>
|
</x-slot:question>
|
||||||
<p><x-highlighted text="Task automation:" /> You don't need to manage your servers anymore. Coolify does
|
<x-slot:explanation>
|
||||||
it for you.</p>
|
<p><x-highlighted text="Task automation:" /> You don't need to manage your servers anymore.
|
||||||
<p><x-highlighted text="No vendor lock-in:" /> All configurations are stored on your servers, so
|
Coolify does
|
||||||
everything works without a connection to Coolify (except integrations and automations).</p>
|
it for you.</p>
|
||||||
<p><x-highlighted text="Monitoring:" />You can get notified on your favourite platforms (Discord,
|
<p><x-highlighted text="No vendor lock-in:" /> All configurations are stored on your servers, so
|
||||||
Telegram, Email, etc.) when something goes wrong, or an action is needed from your side.</p>
|
everything works without a connection to Coolify (except integrations and automations).</p>
|
||||||
</x-slot:explanation>
|
<p><x-highlighted text="Monitoring:" />You can get notified on your favourite platforms
|
||||||
<x-slot:actions>
|
(Discord,
|
||||||
<x-forms.button class="justify-center w-64 box" wire:click="explanation">Next
|
Telegram, Email, etc.) when something goes wrong, or an action is needed from your side.</p>
|
||||||
</x-forms.button>
|
</x-slot:explanation>
|
||||||
</x-slot:actions>
|
<x-slot:actions>
|
||||||
</x-boarding-step>
|
<x-forms.button class="justify-center w-64 box" wire:click="explanation">Next
|
||||||
@endif
|
</x-forms.button>
|
||||||
@if ($currentState === 'select-server-type')
|
</x-slot:actions>
|
||||||
<x-boarding-step title="Server">
|
</x-boarding-step>
|
||||||
<x-slot:question>
|
@endif
|
||||||
Do you want to deploy your resources to your <x-highlighted text="Localhost" />
|
@if ($state === 'select-server-type')
|
||||||
or to a <x-highlighted text="Remote Server" />?
|
<x-boarding-step title="Server">
|
||||||
</x-slot:question>
|
<x-slot:question>
|
||||||
<x-slot:actions>
|
Do you want to deploy your resources to your <x-highlighted text="Localhost" />
|
||||||
<x-forms.button class="justify-center w-64 box" wire:target="setServerType('localhost')"
|
or to a <x-highlighted text="Remote Server" />?
|
||||||
wire:click="setServerType('localhost')">Localhost
|
</x-slot:question>
|
||||||
</x-forms.button>
|
<x-slot:actions>
|
||||||
|
<x-forms.button class="justify-center w-64 box" wire:target="setServerType('localhost')"
|
||||||
|
wire:click="setServerType('localhost')">Localhost
|
||||||
|
</x-forms.button>
|
||||||
|
|
||||||
<x-forms.button class="justify-center w-64 box " wire:target="setServerType('remote')"
|
<x-forms.button class="justify-center w-64 box " wire:target="setServerType('remote')"
|
||||||
wire:click="setServerType('remote')">Remote Server
|
wire:click="setServerType('remote')">Remote Server
|
||||||
</x-forms.button>
|
|
||||||
@if (!$serverReachable)
|
|
||||||
Localhost is not reachable with the following public key.
|
|
||||||
<br /> <br />
|
|
||||||
Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for user
|
|
||||||
'root' or skip the boarding process and add a new private key manually to Coolify and to the
|
|
||||||
server.
|
|
||||||
<br />
|
|
||||||
Check this <a target="_blank" class="underline"
|
|
||||||
href="https://coolify.io/docs/server/openssh">documentation</a> for further help.
|
|
||||||
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
|
|
||||||
<x-forms.button class="w-64 box" wire:target="setServerType('localhost')"
|
|
||||||
wire:click="setServerType('localhost')">Check again
|
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@if (!$serverReachable)
|
||||||
</x-slot:actions>
|
Localhost is not reachable with the following public key.
|
||||||
<x-slot:explanation>
|
<br /> <br />
|
||||||
<p>Servers are the main building blocks, as they will host your applications, databases,
|
Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for
|
||||||
services, called resources. Any CPU intensive process will use the server's CPU where you
|
user
|
||||||
are deploying your resources.</p>
|
'root' or skip the boarding process and add a new private key manually to Coolify and to the
|
||||||
<p>Localhost is the server where Coolify is running on. It is not recommended to use one server
|
server.
|
||||||
for everything.</p>
|
<br />
|
||||||
<p>Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud
|
Check this <a target="_blank" class="underline"
|
||||||
provider.</p>
|
href="https://coolify.io/docs/server/openssh">documentation</a> for further help.
|
||||||
</x-slot:explanation>
|
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
|
||||||
</x-boarding-step>
|
<x-forms.button class="w-64 box" wire:target="setServerType('localhost')"
|
||||||
@endif
|
wire:click="setServerType('localhost')">Check again
|
||||||
</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>
|
|
||||||
<x-forms.button class="justify-center w-64 box" wire:target="setPrivateKey('own')"
|
|
||||||
wire:click="setPrivateKey('own')">Yes
|
|
||||||
</x-forms.button>
|
|
||||||
<x-forms.button class="justify-center w-64 box" wire:target="setPrivateKey('create')"
|
|
||||||
wire:click="setPrivateKey('create')">No (create one for me)
|
|
||||||
</x-forms.button>
|
|
||||||
@if (count($privateKeys) > 0)
|
|
||||||
<form wire:submit='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-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="flex flex-col gap-4">
|
|
||||||
<div>
|
|
||||||
<x-forms.button class="justify-center w-64 box" wire:click="createNewServer">No (create one
|
|
||||||
for
|
|
||||||
me)
|
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
@endif
|
||||||
<div>
|
</x-slot:actions>
|
||||||
<form wire:submit='selectExistingServer' class="flex flex-col w-full gap-4 lg:w-96">
|
<x-slot:explanation>
|
||||||
<x-forms.select label="Existing servers" class="w-96" id='selectedExistingServer'>
|
<p>Servers are the main building blocks, as they will host your applications, databases,
|
||||||
@foreach ($servers as $server)
|
services, called resources. Any CPU intensive process will use the server's CPU where you
|
||||||
<option wire:key="{{ $loop->index }}" value="{{ $server->id }}">
|
are deploying your resources.</p>
|
||||||
{{ $server->name }}</option>
|
<p><x-highlighted text="Localhost" /> is the server where Coolify is running on. It is not
|
||||||
|
recommended to use one server
|
||||||
|
for everything.</p>
|
||||||
|
<p><x-highlighted text="A 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 ($state === '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>
|
||||||
|
<x-forms.button class="justify-center w-64 box" wire:target="setPrivateKey('own')"
|
||||||
|
wire:click="setPrivateKey('own')">Yes
|
||||||
|
</x-forms.button>
|
||||||
|
<x-forms.button class="justify-center w-64 box" wire:target="setPrivateKey('create')"
|
||||||
|
wire:click="setPrivateKey('create')">No (create one for me)
|
||||||
|
</x-forms.button>
|
||||||
|
@if (count($privateKeys) > 0)
|
||||||
|
<form wire:submit='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
|
@endforeach
|
||||||
</x-forms.select>
|
</x-forms.select>
|
||||||
<x-forms.button type="submit">Use this Server</x-forms.button>
|
<x-forms.button type="submit">Use this SSH Key</x-forms.button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@if (!$serverReachable)
|
|
||||||
This server is not reachable with the following public key.
|
|
||||||
<br /> <br />
|
|
||||||
Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for user
|
|
||||||
'root' or skip the boarding process and add a new private key manually to Coolify and to the
|
|
||||||
server.
|
|
||||||
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
|
|
||||||
<x-forms.button class="w-64 box" wire:target="validateServer" wire:click="validateServer">Check
|
|
||||||
again
|
|
||||||
</x-forms.button>
|
|
||||||
@endif
|
|
||||||
</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='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')
|
|
||||||
<x-forms.textarea rows="7" readonly label="Public Key" id="publicKey" />
|
|
||||||
<span class="font-bold text-warning">ACTION REQUIRED: Copy the 'Public Key' to your server's
|
|
||||||
~/.ssh/authorized_keys
|
|
||||||
file.</span>
|
|
||||||
@endif
|
@endif
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
</x-slot:actions>
|
||||||
</form>
|
<x-slot:explanation>
|
||||||
</x-slot:actions>
|
<p>SSH Keys are used to connect to a remote server through a secure shell, called SSH.</p>
|
||||||
<x-slot:explanation>
|
<p>You can use your own ssh private key, or you can let Coolify to create one for you.</p>
|
||||||
<p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p>
|
<p>In both ways, you need to add the public version of your ssh private key to the remote
|
||||||
<p>You can use your own private key, or you can let Coolify to create one for you.</p>
|
server's
|
||||||
<p>In both ways, you need to add the public version of your private key to the remote server's
|
<code class="text-warning">~/.ssh/authorized_keys</code> file.
|
||||||
<code>~/.ssh/authorized_keys</code> file.
|
</p>
|
||||||
</p>
|
</x-slot:explanation>
|
||||||
</x-slot:explanation>
|
</x-boarding-step>
|
||||||
</x-boarding-step>
|
@endif
|
||||||
@endif
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
@if ($state === 'select-existing-server')
|
||||||
@if ($currentState === 'create-server')
|
<x-boarding-step title="Select a server">
|
||||||
<x-boarding-step title="Create Server">
|
<x-slot:question>
|
||||||
<x-slot:question>
|
There are already servers available for your Team. Do you want to use one of them?
|
||||||
Please let me know your server details.
|
</x-slot:question>
|
||||||
</x-slot:question>
|
<x-slot:actions>
|
||||||
<x-slot:actions>
|
<div class="flex flex-col gap-4">
|
||||||
<form wire:submit='saveServer' class="flex flex-col w-full gap-4 pr-10">
|
<div>
|
||||||
<div class="flex gap-2">
|
<x-forms.button class="justify-center w-64 box" wire:click="createNewServer">No (create
|
||||||
<x-forms.input required placeholder="Choose a name for your Server. Could be anything."
|
one
|
||||||
label="Name" id="remoteServerName" />
|
for
|
||||||
|
me)
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<form wire:submit='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>
|
||||||
|
</div>
|
||||||
|
@if (!$serverReachable)
|
||||||
|
This server is not reachable with the following public key.
|
||||||
|
<br /> <br />
|
||||||
|
Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for
|
||||||
|
user
|
||||||
|
'root' or skip the boarding process and add a new private key manually to Coolify and to the
|
||||||
|
server.
|
||||||
|
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
|
||||||
|
<x-forms.button class="w-64 box" wire:target="validateServer"
|
||||||
|
wire:click="validateServer">Check
|
||||||
|
again
|
||||||
|
</x-forms.button>
|
||||||
|
@endif
|
||||||
|
</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 ($state === '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='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."
|
<x-forms.input placeholder="Description, so others will know more about this."
|
||||||
label="Description" id="remoteServerDescription" />
|
label="Description" id="privateKeyDescription" />
|
||||||
</div>
|
<x-forms.textarea required placeholder="-----BEGIN OPENSSH PRIVATE KEY-----"
|
||||||
<div class="flex gap-2">
|
label="Private Key" id="privateKey" />
|
||||||
<x-forms.input required placeholder="127.0.0.1" label="IP Address" id="remoteServerHost" />
|
@if ($privateKeyType === 'create')
|
||||||
<x-forms.input required placeholder="Port number of your server. Default is 22."
|
<x-forms.textarea rows="7" readonly label="Public Key" id="publicKey" />
|
||||||
label="Port" id="remoteServerPort" />
|
<span class="font-bold text-warning">ACTION REQUIRED: Copy the 'Public Key' to your
|
||||||
<x-forms.input required readonly
|
server's
|
||||||
placeholder="Username to connect to your server. Default is root." label="Username"
|
~/.ssh/authorized_keys
|
||||||
id="remoteServerUser" />
|
file.</span>
|
||||||
</div>
|
@endif
|
||||||
<div class="w-64">
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
<x-forms.checkbox
|
</form>
|
||||||
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<br><span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>"
|
</x-slot:actions>
|
||||||
id="isCloudflareTunnel" label="Cloudflare Tunnel" />
|
<x-slot:explanation>
|
||||||
</div>
|
<p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p>
|
||||||
<x-forms.button type="submit">Continue</x-forms.button>
|
<p>You can use your own private key, or you can let Coolify to create one for you.</p>
|
||||||
</form>
|
<p>In both ways, you need to add the public version of your private key to the remote server's
|
||||||
</x-slot:actions>
|
<code>~/.ssh/authorized_keys</code> file.
|
||||||
<x-slot:explanation>
|
</p>
|
||||||
<p>Username should be <x-highlighted text="root" /> for now. We are working on to use
|
</x-slot:explanation>
|
||||||
non-root users.</p>
|
</x-boarding-step>
|
||||||
</x-slot:explanation>
|
@endif
|
||||||
</x-boarding-step>
|
</div>
|
||||||
@endif
|
<div>
|
||||||
</div>
|
@if ($state === 'create-server')
|
||||||
<div>
|
<x-boarding-step title="Create Server">
|
||||||
@if ($currentState === 'validate-server')
|
<x-slot:question>
|
||||||
<x-boarding-step title="Validate & Configure Server">
|
Please let me know your server details.
|
||||||
<x-slot:question>
|
</x-slot:question>
|
||||||
I need to validate your server (connection, Docker Engine, etc) and configure if something is
|
<x-slot:actions>
|
||||||
missing for me. Are you okay with this?
|
<form wire:submit='saveServer' class="flex flex-col w-full gap-4 pr-10">
|
||||||
</x-slot:question>
|
<div class="flex gap-2">
|
||||||
<x-slot:actions>
|
<x-forms.input required placeholder="Choose a name for your Server. Could be anything."
|
||||||
<x-slide-over closeWithX fullScreen>
|
label="Name" id="remoteServerName" />
|
||||||
<x-slot:title>Validate & configure</x-slot:title>
|
<x-forms.input placeholder="Description, so others will know more about this."
|
||||||
<x-slot:content>
|
label="Description" id="remoteServerDescription" />
|
||||||
<livewire:server.validate-and-install :server="$this->createdServer" />
|
</div>
|
||||||
</x-slot:content>
|
<div class="flex gap-2">
|
||||||
<x-forms.button @click="slideOverOpen=true" class="font-bold box w-96"
|
<x-forms.input required placeholder="127.0.0.1" label="IP Address"
|
||||||
wire:click.prevent='installServer' isHighlighted>
|
id="remoteServerHost" />
|
||||||
Let's do it!
|
<x-forms.input required placeholder="Port number of your server. Default is 22."
|
||||||
</x-forms.button>
|
label="Port" id="remoteServerPort" />
|
||||||
</x-slide-over>
|
<x-forms.input required readonly
|
||||||
</x-slot:actions>
|
placeholder="Username to connect to your server. Default is root."
|
||||||
<x-slot:explanation>
|
label="Username" id="remoteServerUser" />
|
||||||
<p>This will install the latest Docker Engine on your server, configure a few things to be able
|
</div>
|
||||||
to run optimal.<br><br>Minimum Docker Engine version is: 22<br><br>To manually install Docker
|
<div class="w-64">
|
||||||
Engine, check <a target="_blank" class="underline text-warning"
|
<x-forms.checkbox
|
||||||
href="https://docs.docker.com/engine/install/#server">this
|
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<br><span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>"
|
||||||
documentation</a>.</p>
|
id="isCloudflareTunnel" label="Cloudflare Tunnel" />
|
||||||
</x-slot:explanation>
|
</div>
|
||||||
</x-boarding-step>
|
<x-forms.button type="submit">Continue</x-forms.button>
|
||||||
@endif
|
</form>
|
||||||
</div>
|
</x-slot:actions>
|
||||||
{{-- <div>
|
<x-slot:explanation>
|
||||||
@if ($currentState === 'select-proxy')
|
<p>Username should be <x-highlighted text="root" /> for now. We are working on to use
|
||||||
<x-boarding-step title="Select a Proxy">
|
non-root users.</p>
|
||||||
<x-slot:question>
|
</x-slot:explanation>
|
||||||
If you would like to attach any kind of domain to your resources, you need a proxy.
|
</x-boarding-step>
|
||||||
</x-slot:question>
|
@endif
|
||||||
<x-slot:actions>
|
</div>
|
||||||
<x-forms.button wire:click="selectProxy" class="w-64 box">
|
<div>
|
||||||
Decide later
|
@if ($state === 'validate-server')
|
||||||
</x-forms.button>
|
<x-boarding-step title="Validate & Configure Server">
|
||||||
<x-forms.button class="w-32 box" wire:click="selectProxy('{{ ProxyTypes::TRAEFIK_V2 }}')">
|
<x-slot:question>
|
||||||
Traefik
|
I need to validate your server (connection, Docker Engine, etc) and configure if something is
|
||||||
v2
|
missing for me. Are you okay with this?
|
||||||
</x-forms.button>
|
</x-slot:question>
|
||||||
<x-forms.button disabled class="w-32 box">
|
<x-slot:actions>
|
||||||
Nginx
|
<x-slide-over closeWithX fullScreen>
|
||||||
</x-forms.button>
|
<x-slot:title>Validate & configure</x-slot:title>
|
||||||
<x-forms.button disabled class="w-32 box">
|
<x-slot:content>
|
||||||
Caddy
|
<livewire:server.validate-and-install :server="$this->createdServer" />
|
||||||
</x-forms.button>
|
</x-slot:content>
|
||||||
</x-slot:actions>
|
<x-forms.button @click="slideOverOpen=true" class="font-bold box w-96"
|
||||||
<x-slot:explanation>
|
wire:click.prevent='installServer' isHighlighted>
|
||||||
<p>This will install the latest Docker Engine on your server, configure a few things to be able
|
Let's do it!
|
||||||
to run optimal.</p>
|
</x-forms.button>
|
||||||
</x-slot:explanation>
|
</x-slide-over>
|
||||||
</x-boarding-step>
|
</x-slot:actions>
|
||||||
@endif
|
<x-slot:explanation>
|
||||||
</div> --}}
|
<p>This will install the latest Docker Engine on your server, configure a few things to be able
|
||||||
<div>
|
to run optimal.<br><br>Minimum Docker Engine version is: 22<br><br>To manually install
|
||||||
@if ($currentState === 'create-project')
|
Docker
|
||||||
<x-boarding-step title="Project">
|
Engine, check <a target="_blank" class="underline text-warning"
|
||||||
<x-slot:question>
|
href="https://docs.docker.com/engine/install/#server">this
|
||||||
@if (count($projects) > 0)
|
documentation</a>.</p>
|
||||||
You already have some projects. Do you want to use one of them or should I create a new one for
|
</x-slot:explanation>
|
||||||
you?
|
</x-boarding-step>
|
||||||
@else
|
@endif
|
||||||
Let's create an initial project for you. You can change all the details later on.
|
</div>
|
||||||
@endif
|
<div>
|
||||||
</x-slot:question>
|
@if ($state === 'create-project')
|
||||||
<x-slot:actions>
|
<x-boarding-step title="Project">
|
||||||
<x-forms.button class="justify-center w-64 box" wire:click="createNewProject">Create new
|
<x-slot:question>
|
||||||
project!</x-forms.button>
|
|
||||||
<div>
|
|
||||||
@if (count($projects) > 0)
|
@if (count($projects) > 0)
|
||||||
<form wire:submit='selectExistingProject' class="flex flex-col w-full gap-4 lg:w-96">
|
You already have some projects. Do you want to use one of them or should I create a new one
|
||||||
<x-forms.select label="Existing projects" class="w-96"
|
for
|
||||||
id='selectedExistingProject'>
|
you?
|
||||||
@foreach ($projects as $project)
|
@else
|
||||||
<option wire:key="{{ $loop->index }}" value="{{ $project->id }}">
|
Let's create an initial project for you. You can change all the details later on.
|
||||||
{{ $project->name }}</option>
|
|
||||||
@endforeach
|
|
||||||
</x-forms.select>
|
|
||||||
<x-forms.button type="submit">Use this Project</x-forms.button>
|
|
||||||
</form>
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</x-slot:question>
|
||||||
</x-slot:actions>
|
<x-slot:actions>
|
||||||
<x-slot:explanation>
|
<x-forms.button class="justify-center w-64 box" wire:click="createNewProject">Create new
|
||||||
<p>Projects contain several resources combined into one virtual group. There are no
|
project!</x-forms.button>
|
||||||
limitations on the number of projects you can add.</p>
|
<div>
|
||||||
<p>Each project should have at least one environment, this allows you to create a production &
|
@if (count($projects) > 0)
|
||||||
staging version of the same application, but grouped separately.</p>
|
<form wire:submit='selectExistingProject' class="flex flex-col w-full gap-4 lg:w-96">
|
||||||
</x-slot:explanation>
|
<x-forms.select label="Existing projects" class="w-96" id='selectedProject'>
|
||||||
</x-boarding-step>
|
@foreach ($projects as $project)
|
||||||
@endif
|
<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>
|
||||||
|
</x-slot:actions>
|
||||||
|
<x-slot:explanation>
|
||||||
|
<p>Projects contain several resources combined into one virtual group. There are no
|
||||||
|
limitations on the number of projects you can add.</p>
|
||||||
|
<p>Each project should have at least one environment, this allows 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 ($state === 'create-resource')
|
||||||
|
<x-boarding-step title="Resources">
|
||||||
|
<x-slot:question>
|
||||||
|
Let's go to the new resource page, where you can create your first resource.
|
||||||
|
</x-slot:question>
|
||||||
|
<x-slot:actions>
|
||||||
|
<div class="items-center justify-center w-64 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>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</section>
|
||||||
@if ($currentState === 'create-resource')
|
|
||||||
<x-boarding-step title="Resources">
|
|
||||||
<x-slot:question>
|
|
||||||
Let's go to the new resource page, where you can create your first resource.
|
|
||||||
</x-slot:question>
|
|
||||||
<x-slot:actions>
|
|
||||||
<div class="items-center justify-center w-64 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>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<h1 class="title">Dashboard</h1>
|
<h1 class="title">Dashboard</h1>
|
||||||
{{-- <div class="subtitle">Your self-hosted environment</div> --}}
|
{{-- <div class="subtitle">Your self-hosted environment</div> --}}
|
||||||
@if (request()->query->get('success'))
|
@if (request()->query->get('success'))
|
||||||
<div class="mb-10 text-white rounded alert-success">
|
<div class="mb-10 rounded dark:text-white alert-success">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
||||||
viewBox="0 0 24 24">
|
viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
@ -22,26 +22,26 @@
|
|||||||
@if (data_get($project, 'environments')->count() === 1)
|
@if (data_get($project, 'environments')->count() === 1)
|
||||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||||
href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
|
href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
|
||||||
<div class="font-bold text-white">{{ $project->name }}</div>
|
<div class="box-title">{{ $project->name }}</div>
|
||||||
<div class="description">
|
<div class="box-description">
|
||||||
{{ $project->description }}</div>
|
{{ $project->description }}</div>
|
||||||
</a>
|
</a>
|
||||||
@else
|
@else
|
||||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||||
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
||||||
<div class="font-bold text-white">{{ $project->name }}</div>
|
<div class="box-title">{{ $project->name }}</div>
|
||||||
<div class="description">
|
<div class="box-description">
|
||||||
{{ $project->description }}</div>
|
{{ $project->description }}</div>
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
<div class="flex items-center">
|
<div class="flex items-center group">
|
||||||
<a class="mx-4 rounded group-hover:text-white hover:no-underline"
|
<a class="mx-4 rounded hover:no-underline"
|
||||||
href="{{ route('project.resource.create', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
|
href="{{ route('project.resource.create', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
|
||||||
<span class="font-bold hover:text-warning">+ Add Resource</span>
|
<span class="p-2 font-bold group-hover:dark:text-white group-hover:text-black dark:hover:bg-coollabs hover:bg-neutral-300">+ Add Resource</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="mx-4 rounded group-hover:text-white"
|
<a class="mx-4 rounded group-hover:dark:text-white group-hover:text-black"
|
||||||
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon hover:text-warning" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" class="icon hover:text-coollabs" viewBox="0 0 24 24"
|
||||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
stroke-linejoin="round">
|
stroke-linejoin="round">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
@ -54,9 +54,9 @@
|
|||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div>
|
<div>
|
||||||
No projects found. Add your first server <a class="text-white underline"
|
No projects found. Add your first server <a class="underline dark:text-white"
|
||||||
onclick="newEmptyProject.showModal()">here</a> or
|
onclick="newEmptyProject.showModal()">here</a> or
|
||||||
go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page.</a>
|
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding page.</a>
|
||||||
<livewire:project.add-empty />
|
<livewire:project.add-empty />
|
||||||
</div>
|
</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
@ -71,10 +71,10 @@
|
|||||||
'border-red-500' => !$server->settings->is_reachable,
|
'border-red-500' => !$server->settings->is_reachable,
|
||||||
])>
|
])>
|
||||||
<div class="flex flex-col mx-6">
|
<div class="flex flex-col mx-6">
|
||||||
<div class="font-bold text-white">
|
<div class="box-title">
|
||||||
{{ $server->name }}
|
{{ $server->name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="box-description">
|
||||||
{{ $server->description }}</div>
|
{{ $server->description }}</div>
|
||||||
<div class="flex gap-1 text-xs text-error">
|
<div class="flex gap-1 text-xs text-error">
|
||||||
@if (!$server->settings->is_reachable)
|
@if (!$server->settings->is_reachable)
|
||||||
@ -93,8 +93,9 @@
|
|||||||
@empty
|
@empty
|
||||||
<div>
|
<div>
|
||||||
No servers found.
|
No servers found.
|
||||||
Add your first server <a class="text-white underline" href="{{ route('server.create') }}">here</a> or
|
Add your first server <a class="underline dark:text-white" href="{{ route('server.create') }}">here</a>
|
||||||
go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page.</a>
|
or
|
||||||
|
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding page.</a>
|
||||||
</div>
|
</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
@ -116,15 +117,15 @@
|
|||||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||||
])>
|
])>
|
||||||
<div class="flex flex-col mx-6">
|
<div class="flex flex-col mx-6">
|
||||||
<div class="font-bold text-white">
|
<div class="box-title">
|
||||||
{{ data_get($deployment, 'application_name') }}
|
{{ data_get($deployment, 'application_name') }}
|
||||||
</div>
|
</div>
|
||||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||||
<div class="description">
|
<div class="box-description">
|
||||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="description">
|
<div class="box-description">
|
||||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle">All your projects.</div>
|
<div class="subtitle">All your projects are here.</div>
|
||||||
<div class="grid gap-2 lg:grid-cols-2">
|
<div class="grid gap-2 lg:grid-cols-2">
|
||||||
@if ($servers === 0)
|
@if ($servers === 0)
|
||||||
<div>
|
<div>
|
||||||
|
@ -52,7 +52,7 @@ class="items-center justify-center box">+ Add New Resource</a>
|
|||||||
<a class="h-24 box group" :href="item.hrefLink">
|
<a class="h-24 box group" :href="item.hrefLink">
|
||||||
<div class="flex flex-col w-full px-4 mx-2">
|
<div class="flex flex-col w-full px-4 mx-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
|
<div class="pb-2 box-title" x-text="item.name"></div>
|
||||||
<template x-if="item.status.startsWith('running')">
|
<template x-if="item.status.startsWith('running')">
|
||||||
<div title="running" class="mt-1 bg-success badge "></div>
|
<div title="running" class="mt-1 bg-success badge "></div>
|
||||||
</template>
|
</template>
|
||||||
@ -66,16 +66,16 @@ class="items-center justify-center box">+ Add New Resource</a>
|
|||||||
<div title="degraded" class="mt-1 bg-warning badge "></div>
|
<div title="degraded" class="mt-1 bg-warning badge "></div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="max-w-full truncate description" x-text="item.description"></div>
|
<div class="max-w-full truncate box-description" x-text="item.description"></div>
|
||||||
<div class="max-w-full truncate description" x-text="item.fqdn"></div>
|
<div class="max-w-full truncate box-description" x-text="item.fqdn"></div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
|
<div class="flex gap-1 pt-1 group-hover:dark:text-white group-hover:text-black group min-h-6">
|
||||||
<template x-for="tag in item.tags">
|
<template x-for="tag in item.tags">
|
||||||
<div class="px-2 py-1 cursor-pointer description bg-coolgray-100 hover:bg-coolgray-300"
|
<div class="px-2 py-1 cursor-pointer box-description dark:bg-coolgray-100 dark:hover:bg-coolgray-300 bg-neutral-100 hover:bg-neutral-200"
|
||||||
@click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
@click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
||||||
</template>
|
</template>
|
||||||
<div class="flex items-center px-2 text-xs cursor-pointer text-neutral-500/20 group-hover:text-white hover:bg-coolgray-300"
|
<div class="flex items-center px-2 text-xs cursor-pointer dark:text-neutral-500/20 text-neutral-500 group-hover:text-neutral-700 group-hover:dark:text-white dark:hover:bg-coolgray-300 hover:bg-neutral-200"
|
||||||
@click.prevent="goto(item)">Add tag</div>
|
@click.prevent="goto(item)">Add tag</div>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
@ -85,7 +85,7 @@ class="items-center justify-center box">+ Add New Resource</a>
|
|||||||
<a class="h-24 box group" :href="item.hrefLink">
|
<a class="h-24 box group" :href="item.hrefLink">
|
||||||
<div class="flex flex-col px-4 mx-2">
|
<div class="flex flex-col px-4 mx-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
|
<div class="pb-2 font-bold box-title" x-text="item.name"></div>
|
||||||
<template x-if="item.status.startsWith('running')">
|
<template x-if="item.status.startsWith('running')">
|
||||||
<div title="running" class="mt-1 bg-success badge "></div>
|
<div title="running" class="mt-1 bg-success badge "></div>
|
||||||
</template>
|
</template>
|
||||||
@ -99,10 +99,10 @@ class="items-center justify-center box">+ Add New Resource</a>
|
|||||||
<div title="degraded" class="mt-1 bg-warning badge "></div>
|
<div title="degraded" class="mt-1 bg-warning badge "></div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="max-w-full truncate description" x-text="item.description"></div>
|
<div class="max-w-full truncate box-description" x-text="item.description"></div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
|
<div class="flex gap-1 pt-1 group-hover:dark:text-white group-hover:text-black group min-h-6">
|
||||||
<template x-for="tag in item.tags">
|
<template x-for="tag in item.tags">
|
||||||
<div class="px-2 py-1 cursor-pointer description bg-coolgray-100 hover:bg-coolgray-300"
|
<div class="px-2 py-1 cursor-pointer description bg-coolgray-100 hover:bg-coolgray-300"
|
||||||
@click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
@click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<x-forms.button >+ Add</x-forms.button>
|
<x-forms.button >+ Add</x-forms.button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle">All your projects.</div>
|
<div class="subtitle">All your servers are here.</div>
|
||||||
|
|
||||||
<div class="grid gap-2 lg:grid-cols-2">
|
<div class="grid gap-2 lg:grid-cols-2">
|
||||||
@forelse ($servers as $server)
|
@forelse ($servers as $server)
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pb-4 ">Email settings for password resets, invitations, shared with Pro+ subscribers etc.</div>
|
<div class="pb-4 ">Email settings for password resets, invitations, shared with Pro+ subscribers etc.</div>
|
||||||
<form wire:submit='submitFromFields' class="pb-4">
|
<form wire:submit='submitFromFields' class="pb-4">
|
||||||
<div class="flex flex-col items-end w-full gap-2 xl:flex-row">
|
<div class="flex gap-2">
|
||||||
<x-forms.input required id="settings.smtp_from_name" helper="Name used in emails." label="From Name" />
|
<x-forms.input required id="settings.smtp_from_name" helper="Name used in emails." label="From Name" />
|
||||||
<x-forms.input required id="settings.smtp_from_address" helper="Email address used in emails."
|
<x-forms.input required id="settings.smtp_from_address" helper="Email address used in emails."
|
||||||
label="From Address" />
|
label="From Address" />
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if (isEmailEnabled($settings) && auth()->user()->isAdminFromSession() && isTestEmailEnabled($settings))
|
{{-- @if (isEmailEnabled($settings) && auth()->user()->isAdminFromSession() && isTestEmailEnabled($settings))
|
||||||
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
||||||
<form wire:submit='submit' class="flex flex-col gap-2">
|
<form wire:submit='submit' class="flex flex-col gap-2">
|
||||||
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
||||||
@ -21,16 +21,21 @@
|
|||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</form>
|
</form>
|
||||||
</x-modal-input>
|
</x-modal-input>
|
||||||
@endif
|
@endif --}}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="p-4 border border-coolgray-500">
|
<div class="p-4 border border-coolgray-500">
|
||||||
<h3>SMTP Server</h3>
|
|
||||||
<div class="w-32">
|
|
||||||
<x-forms.checkbox instantSave id="settings.smtp_enabled" label="Enabled" />
|
|
||||||
</div>
|
|
||||||
<form wire:submit='submit' class="flex flex-col">
|
<form wire:submit='submit' class="flex flex-col">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<h3>SMTP Server</h3>
|
||||||
|
<x-forms.button type="submit">
|
||||||
|
Save
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div class="w-32">
|
||||||
|
<x-forms.checkbox instantSave id="settings.smtp_enabled" label="Enabled" />
|
||||||
|
</div>
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||||
<x-forms.input required id="settings.smtp_host" placeholder="smtp.mailgun.org" label="Host" />
|
<x-forms.input required id="settings.smtp_host" placeholder="smtp.mailgun.org" label="Host" />
|
||||||
@ -45,30 +50,25 @@
|
|||||||
label="Timeout" />
|
label="Timeout" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end gap-4 pt-6">
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border border-coolgray-500">
|
||||||
|
<form wire:submit='submitResend' class="flex flex-col">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<h3>Resend</h3>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="w-32">
|
||||||
</div>
|
<x-forms.checkbox instantSave='instantSaveResend' id="settings.resend_enabled" label="Enabled" />
|
||||||
<div class="p-4 border border-coolgray-500">
|
</div>
|
||||||
<h3>Resend</h3>
|
|
||||||
<div class="w-32">
|
|
||||||
<x-forms.checkbox instantSave='instantSaveResend' id="settings.resend_enabled" label="Enabled" />
|
|
||||||
</div>
|
|
||||||
<form wire:submit='submitResend' class="flex flex-col">
|
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||||
<x-forms.input type="password" id="settings.resend_api_key" placeholder="API key" required
|
<x-forms.input type="password" id="settings.resend_api_key" placeholder="API key" required
|
||||||
label="Host" />
|
label="Host" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end gap-4 pt-6">
|
|
||||||
<x-forms.button type="submit">
|
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
@click.prevent="activeTab = 'smtp'; window.location.hash = 'smtp'" href="#">Transactional
|
@click.prevent="activeTab = 'smtp'; window.location.hash = 'smtp'" href="#">Transactional
|
||||||
Email</a>
|
Email</a>
|
||||||
<a :class="activeTab === 'auth' && 'text-white'"
|
<a :class="activeTab === 'auth' && 'text-white'"
|
||||||
@click.prevent="activeTab = 'auth'; window.location.hash = 'auth'" href="#">Authentication</a>
|
@click.prevent="activeTab = 'auth'; window.location.hash = 'auth'" href="#">Authentication (OAuth)</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full pl-8">
|
<div class="w-full pl-8">
|
||||||
<div x-cloak x-show="activeTab === 'general'" class="h-full">
|
<div x-cloak x-show="activeTab === 'general'" class="h-full">
|
||||||
|
Loading…
Reference in New Issue
Block a user