Added +add flows everywhere

ui: changed vibrant button to not so vibrant
This commit is contained in:
Andras Bacsai 2023-07-26 13:23:47 +02:00
parent 8deeb59d5c
commit fd89735521
40 changed files with 578 additions and 274 deletions

View File

@ -3,15 +3,16 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Project; use App\Models\Project;
use App\Models\Server;
class ProjectController extends Controller class ProjectController extends Controller
{ {
public function all() public function all()
{ {
$teamId = session('currentTeam')->id; return view('projects', [
'projects' => Project::ownedByCurrentTeam()->get(),
$projects = Project::where('team_id', $teamId)->get(); 'servers' => Server::ownedByCurrentTeam()->count(),
return view('projects', ['projects' => $projects]); ]);
} }
public function edit() public function edit()
@ -34,9 +35,6 @@ public function show()
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
$project->load(['environments']); $project->load(['environments']);
if (count($project->environments) == 1) {
return redirect()->route('project.resources', ['project_uuid' => $project->uuid, 'environment_name' => $project->environments->first()->name]);
}
return view('project.show', ['project' => $project]); return view('project.show', ['project' => $project]);
} }

View File

@ -7,7 +7,7 @@
class Create extends Component class Create extends Component
{ {
protected string|null $from = null; public string|null $from = null;
public string $name; public string $name;
public string|null $description = null; public string|null $description = null;
public string $value; public string $value;

View File

@ -0,0 +1,36 @@
<?php
namespace App\Http\Livewire\Project;
use App\Models\Project;
use Livewire\Component;
class AddEmpty extends Component
{
public string $name = '';
public string $description = '';
protected $rules = [
'name' => 'required|string|min:3',
'description' => 'nullable|string',
];
protected $validationAttributes = [
'name' => 'Project Name',
'description' => 'Project Description',
];
public function submit()
{
try {
$this->validate();
$project = Project::create([
'name' => $this->name,
'description' => $this->description,
'team_id' => auth()->user()->currentTeam()->id,
]);
return redirect()->route('project.show', $project->uuid);
} catch (\Exception $e) {
general_error_handler($e, $this);
} finally {
$this->name = '';
}
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Livewire\Project;
use App\Models\Environment;
use App\Models\Project;
use Livewire\Component;
class AddEnvironment extends Component
{
public Project $project;
public string $name = '';
public string $description = '';
protected $rules = [
'name' => 'required|string|min:3',
];
protected $validationAttributes = [
'name' => 'Environment Name',
];
public function submit()
{
try {
$this->validate();
$environment = Environment::create([
'name' => $this->name,
'project_id' => $this->project->id,
]);
return redirect()->route('project.resources', [
'project_uuid' => $this->project->uuid,
'environment_name' => $environment->name,
]);
} catch (\Exception $e) {
general_error_handler($e, $this);
} finally {
$this->name = '';
}
}
}

View File

@ -15,6 +15,7 @@
class GithubPrivateRepository extends Component class GithubPrivateRepository extends Component
{ {
public $current_step = 'github_apps';
public $github_apps; public $github_apps;
public GithubApp $github_app; public GithubApp $github_app;
public $parameters; public $parameters;
@ -90,6 +91,7 @@ public function loadRepositories($github_app_id)
} }
} }
$this->selected_repository_id = $this->repositories[0]['id']; $this->selected_repository_id = $this->repositories[0]['id'];
$this->current_step = 'repository';
} }
public function loadBranches() public function loadBranches()
{ {

View File

@ -14,6 +14,7 @@
class GithubPrivateRepositoryDeployKey extends Component class GithubPrivateRepositoryDeployKey extends Component
{ {
public $current_step = 'private_keys';
public $parameters; public $parameters;
public $query; public $query;
public $private_keys; public $private_keys;
@ -70,6 +71,7 @@ public function instantSave()
public function setPrivateKey($private_key_id) public function setPrivateKey($private_key_id)
{ {
$this->private_key_id = $private_key_id; $this->private_key_id = $private_key_id;
$this->current_step = 'repository';
} }
private function get_git_source() private function get_git_source()
{ {

View File

@ -82,7 +82,9 @@ public function load_branch()
$this->get_git_source(); $this->get_git_source();
try { try {
$this->get_branch(); $this->get_branch();
$this->selected_branch = $this->git_branch;
} catch (\Exception $e) { } catch (\Exception $e) {
return general_error_handler(err: $e, that: $this);
} }
if (!$this->branch_found && $this->git_branch == 'main') { if (!$this->branch_found && $this->git_branch == 'main') {

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Livewire\Project\New;
use App\Models\Server;
use Livewire\Component;
class Select extends Component
{
public $current_step = 'type';
public string $type;
public string $server_id;
public string $destination_uuid;
public $servers = [];
public $destinations = [];
public array $parameters;
public function mount()
{
$this->parameters = getRouteParameters();
}
public function set_type(string $type)
{
$this->type = $type;
$this->current_step = 'servers';
}
public function set_server(Server $server)
{
$this->server_id = $server->id;
$this->destinations = $server->destinations();
$this->current_step = 'destinations';
}
public function set_destination(string $destination_uuid)
{
$this->destination_uuid = $destination_uuid;
redirect()->route('project.resources.new', [
'project_uuid' => $this->parameters['project_uuid'],
'environment_name' => $this->parameters['environment_name'],
'type' => $this->type,
'destination' => $this->destination_uuid,
]);
}
public function load_servers()
{
$this->servers = Server::ownedByCurrentTeam()->get();
}
}

View File

@ -15,6 +15,10 @@ protected static function booted()
'project_id' => $project->id, 'project_id' => $project->id,
]); ]);
}); });
static::deleted(function ($project) {
$project->environments()->delete();
$project->settings()->delete();
});
} }
protected $fillable = [ protected $fillable = [
'name', 'name',

View File

@ -15,7 +15,7 @@ public function __construct(
public bool $disabled = false, public bool $disabled = false,
public bool $isModal = false, public bool $isModal = false,
public string|null $modalId = null, public string|null $modalId = null,
public string $defaultClass = "btn btn-primary btn-xs text-white normal-case no-animation rounded border-none" public string $defaultClass = "btn btn-primary btn-sm font-normal text-white normal-case no-animation rounded border-none"
) { ) {
// //
} }

View File

@ -9,7 +9,7 @@ body {
@apply text-sm antialiased scrollbar; @apply text-sm antialiased scrollbar;
} }
button[isError] { button[isError] {
@apply bg-red-600 hover:bg-red-500; @apply bg-red-600 hover:bg-red-700;
} }
.scrollbar { .scrollbar {
@apply scrollbar-thumb-coollabs-100 scrollbar-track-coolgray-200 scrollbar-w-2; @apply scrollbar-thumb-coollabs-100 scrollbar-track-coolgray-200 scrollbar-w-2;
@ -17,37 +17,17 @@ .scrollbar {
.main { .main {
@apply max-w-screen-xl pt-4 pl-24 pr-10 mx-auto; @apply max-w-screen-xl pt-4 pl-24 pr-10 mx-auto;
} }
/* input {
@apply w-full text-white rounded outline-none input input-sm h-7 placeholder:text-neutral-700 bg-coolgray-200 read-only:bg-coolgray-200/50 read-only:text-opacity-25;
}
input:not(input[type="checkbox"]) {
@apply border-none disabled:border-none;
}
input[type="checkbox"] {
@apply rounded toggle toggle-warning toggle-xs disabled:toggle-warning;
} */
/* textarea {
@apply text-xs leading-5 text-white rounded textarea read-only:bg-coolgray-200/50 disabled:border-none read-only:text-opacity-25 placeholder:text-neutral-700 scrollbar bg-coolgray-200;
}
select {
@apply font-normal text-white border-none rounded h-7 select select-xs disabled:bg-coolgray-200 disabled:opacity-50 placeholder:text-neutral-700 bg-coolgray-200;
} */
.label-text, .label-text,
label { label {
@apply text-neutral-400; @apply text-neutral-400;
} }
.navbar-main {
@apply flex items-end gap-6 py-2 border-b-2 border-solid border-coolgray-200;
}
.loading { .loading {
@apply w-4 text-warning; @apply w-4 text-warning;
} }
/* button[isWarning] {
@apply bg-red-600 hover:bg-red-500;
}
button[isHighlighted] {
@apply text-white btn-primary;
} */
h1 { h1 {
@apply text-3xl font-bold text-white; @apply text-3xl font-bold text-white;
} }

View File

@ -1,23 +1,12 @@
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<div class="group"> <div class="group">
<label tabindex="0" class="flex items-center gap-2 cursor-pointer hover:text-white"> Actions <label tabindex="0" class="flex items-center gap-2 cursor-pointer hover:text-white"> Advanced
<x-chevron-down /> <x-chevron-down />
</label> </label>
<div class="absolute hidden group-hover:block "> <div class="absolute hidden group-hover:block ">
<ul tabindex="0" <ul tabindex="0"
class="relative text-xs text-white normal-case rounded -ml-44 min-w-max menu bg-coolgray-200"> class="relative text-xs text-white normal-case rounded -ml-44 min-w-max menu bg-coolgray-200">
@if ($application->status === 'running') @if ($application->status === 'running')
<li>
<div class="rounded-none hover:bg-coollabs hover:text-white" wire:click='deploy'><svg
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
<path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
<path d="M12 9l0 3" />
<path d="M12 15l.01 0" />
</svg>Restart</div>
</li>
<li> <li>
<div class="rounded-none hover:bg-coollabs hover:text-white" <div class="rounded-none hover:bg-coollabs hover:text-white"
wire:click='force_deploy_without_cache'><svg xmlns="http://www.w3.org/2000/svg" wire:click='force_deploy_without_cache'><svg xmlns="http://www.w3.org/2000/svg"
@ -34,31 +23,7 @@ class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
cache) cache)
</div> </div>
</li> </li>
<li>
<div class="rounded-none hover:bg-red-500 hover:text-white" wire:click='stop'><svg
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M8 13v-7.5a1.5 1.5 0 0 1 3 0v6.5" />
<path d="M11 5.5v-2a1.5 1.5 0 1 1 3 0v8.5" />
<path d="M14 5.5a1.5 1.5 0 0 1 3 0v6.5" />
<path
d="M17 7.5a1.5 1.5 0 0 1 3 0v8.5a6 6 0 0 1 -6 6h-2h.208a6 6 0 0 1 -5.012 -2.7a69.74 69.74 0 0 1 -.196 -.3c-.312 -.479 -1.407 -2.388 -3.286 -5.728a1.5 1.5 0 0 1 .536 -2.022a1.867 1.867 0 0 1 2.28 .28l1.47 1.47" />
</svg>Stop</div>
</li>
@else @else
<li>
<div class="rounded-none hover:bg-coollabs hover:text-white" wire:click='deploy'><svg
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M7 4v16l13 -8z" />
</svg>Deploy</div>
</li>
<li>
</li>
<li> <li>
<div class="rounded-none hover:bg-coollabs hover:text-white" wire:click='deploy(true)'><svg <div class="rounded-none hover:bg-coollabs hover:text-white" wire:click='deploy(true)'><svg
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24"

View File

@ -1,4 +1,4 @@
<div class="flex items-end gap-4 py-2 border-b-2 border-solid border-coolgray-200"> <div class="navbar-main">
<a class="{{ request()->routeIs('project.application.configuration') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('project.application.configuration') ? 'text-white' : '' }}"
href="{{ route('project.application.configuration', $parameters) }}"> href="{{ route('project.application.configuration', $parameters) }}">
<button>Configuration</button> <button>Configuration</button>
@ -7,7 +7,38 @@
href="{{ route('project.application.deployments', $parameters) }}"> href="{{ route('project.application.deployments', $parameters) }}">
<button>Deployments</button> <button>Deployments</button>
</a> </a>
<div class="flex-1"></div>
<x-applications.links :application="$application" /> <x-applications.links :application="$application" />
<x-applications.actions :application="$application" /> <div class="flex-1"></div>
<x-applications.advanced :application="$application" />
@if ($application->status === 'running')
<button wire:click='deploy' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24" stroke-width="2"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path
d="M10.09 4.01l.496 -.495a2 2 0 0 1 2.828 0l7.071 7.07a2 2 0 0 1 0 2.83l-7.07 7.07a2 2 0 0 1 -2.83 0l-7.07 -7.07a2 2 0 0 1 0 -2.83l3.535 -3.535h-3.988">
</path>
<path d="M7.05 11.038v-3.988"></path>
</svg>
Restart
</button>
<button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24" stroke-width="2"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path>
<path d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path>
</svg>
Stop
</button>
@else
<button wire:click='deploy' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M7 4v16l13 -8z" />
</svg>Deploy
</button>
@endif
</div> </div>

View File

@ -10,7 +10,7 @@ class="flex items-center gap-1 mb-2 text-sm font-medium text-neutral-400">{{ $la
@endif @endif
</label> </label>
@endif @endif
<select {{ $attributes->merge(['class' => $defaultClass]) }} @required($required) <select {{ $attributes->merge(['class' => $defaultClass]) }} @required($required) wire:dirty.class.remove='text-white'
wire:dirty.class="text-black bg-warning" wire:loading.attr="disabled" name={{ $id }} wire:dirty.class="text-black bg-warning" wire:loading.attr="disabled" name={{ $id }}
@if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} @else wire:model.defer={{ $id }} @endif> @if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} @else wire:model.defer={{ $id }} @endif>
{{ $slot }} {{ $slot }}

View File

@ -10,6 +10,21 @@
</svg> </svg>
</a> </a>
</li> </li>
<li title="Servers">
<a class="hover:bg-transparent" @if (!request()->is('servers')) href="/servers" @endif>
<svg xmlns="http://www.w3.org/2000/svg"
class="{{ request()->is('server/*') || request()->is('servers') ? 'text-warning icon' : 'icon' }}"
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M3 4m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z" />
<path d="M15 20h-9a3 3 0 0 1 -3 -3v-2a3 3 0 0 1 3 -3h12" />
<path d="M7 8v.01" />
<path d="M7 16v.01" />
<path d="M20 15l-2 3h3l-2 3" />
</svg>
</a>
</li>
<li title="Projects"> <li title="Projects">
<a class="hover:bg-transparent" @if (!request()->is('projects')) href="/projects" @endif> <a class="hover:bg-transparent" @if (!request()->is('projects')) href="/projects" @endif>
<svg xmlns="http://www.w3.org/2000/svg" <svg xmlns="http://www.w3.org/2000/svg"
@ -24,21 +39,7 @@ class="{{ request()->is('project/*') || request()->is('projects') ? 'text-warnin
</a> </a>
</li> </li>
<li title="Servers">
<a class="hover:bg-transparent" @if (!request()->is('servers')) href="/servers" @endif>
<svg xmlns="http://www.w3.org/2000/svg"
class="{{ request()->is('server/*') || request()->is('servers') ? 'text-warning icon' : 'icon' }}"
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M3 4m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z" />
<path d="M15 20h-9a3 3 0 0 1 -3 -3v-2a3 3 0 0 1 3 -3h12" />
<path d="M7 8v.01" />
<path d="M7 16v.01" />
<path d="M20 15l-2 3h3l-2 3" />
</svg>
</a>
</li>
@if (auth()->user()->isInstanceAdmin()) @if (auth()->user()->isInstanceAdmin())
<li title="Command Center"> <li title="Command Center">
<a class="hover:bg-transparent" @if (!request()->is('command-center')) href="/command-center" @endif> <a class="hover:bg-transparent" @if (!request()->is('command-center')) href="/command-center" @endif>

View File

@ -1,7 +1,7 @@
<div class="pb-6"> <div class="pb-6">
<h1>Server</h1> <h1>Server</h1>
<div class="pt-2 pb-10 ">{{ data_get($server, 'name') }}</div> <div class="pt-2 pb-10 ">{{ data_get($server, 'name') }}</div>
<nav class="flex items-end gap-4 py-2 border-b-2 border-solid border-coolgray-200"> <nav class="navbar-main">
<a class="{{ request()->routeIs('server.show') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('server.show') ? 'text-white' : '' }}"
href="{{ route('server.show', [ href="{{ route('server.show', [
'server_uuid' => Route::current()->parameters()['server_uuid'], 'server_uuid' => Route::current()->parameters()['server_uuid'],

View File

@ -1,7 +1,7 @@
<div class="pb-6"> <div class="pb-6">
<h1>Settings</h1> <h1>Settings</h1>
<div class="pt-2 pb-10 ">Instance wide settings for Coolify.</div> <div class="pt-2 pb-10 ">Instance wide settings for Coolify.</div>
<nav class="flex items-end gap-4 py-2 border-b-2 border-solid border-coolgray-200"> <nav class="navbar-main">
<a class="{{ request()->routeIs('settings.configuration') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('settings.configuration') ? 'text-white' : '' }}"
href="{{ route('settings.configuration') }}"> href="{{ route('settings.configuration') }}">
<button>Configuration</button> <button>Configuration</button>

View File

@ -20,7 +20,7 @@
@endif @endif
</ol> </ol>
</nav> </nav>
<nav class="flex items-end gap-4 py-2 border-b-2 border-solid border-coolgray-200"> <nav class="navbar-main">
<a class="{{ request()->routeIs('team.show') ? 'text-white' : '' }}" href="{{ route('team.show') }}"> <a class="{{ request()->routeIs('team.show') ? 'text-white' : '' }}" href="{{ route('team.show') }}">
<button>General</button> <button>General</button>
</a> </a>

View File

@ -1,2 +1,10 @@
<br><br>Use the magic <div class="pt-4">
@if (isset($link))
Use the magic
bar (press <span class="kbd-custom">/</span>) to create a new one or <a href="{{ $link }}"
class="underline text-warning">click here</a>.
@else
Use the magic
bar (press <span class="kbd-custom">/</span>) to create a new one. bar (press <span class="kbd-custom">/</span>) to create a new one.
@endif
</div>

View File

@ -8,7 +8,7 @@
Save Save
</x-forms.button> </x-forms.button>
@if ($private_key->id > 0) @if ($private_key->id > 0)
<x-forms.button x-on:click.prevent="deletePrivateKey = true"> <x-forms.button isError x-on:click.prevent="deletePrivateKey = true">
Delete Delete
</x-forms.button> </x-forms.button>
@endif @endif

View File

@ -0,0 +1,12 @@
<dialog id="newEmptyProject" class="modal">
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit.prevent='submit'>
<x-forms.input placeholder="Your Cool Project" id="name" label="Name" required />
<x-forms.input placeholder="This is my cool project everyone knows about" id="description" label="Description" />
<x-forms.button onclick="newEmptyProject.close()" type="submit">
Save
</x-forms.button>
</form>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>

View File

@ -0,0 +1,11 @@
<dialog id="newEnvironment" class="modal">
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit.prevent='submit'>
<x-forms.input placeholder="production" id="name" label="Name" required />
<x-forms.button onclick="newEnvironment.close()" type="submit">
Save
</x-forms.button>
</form>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>

View File

@ -34,18 +34,19 @@
<x-forms.input placeholder="HEAD" id="application.git_commit_sha" placeholder="HEAD" label="Commit SHA" /> <x-forms.input placeholder="HEAD" id="application.git_commit_sha" placeholder="HEAD" label="Commit SHA" />
</div> </div>
@isset($application->private_key_id)
<h3 class="pt-4">Deploy Key</h3>
<div class="py-2 pt-4">Currently attache Private Key: <span
class="text-warning">{{ $application->private_key->name }}</span>
</div>
@if ($application->private_key_id) <h4 class="py-2 ">Select another Private Key</h4>
<h4 class="py-2 pt-4">Current Deploy Key: <span
class="text-warning">{{ $application->private_key->name }}</span></h4>
<div class="py-2 ">Select another Deploy Key</div>
<div class="flex gap-2"> <div class="flex gap-2">
@foreach ($private_keys as $key) @foreach ($private_keys as $key)
<x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }} <x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
</x-forms.button> </x-forms.button>
@endforeach @endforeach
</div> </div>
@endif @endisset
</form> </form>
</div> </div>

View File

@ -1,7 +1,7 @@
<div x-data="{ deleteEnvironment: false }"> <div x-data="{ deleteEnvironment: false }">
<x-naked-modal show="deleteEnvironment" title="Delete Environment" <x-naked-modal show="deleteEnvironment" title="Delete Environment"
message='This environment will be deleted. It is not reversible. <br>Please think again.' /> message='This environment will be deleted. It is not reversible. <br>Please think again.' />
<x-forms.button x-on:click.prevent="deleteEnvironment = true"> <x-forms.button isError x-on:click.prevent="deleteEnvironment = true">
Delete Environment Delete Environment
</x-forms.button> </x-forms.button>
</div> </div>

View File

@ -1,7 +1,7 @@
<div x-data="{ deleteProject: false }"> <div x-data="{ deleteProject: false }">
<x-naked-modal show="deleteProject" title="Delete Project" <x-naked-modal show="deleteProject" title="Delete Project"
message='This project will be deleted. It is not reversible. <br>Please think again.' /> message='This project will be deleted. It is not reversible. <br>Please think again.' />
<x-forms.button x-on:click.prevent="deleteProject = true"> <x-forms.button isError x-on:click.prevent="deleteProject = true">
Delete Project Delete Project
</x-forms.button> </x-forms.button>
</div> </div>

View File

@ -3,6 +3,9 @@
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<h1>Project: {{ data_get($project, 'name') }}</h1> <h1>Project: {{ data_get($project, 'name') }}</h1>
<x-forms.button type="submit">Save</x-forms.button> <x-forms.button type="submit">Save</x-forms.button>
@if ($project->applications->count() === 0)
<livewire:project.delete-project :project_id="$project->id" />
@endif
</div> </div>
<div class="pb-10">Edit project details here.</div> <div class="pb-10">Edit project details here.</div>
<div class="flex gap-2"> <div class="flex gap-2">

View File

@ -1,32 +1,56 @@
<div> <div>
<h1>Create a new Application</h1> <h1>Create a new Application</h1>
<div class="pt-2 pb-10">Deploy any public or private GIT repositories through a Deploy Key.</div> <div class="pt-2">Deploy any public or private Git repositories through a Deploy Key.</div>
<h3 class="py-2">Select a Private Key</h3> <div class="flex flex-col pt-10">
@if ($current_step === 'private_keys')
<ul class="pb-10 steps">
<li class="step step-secondary">Select a Private Key</li>
<li class="step">Select a Repository, Branch & Save</li>
</ul>
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
@foreach ($private_keys as $key) @foreach ($private_keys as $key)
@if ($private_key_id == $key->id) @if ($private_key_id == $key->id)
<x-forms.button class="bg-coollabs hover:bg-coollabs-100" <div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click.defer="setPrivateKey('{{ $key->id }}')"> wire:click.defer="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
{{ $key->name }}</x-forms.button> <div class="flex gap-4 mx-6">
<div class="group-hover:text-white">
{{ $key->name }}
</div>
<span wire:target="loadRepositories" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@else @else
<x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }} <div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
</x-forms.button> wire:click.defer="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
<div class="flex gap-4 mx-6">
<div class="group-hover:text-white">
{{ $key->name }}
</div>
<span wire:target="loadRepositories" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@endif @endif
@endforeach @endforeach
<a href="{{ route('private-key.new') }}"> </div>
<x-forms.button isHighlighted>+</x-forms.button> @endif
</a> @if ($current_step === 'repository')
@isset($private_key_id) <ul class="pb-10 steps">
<li class="step step-secondary">Select a Private Key</li>
<li class="step step-secondary">Select a Repository, Branch & Save</li>
</ul>
<form class="flex flex-col gap-2 pb-6" wire:submit.prevent='submit'> <form class="flex flex-col gap-2 pb-6" wire:submit.prevent='submit'>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input id="repository_url" label="Repository URL" helper="{!! __('repository.url') !!}" /> <x-forms.input id="repository_url" required label="Repository URL"
<x-forms.input id="branch" label="Branch" /> helper="{!! __('repository.url') !!}" />
<x-forms.input id="branch" required label="Branch" />
@if ($is_static) @if ($is_static)
<x-forms.input id="publish_directory" label="Publish Directory" /> <x-forms.input id="publish_directory" required label="Publish Directory" />
@else @else
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static" /> <x-forms.input type="number" required id="port" label="Port" :readonly="$is_static" />
@endif @endif
</div> </div>
<h4 class="pt-4">Settings</h4>
<div class="w-52"> <div class="w-52">
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?" <x-forms.checkbox instantSave id="is_static" label="Is it a static site?"
helper="If your application is a static site or the final build assets should be served as a static site, enable this." /> helper="If your application is a static site or the final build assets should be served as a static site, enable this." />
@ -35,5 +59,6 @@
Save New Application Save New Application
</x-forms.button> </x-forms.button>
</form> </form>
@endisset @endif
</div>
</div> </div>

View File

@ -2,23 +2,46 @@
<h1>Create a new Application</h1> <h1>Create a new Application</h1>
<div class="pb-4 ">Deploy any public or private git repositories through a GitHub App.</div> <div class="pb-4 ">Deploy any public or private git repositories through a GitHub App.</div>
@if ($github_apps->count() > 0) @if ($github_apps->count() > 0)
<form class="flex flex-col" wire:submit.prevent='submit'> <div class="flex flex-col pt-10">
<div class="flex flex-col gap-2"> @if ($current_step === 'github_apps')
<h3 class="py-2">Select a GitHub App</h3> <ul class="pb-10 steps">
<li class="step step-secondary">Select a GitHub App</li>
<li class="step">Select a Repository, Branch & Save</li>
</ul>
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
@foreach ($github_apps as $ghapp) @foreach ($github_apps as $ghapp)
@if ($selected_github_app_id == $ghapp->id) @if ($selected_github_app_id == $ghapp->id)
<x-forms.button class="bg-coollabs hover:bg-coollabs-100 h-7" wire:key="{{ $ghapp->id }}" <div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click.prevent="loadRepositories({{ $ghapp->id }})"> wire:click.prevent="loadRepositories({{ $ghapp->id }})" wire:key="{{ $ghapp->id }}">
<div class="flex gap-4 mx-6">
<div class="group-hover:text-white">
{{ $ghapp->name }} {{ $ghapp->name }}
</x-forms.button> </div>
<span wire:target="loadRepositories" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@else @else
<x-forms.button wire:key="{{ $ghapp->id }}" <div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click.prevent="loadRepositories({{ $ghapp->id }})"> wire:click.prevent="loadRepositories({{ $ghapp->id }})"
wire:key="{{ $ghapp->id }}">
<div class="flex gap-4 mx-6">
<div class="group-hover:text-white">
{{ $ghapp->name }} {{ $ghapp->name }}
</x-forms.button> </div>
<span wire:target="loadRepositories" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@endif @endif
@endforeach @endforeach
<div class="flex flex-col"> </div>
@endif
@if ($current_step === 'repository')
<ul class="pb-10 steps">
<li class="step step-secondary">Select a GitHub App</li>
<li class="step step-secondary">Select a Repository, Branch & Save</li>
</ul>
@if ($repositories->count() > 0) @if ($repositories->count() > 0)
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<x-forms.select class="w-full" label="Repository URL" helper="{!! __('repository.url') !!}" <x-forms.select class="w-full" label="Repository URL" helper="{!! __('repository.url') !!}"
@ -37,9 +60,13 @@
<x-forms.button wire:click.prevent="loadBranches"> Check <x-forms.button wire:click.prevent="loadBranches"> Check
repository</x-forms.button> repository</x-forms.button>
</div> </div>
@else
<div>No repositories found. Check your GitHub App configuration.</div>
@endif @endif
</div>
@if ($branches->count() > 0) @if ($branches->count() > 0)
<h3 class="pt-8 pb-2">Details</h3>
<div class="flex flex-col gap-2 pb-6">
<form class="flex flex-col" wire:submit.prevent='submit'>
<div class="flex flex-col gap-2 pb-6"> <div class="flex flex-col gap-2 pb-6">
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.select id="selected_branch_name" label="Branch"> <x-forms.select id="selected_branch_name" label="Branch">
@ -64,7 +91,6 @@
helper="The port your application listens on." /> helper="The port your application listens on." />
@endif @endif
</div> </div>
<h4 class="pt-4">Settings</h4>
<div class="w-52"> <div class="w-52">
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?" <x-forms.checkbox instantSave id="is_static" label="Is it a static site?"
helper="If your application is a static site or the final build assets should be served as a static site, enable this." /> helper="If your application is a static site or the final build assets should be served as a static site, enable this." />
@ -74,8 +100,8 @@
Save New Application Save New Application
</x-forms.button> </x-forms.button>
@endif @endif
@endif
</div> </div>
</form>
@else @else
<div> <div>
<div>No Git App found.</div> <div>No Git App found.</div>

View File

@ -1,6 +1,6 @@
<div> <div>
<h1>Create a new Application</h1> <h1>Create a new Application</h1>
<div class="pb-4">Deploy any public git repositories.</div> <div class="pb-4">Deploy any public Git repositories.</div>
<form class="flex flex-col gap-2" wire:submit.prevent> <form class="flex flex-col gap-2" wire:submit.prevent>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="flex flex-col"> <div class="flex flex-col">
@ -12,10 +12,14 @@
</x-forms.button> </x-forms.button>
</div> </div>
@if ($branch_found) @if ($branch_found)
<div class="py-2"> @if ($rate_limit_remaining && $rate_limit_reset)
<div>Rate limit remaining: {{ $rate_limit_remaining }}</div> <div class="flex gap-2 py-2">
<div>Rate limit reset at: {{ $rate_limit_reset }}</div> <div>Rate Limit</div>
<x-helper
helper="Rate limit remaining: {{ $rate_limit_remaining }}<br>Rate limit reset at: {{ $rate_limit_reset }}" />
</div> </div>
@endif
<h3 class="pt-8 pb-2">Details</h3>
<div class="flex flex-col gap-2 pb-6"> <div class="flex flex-col gap-2 pb-6">
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input disabled id="git_branch" label="Selected branch" <x-forms.input disabled id="git_branch" label="Selected branch"
@ -28,7 +32,6 @@
helper="The port your application listens on." /> helper="The port your application listens on." />
@endif @endif
</div> </div>
<h4 class="pt-4">Settings</h4>
<div class="w-52"> <div class="w-52">
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?" <x-forms.checkbox instantSave id="is_static" label="Is it a static site?"
helper="If your application is a static site or the final build assets should be served as a static site, enable this." /> helper="If your application is a static site or the final build assets should be served as a static site, enable this." />

View File

@ -0,0 +1,87 @@
<div x-data x-init="$wire.load_servers">
<h1>New Resource</h1>
<div class="pb-4 ">Deploy any Git repository from different sources.</div>
<div class="flex flex-col pt-10">
@if ($current_step === 'type')
<ul class="pb-10 steps">
<li class="step step-secondary">Application Type</li>
<li class="step">Select a Server</li>
<li class="step">Select a Destination</li>
</ul>
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click="set_type('public')">
<div class="flex flex-col mx-6">
<div class="group-hover:text-white">
Public Repository
</div>
<div class="text-xs group-hover:text-white">
You can deploy any kind of public repositories from the supported git servers.</div>
</div>
</div>
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click="set_type('private-gh-app')">
<div class="flex flex-col mx-6">
<div class="group-hover:text-white">
Private Repository
</div>
<div class="text-xs group-hover:text-white">
You can deploy public & private repositories through your GitHub Apps.</div>
</div>
</div>
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click="set_type('private-deploy-key')">
<div class="flex flex-col mx-6">
<div class="group-hover:text-white">
Private Repository (with deploy key)
</div>
<div class="text-xs group-hover:text-white">
You can deploy public & private repositories with a simple deploy key.</div>
</div>
</div>
</div>
@endif
@if ($current_step === 'servers')
<ul class="pb-10 steps">
<li class="step step-secondary">Application Type</li>
<li class="step step-secondary">Select a Server</li>
<li class="step">Select a Destination</li>
</ul>
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
@foreach ($servers as $server)
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click="set_server({{ $server }})">
<div class="flex flex-col mx-6">
<div class="group-hover:text-white">
{{ $server->name }}
</div>
<div class="text-xs group-hover:text-white">
{{ $server->description }}</div>
</div>
</div>
@endforeach
</div>
@endif
@if ($current_step === 'destinations')
<ul class="pb-10 steps">
<li class="step step-secondary">Application Type</li>
<li class="step step-secondary">Select a Server</li>
<li class="step step-secondary">Select a Destination</li>
</ul>
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
@foreach ($destinations as $destination)
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
wire:click="set_destination('{{ $destination->uuid }}')">
<div class="flex flex-col mx-6">
<div class="group-hover:text-white">
{{ $destination->name }}
</div>
<div class="text-xs group-hover:text-white">
{{ $destination->description }}</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>

View File

@ -1,5 +1,4 @@
<div x-data="{ changeLocalhost: false }"> <div x-data="{ changeLocalhost: false }">
@if ($server->settings->is_reachable)
<x-modal yesOrNo modalId="{{ $modalId }}" modalTitle="Delete Server"> <x-modal yesOrNo modalId="{{ $modalId }}" modalTitle="Delete Server">
<x-slot:modalBody> <x-slot:modalBody>
<p>This server will be deleted. It is not reversible. <br>Please think again..</p> <p>This server will be deleted. It is not reversible. <br>Please think again..</p>
@ -7,6 +6,9 @@
</x-modal> </x-modal>
<x-naked-modal show="changeLocalhost" action="submit" title="Change localhost" <x-naked-modal show="changeLocalhost" action="submit" title="Change localhost"
message='You could lost a lot of functionalities if you change the server details of the server where Coolify is running on.<br>Please think again.' /> message='You could lost a lot of functionalities if you change the server details of the server where Coolify is running on.<br>Please think again.' />
@if ($server->settings->is_reachable)
<form wire:submit.prevent='submit' class="flex flex-col"> <form wire:submit.prevent='submit' class="flex flex-col">
<div class="flex gap-2"> <div class="flex gap-2">
<h2>General</h2> <h2>General</h2>
@ -70,6 +72,13 @@
</div> </div>
@endisset @endisset
</form> </form>
@else
<div class="w-full pb-4">
<div class="cursor-pointer box" wire:click.prevent='validateServer'>
Validate Server
</div>
</div>
@endif
<h3>Danger Zone</h3> <h3>Danger Zone</h3>
<div class="">Woah. I hope you know what are you doing.</div> <div class="">Woah. I hope you know what are you doing.</div>
<h4 class="pt-4">Delete Server</h4> <h4 class="pt-4">Delete Server</h4>
@ -81,11 +90,4 @@
Delete Delete
</x-forms.button> </x-forms.button>
@endif @endif
@else
<div class="w-full">
<div class="cursor-pointer box" wire:click.prevent='validateServer'>
Validate Server
</div>
</div>
@endif
</div> </div>

View File

@ -7,9 +7,7 @@
<div class="flex gap-2"> <div class="flex gap-2">
@if ($github_app->app_id) @if ($github_app->app_id)
<x-forms.button type="submit">Save</x-forms.button> <x-forms.button type="submit">Save</x-forms.button>
<x-forms.button x-on:click.prevent="deleteSource = true">
Delete
</x-forms.button>
<a href="{{ get_installation_path($github_app) }}"> <a href="{{ get_installation_path($github_app) }}">
<x-forms.button> <x-forms.button>
@if ($github_app->installation_id) @if ($github_app->installation_id)
@ -21,9 +19,12 @@
@endif @endif
</x-forms.button> </x-forms.button>
</a> </a>
<x-forms.button isError x-on:click.prevent="deleteSource = true">
Delete
</x-forms.button>
@else @else
<x-forms.button disabled type="submit">Save</x-forms.button> <x-forms.button disabled type="submit">Save</x-forms.button>
<x-forms.button x-on:click.prevent="deleteSource = true"> <x-forms.button isError x-on:click.prevent="deleteSource = true">
Delete Delete
</x-forms.button> </x-forms.button>

View File

@ -12,7 +12,7 @@
@empty @empty
<div> <div>
<div>No private keys found.</div> <div>No private keys found.</div>
<x-use-magic-bar /> <x-use-magic-bar link="/private-key/new" />
</div> </div>
@endforelse @endforelse
</div> </div>

View File

@ -5,5 +5,7 @@
<livewire:project.new.github-private-repository :type="$type" /> <livewire:project.new.github-private-repository :type="$type" />
@elseif ($type === 'private-deploy-key') @elseif ($type === 'private-deploy-key')
<livewire:project.new.github-private-repository-deploy-key :type="$type" /> <livewire:project.new.github-private-repository-deploy-key :type="$type" />
@else
<livewire:project.new.select />
@endif @endif
</x-layout> </x-layout>

View File

@ -2,6 +2,9 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h1>Resources</h1> <h1>Resources</h1>
<a href="{{ route('project.resources.new', ['project_uuid' => request()->route('project_uuid'), 'environment_name' => request()->route('environment_name')]) }} "
class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation">+
Add</a>
@if ($environment->applications->count() === 0) @if ($environment->applications->count() === 0)
<livewire:project.delete-environment :environment_id="$environment->id" /> <livewire:project.delete-environment :environment_id="$environment->id" />
@endif @endif

View File

@ -1,9 +1,8 @@
<x-layout> <x-layout>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h1>Environments</h1> <h1>Environments</h1>
@if ($project->applications->count() === 0) <x-forms.button class="btn" onclick="newEnvironment.showModal()">+ Add</x-forms.button>
<livewire:project.delete-project :project_id="$project->id" /> <livewire:project.add-environment :project="$project" />
@endif
</div> </div>
<div class="pt-2 pb-10 text-xs truncate lg:text-sm">{{ $project->name }}</div> <div class="pt-2 pb-10 text-xs truncate lg:text-sm">{{ $project->name }}</div>
<div class="grid gap-2 lg:grid-cols-2"> <div class="grid gap-2 lg:grid-cols-2">

View File

@ -1,7 +1,19 @@
<x-layout> <x-layout>
<h1>Projects</h1> <div class="flex gap-2">
<h1>Projects</span></h1>
@if ($servers > 0)
<x-forms.button class="btn" onclick="newEmptyProject.showModal()">+ Add</x-forms.button>
<livewire:project.add-empty />
@endif
</div>
<div class="pt-2 pb-10 ">All Projects</div> <div class="pt-2 pb-10 ">All Projects</div>
<div class="grid gap-2 lg:grid-cols-2"> <div class="grid gap-2 lg:grid-cols-2">
@if ($servers === 0)
<div>
<div>No servers found. Without a server, you won't be able to do much.</div>
<x-use-magic-bar link="/server/new" />
</div>
@else
@forelse ($projects as $project) @forelse ($projects as $project)
<div class="gap-2 border border-transparent cursor-pointer box group" x-data <div class="gap-2 border border-transparent cursor-pointer box group" x-data
x-on:click="goto('{{ $project->uuid }}')"> x-on:click="goto('{{ $project->uuid }}')">
@ -29,6 +41,8 @@
<x-use-magic-bar /> <x-use-magic-bar />
</div> </div>
@endforelse @endforelse
@endif
<script> <script>
function goto(uuid) { function goto(uuid) {
window.location.href = '/project/' + uuid; window.location.href = '/project/' + uuid;

View File

@ -1,5 +1,5 @@
<x-layout> <x-layout>
<h1>Servers</h1> <h1>Servers</span></h1>
<div class="pt-2 pb-10 ">All Servers</div> <div class="pt-2 pb-10 ">All Servers</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)
@ -11,7 +11,6 @@
<div class="flex flex-col mx-6"> <div class="flex flex-col mx-6">
<div class=" group-hover:text-white"> <div class=" group-hover:text-white">
{{ $server->name }} {{ $server->name }}
</div> </div>
<div class="text-xs group-hover:text-white" <div class="text-xs group-hover:text-white"
href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"> href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}">
@ -33,7 +32,7 @@
@empty @empty
<div> <div>
<div>No servers found. Without a server, you won't be able to do much.</div> <div>No servers found. Without a server, you won't be able to do much.</div>
<x-use-magic-bar /> <x-use-magic-bar link="/server/new" />
</div> </div>
@endforelse @endforelse
<script> <script>

View File

@ -1,7 +1,7 @@
<x-layout> <x-layout>
@if ($private_keys->count() === 0) @if ($private_keys->count() === 0)
<h2>Create Private Key</h2> <h1>Create Private Key</h1>
<div>You need to create a private key before you can create a server.</div> <div class="pb-10">You need to create a private key before you can create a server.</div>
<livewire:private-key.create from="server" /> <livewire:private-key.create from="server" />
@else @else
<livewire:server.new.by-ip :private_keys="$private_keys" /> <livewire:server.new.by-ip :private_keys="$private_keys" />

View File

@ -39,7 +39,8 @@ module.exports = {
themes: [ themes: [
{ {
coollabs: { coollabs: {
primary: "#6B16ED", primary: "#323232",
"primary-focus": "#242424",
secondary: "#4338ca", secondary: "#4338ca",
accent: "#4338ca", accent: "#4338ca",
neutral: "#1B1D1D", neutral: "#1B1D1D",