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;
use App\Models\Project;
use App\Models\Server;
class ProjectController extends Controller
{
public function all()
{
$teamId = session('currentTeam')->id;
$projects = Project::where('team_id', $teamId)->get();
return view('projects', ['projects' => $projects]);
return view('projects', [
'projects' => Project::ownedByCurrentTeam()->get(),
'servers' => Server::ownedByCurrentTeam()->count(),
]);
}
public function edit()
@ -34,9 +35,6 @@ public function show()
return redirect()->route('dashboard');
}
$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]);
}

View File

@ -7,7 +7,7 @@
class Create extends Component
{
protected string|null $from = null;
public string|null $from = null;
public string $name;
public string|null $description = null;
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
{
public $current_step = 'github_apps';
public $github_apps;
public GithubApp $github_app;
public $parameters;
@ -90,6 +91,7 @@ public function loadRepositories($github_app_id)
}
}
$this->selected_repository_id = $this->repositories[0]['id'];
$this->current_step = 'repository';
}
public function loadBranches()
{

View File

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

View File

@ -82,7 +82,9 @@ public function load_branch()
$this->get_git_source();
try {
$this->get_branch();
$this->selected_branch = $this->git_branch;
} catch (\Exception $e) {
return general_error_handler(err: $e, that: $this);
}
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,
]);
});
static::deleted(function ($project) {
$project->environments()->delete();
$project->settings()->delete();
});
}
protected $fillable = [
'name',

View File

@ -15,7 +15,7 @@ public function __construct(
public bool $disabled = false,
public bool $isModal = false,
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"
) {
//
}
@ -27,4 +27,4 @@ public function render(): View|Closure|string
{
return view('components.forms.button');
}
}
}

View File

@ -9,7 +9,7 @@ body {
@apply text-sm antialiased scrollbar;
}
button[isError] {
@apply bg-red-600 hover:bg-red-500;
@apply bg-red-600 hover:bg-red-700;
}
.scrollbar {
@apply scrollbar-thumb-coollabs-100 scrollbar-track-coolgray-200 scrollbar-w-2;
@ -17,37 +17,17 @@ .scrollbar {
.main {
@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 {
@apply text-neutral-400;
}
.navbar-main {
@apply flex items-end gap-6 py-2 border-b-2 border-solid border-coolgray-200;
}
.loading {
@apply w-4 text-warning;
}
/* button[isWarning] {
@apply bg-red-600 hover:bg-red-500;
}
button[isHighlighted] {
@apply text-white btn-primary;
} */
h1 {
@apply text-3xl font-bold text-white;
}

View File

@ -1,23 +1,12 @@
<div class="flex items-center gap-2">
<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 />
</label>
<div class="absolute hidden group-hover:block ">
<ul tabindex="0"
class="relative text-xs text-white normal-case rounded -ml-44 min-w-max menu bg-coolgray-200">
@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>
<div class="rounded-none hover:bg-coollabs hover:text-white"
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)
</div>
</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
<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>
<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"

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' : '' }}"
href="{{ route('project.application.configuration', $parameters) }}">
<button>Configuration</button>
@ -7,7 +7,38 @@
href="{{ route('project.application.deployments', $parameters) }}">
<button>Deployments</button>
</a>
<div class="flex-1"></div>
<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>

View File

@ -10,7 +10,7 @@ class="flex items-center gap-1 mb-2 text-sm font-medium text-neutral-400">{{ $la
@endif
</label>
@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 }}
@if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} @else wire:model.defer={{ $id }} @endif>
{{ $slot }}

View File

@ -10,6 +10,21 @@
</svg>
</a>
</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">
<a class="hover:bg-transparent" @if (!request()->is('projects')) href="/projects" @endif>
<svg xmlns="http://www.w3.org/2000/svg"
@ -24,21 +39,7 @@ class="{{ request()->is('project/*') || request()->is('projects') ? 'text-warnin
</a>
</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())
<li title="Command Center">
<a class="hover:bg-transparent" @if (!request()->is('command-center')) href="/command-center" @endif>

View File

@ -1,7 +1,7 @@
<div class="pb-6">
<h1>Server</h1>
<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' : '' }}"
href="{{ route('server.show', [
'server_uuid' => Route::current()->parameters()['server_uuid'],

View File

@ -1,7 +1,7 @@
<div class="pb-6">
<h1>Settings</h1>
<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' : '' }}"
href="{{ route('settings.configuration') }}">
<button>Configuration</button>

View File

@ -20,7 +20,7 @@
@endif
</ol>
</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') }}">
<button>General</button>
</a>

View File

@ -1,2 +1,10 @@
<br><br>Use the magic
bar (press <span class="kbd-custom">/</span>) to create a new one.
<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.
@endif
</div>

View File

@ -8,7 +8,7 @@
Save
</x-forms.button>
@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
</x-forms.button>
@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" />
</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 pt-4">Current Deploy Key: <span
class="text-warning">{{ $application->private_key->name }}</span></h4>
<div class="py-2 ">Select another Deploy Key</div>
<h4 class="py-2 ">Select another Private Key</h4>
<div class="flex gap-2">
@foreach ($private_keys as $key)
<x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
</x-forms.button>
@endforeach
</div>
@endif
@endisset
</form>
</div>

View File

@ -1,7 +1,7 @@
<div x-data="{ deleteEnvironment: false }">
<x-naked-modal show="deleteEnvironment" title="Delete Environment"
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
</x-forms.button>
</div>

View File

@ -1,7 +1,7 @@
<div x-data="{ deleteProject: false }">
<x-naked-modal show="deleteProject" title="Delete Project"
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
</x-forms.button>
</div>

View File

@ -3,6 +3,9 @@
<div class="flex items-end gap-2">
<h1>Project: {{ data_get($project, 'name') }}</h1>
<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 class="pb-10">Edit project details here.</div>
<div class="flex gap-2">

View File

@ -1,39 +1,64 @@
<div>
<h1>Create a new Application</h1>
<div class="pt-2 pb-10">Deploy any public or private GIT repositories through a Deploy Key.</div>
<h3 class="py-2">Select a Private Key</h3>
@foreach ($private_keys as $key)
@if ($private_key_id == $key->id)
<x-forms.button class="bg-coollabs hover:bg-coollabs-100"
wire:click.defer="setPrivateKey('{{ $key->id }}')">
{{ $key->name }}</x-forms.button>
@else
<x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
</x-forms.button>
<div class="pt-2">Deploy any public or private Git repositories through a Deploy Key.</div>
<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)
@if ($private_key_id == $key->id)
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
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>
@else
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
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
@endforeach
</div>
@endif
@endforeach
<a href="{{ route('private-key.new') }}">
<x-forms.button isHighlighted>+</x-forms.button>
</a>
@isset($private_key_id)
<form class="flex flex-col gap-2 pb-6" wire:submit.prevent='submit'>
<div class="flex gap-2">
<x-forms.input id="repository_url" label="Repository URL" helper="{!! __('repository.url') !!}" />
<x-forms.input id="branch" label="Branch" />
@if ($is_static)
<x-forms.input id="publish_directory" label="Publish Directory" />
@else
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static" />
@endif
</div>
<h4 class="pt-4">Settings</h4>
<div class="w-52">
<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." />
</div>
<x-forms.button type="submit">
Save New Application
</x-forms.button>
</form>
@endisset
@if ($current_step === 'repository')
<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'>
<div class="flex gap-2">
<x-forms.input id="repository_url" required label="Repository URL"
helper="{!! __('repository.url') !!}" />
<x-forms.input id="branch" required label="Branch" />
@if ($is_static)
<x-forms.input id="publish_directory" required label="Publish Directory" />
@else
<x-forms.input type="number" required id="port" label="Port" :readonly="$is_static" />
@endif
</div>
<div class="w-52">
<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." />
</div>
<x-forms.button type="submit">
Save New Application
</x-forms.button>
</form>
@endif
</div>
</div>

View File

@ -2,80 +2,106 @@
<h1>Create a new Application</h1>
<div class="pb-4 ">Deploy any public or private git repositories through a GitHub App.</div>
@if ($github_apps->count() > 0)
<form class="flex flex-col" wire:submit.prevent='submit'>
<div class="flex flex-col gap-2">
<h3 class="py-2">Select a GitHub App</h3>
@foreach ($github_apps as $ghapp)
@if ($selected_github_app_id == $ghapp->id)
<x-forms.button class="bg-coollabs hover:bg-coollabs-100 h-7" wire:key="{{ $ghapp->id }}"
wire:click.prevent="loadRepositories({{ $ghapp->id }})">
{{ $ghapp->name }}
</x-forms.button>
@else
<x-forms.button wire:key="{{ $ghapp->id }}"
wire:click.prevent="loadRepositories({{ $ghapp->id }})">
{{ $ghapp->name }}
</x-forms.button>
@endif
@endforeach
<div class="flex flex-col">
@if ($repositories->count() > 0)
<div class="flex items-end gap-2">
<x-forms.select class="w-full" label="Repository URL" helper="{!! __('repository.url') !!}"
wire:model.defer="selected_repository_id">
@foreach ($repositories as $repo)
@if ($loop->first)
<option selected value="{{ data_get($repo, 'id') }}">
{{ data_get($repo, 'name') }}
</option>
@else
<option value="{{ data_get($repo, 'id') }}">{{ data_get($repo, 'name') }}
</option>
@endif
@endforeach
</x-forms.select>
<x-forms.button wire:click.prevent="loadBranches"> Check
repository</x-forms.button>
</div>
@endif
<div class="flex flex-col pt-10">
@if ($current_step === 'github_apps')
<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)
@if ($selected_github_app_id == $ghapp->id)
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
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 }}
</div>
<span wire:target="loadRepositories" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@else
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200"
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 }}
</div>
<span wire:target="loadRepositories" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@endif
@endforeach
</div>
@if ($branches->count() > 0)
<div class="flex flex-col gap-2 pb-6">
<div class="flex gap-2">
<x-forms.select id="selected_branch_name" label="Branch">
<option value="default" disabled selected>Select a branch</option>
@foreach ($branches as $branch)
@if ($loop->first)
<option selected value="{{ data_get($branch, 'name') }}">
{{ data_get($branch, 'name') }}
</option>
@else
<option value="{{ data_get($branch, 'name') }}">
{{ data_get($branch, 'name') }}
</option>
@endif
@endforeach
</x-forms.select>
@if ($is_static)
<x-forms.input id="publish_directory" label="Publish Directory"
helper="If there is a build process involved (like Svelte, React, Next, etc..), please specify the output directory for the build assets." />
@else
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static"
helper="The port your application listens on." />
@endif
</div>
<h4 class="pt-4">Settings</h4>
<div class="w-52">
<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." />
</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)
<div class="flex items-end gap-2">
<x-forms.select class="w-full" label="Repository URL" helper="{!! __('repository.url') !!}"
wire:model.defer="selected_repository_id">
@foreach ($repositories as $repo)
@if ($loop->first)
<option selected value="{{ data_get($repo, 'id') }}">
{{ data_get($repo, 'name') }}
</option>
@else
<option value="{{ data_get($repo, 'id') }}">{{ data_get($repo, 'name') }}
</option>
@endif
@endforeach
</x-forms.select>
<x-forms.button wire:click.prevent="loadBranches"> Check
repository</x-forms.button>
</div>
<x-forms.button type="submit">
Save New Application
</x-forms.button>
@else
<div>No repositories found. Check your GitHub App configuration.</div>
@endif
</div>
</form>
@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 gap-2">
<x-forms.select id="selected_branch_name" label="Branch">
<option value="default" disabled selected>Select a branch</option>
@foreach ($branches as $branch)
@if ($loop->first)
<option selected value="{{ data_get($branch, 'name') }}">
{{ data_get($branch, 'name') }}
</option>
@else
<option value="{{ data_get($branch, 'name') }}">
{{ data_get($branch, 'name') }}
</option>
@endif
@endforeach
</x-forms.select>
@if ($is_static)
<x-forms.input id="publish_directory" label="Publish Directory"
helper="If there is a build process involved (like Svelte, React, Next, etc..), please specify the output directory for the build assets." />
@else
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static"
helper="The port your application listens on." />
@endif
</div>
<div class="w-52">
<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." />
</div>
</div>
<x-forms.button type="submit">
Save New Application
</x-forms.button>
@endif
@endif
</div>
@else
<div>
<div>No Git App found.</div>

View File

@ -1,6 +1,6 @@
<div>
<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>
<div class="flex flex-col gap-2">
<div class="flex flex-col">
@ -12,10 +12,14 @@
</x-forms.button>
</div>
@if ($branch_found)
<div class="py-2">
<div>Rate limit remaining: {{ $rate_limit_remaining }}</div>
<div>Rate limit reset at: {{ $rate_limit_reset }}</div>
</div>
@if ($rate_limit_remaining && $rate_limit_reset)
<div class="flex gap-2 py-2">
<div>Rate Limit</div>
<x-helper
helper="Rate limit remaining: {{ $rate_limit_remaining }}<br>Rate limit reset at: {{ $rate_limit_reset }}" />
</div>
@endif
<h3 class="pt-8 pb-2">Details</h3>
<div class="flex flex-col gap-2 pb-6">
<div class="flex gap-2">
<x-forms.input disabled id="git_branch" label="Selected branch"
@ -28,7 +32,6 @@
helper="The port your application listens on." />
@endif
</div>
<h4 class="pt-4">Settings</h4>
<div class="w-52">
<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." />

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,12 +1,14 @@
<div x-data="{ changeLocalhost: false }">
<x-modal yesOrNo modalId="{{ $modalId }}" modalTitle="Delete Server">
<x-slot:modalBody>
<p>This server will be deleted. It is not reversible. <br>Please think again..</p>
</x-slot:modalBody>
</x-modal>
<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.' />
@if ($server->settings->is_reachable)
<x-modal yesOrNo modalId="{{ $modalId }}" modalTitle="Delete Server">
<x-slot:modalBody>
<p>This server will be deleted. It is not reversible. <br>Please think again..</p>
</x-slot:modalBody>
</x-modal>
<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.' />
<form wire:submit.prevent='submit' class="flex flex-col">
<div class="flex gap-2">
<h2>General</h2>
@ -70,22 +72,22 @@
</div>
@endisset
</form>
<h3>Danger Zone</h3>
<div class="">Woah. I hope you know what are you doing.</div>
<h4 class="pt-4">Delete Server</h4>
<div class="pb-4">This will remove this server from Coolify. Beware! There is no coming
back!
</div>
@if ($server->id !== 0 || isDev())
<x-forms.button isError isModal modalId="{{ $modalId }}">
Delete
</x-forms.button>
@endif
@else
<div class="w-full">
<div class="w-full pb-4">
<div class="cursor-pointer box" wire:click.prevent='validateServer'>
Validate Server
</div>
</div>
@endif
<h3>Danger Zone</h3>
<div class="">Woah. I hope you know what are you doing.</div>
<h4 class="pt-4">Delete Server</h4>
<div class="pb-4">This will remove this server from Coolify. Beware! There is no coming
back!
</div>
@if ($server->id !== 0 || isDev())
<x-forms.button isError isModal modalId="{{ $modalId }}">
Delete
</x-forms.button>
@endif
</div>

View File

@ -7,9 +7,7 @@
<div class="flex gap-2">
@if ($github_app->app_id)
<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) }}">
<x-forms.button>
@if ($github_app->installation_id)
@ -21,9 +19,12 @@
@endif
</x-forms.button>
</a>
<x-forms.button isError x-on:click.prevent="deleteSource = true">
Delete
</x-forms.button>
@else
<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
</x-forms.button>

View File

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

View File

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

View File

@ -2,6 +2,9 @@
<div class="flex flex-col">
<div class="flex items-center gap-2">
<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)
<livewire:project.delete-environment :environment_id="$environment->id" />
@endif

View File

@ -1,9 +1,8 @@
<x-layout>
<div class="flex items-center gap-2">
<h1>Environments</h1>
@if ($project->applications->count() === 0)
<livewire:project.delete-project :project_id="$project->id" />
@endif
<x-forms.button class="btn" onclick="newEnvironment.showModal()">+ Add</x-forms.button>
<livewire:project.add-environment :project="$project" />
</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">

View File

@ -1,34 +1,48 @@
<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="grid gap-2 lg:grid-cols-2">
@forelse ($projects as $project)
<div class="gap-2 border border-transparent cursor-pointer box group" x-data
x-on:click="goto('{{ $project->uuid }}')">
<div class="flex flex-col mx-6">
<a class=" group-hover:text-white hover:no-underline"
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">{{ $project->name }}</a>
<div class="text-xs group-hover:text-white hover:no-underline"
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
{{ $project->description }}</div>
</div>
<div class="flex-1"></div>
<a class="mx-4 rounded hover:text-white"
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}"><svg
xmlns="http://www.w3.org/2000/svg" class="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="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg></a>
</div>
@empty
@if ($servers === 0)
<div>
<div>No project found.</div>
<x-use-magic-bar />
<div>No servers found. Without a server, you won't be able to do much.</div>
<x-use-magic-bar link="/server/new" />
</div>
@endforelse
@else
@forelse ($projects as $project)
<div class="gap-2 border border-transparent cursor-pointer box group" x-data
x-on:click="goto('{{ $project->uuid }}')">
<div class="flex flex-col mx-6">
<a class=" group-hover:text-white hover:no-underline"
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">{{ $project->name }}</a>
<div class="text-xs group-hover:text-white hover:no-underline"
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
{{ $project->description }}</div>
</div>
<div class="flex-1"></div>
<a class="mx-4 rounded hover:text-white"
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}"><svg
xmlns="http://www.w3.org/2000/svg" class="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="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg></a>
</div>
@empty
<div>
<div>No project found.</div>
<x-use-magic-bar />
</div>
@endforelse
@endif
<script>
function goto(uuid) {
window.location.href = '/project/' + uuid;

View File

@ -1,5 +1,5 @@
<x-layout>
<h1>Servers</h1>
<h1>Servers</span></h1>
<div class="pt-2 pb-10 ">All Servers</div>
<div class="grid gap-2 lg:grid-cols-2">
@forelse ($servers as $server)
@ -11,7 +11,6 @@
<div class="flex flex-col mx-6">
<div class=" group-hover:text-white">
{{ $server->name }}
</div>
<div class="text-xs group-hover:text-white"
href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}">
@ -33,7 +32,7 @@
@empty
<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>
@endforelse
<script>

View File

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

View File

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