ui: redesign
This commit is contained in:
parent
91950e1891
commit
b61860b3ab
@ -119,16 +119,18 @@ public function submit()
|
||||
{
|
||||
try {
|
||||
$this->resetErrorBag();
|
||||
$this->validate([
|
||||
'team.smtp_from_address' => 'required|email',
|
||||
'team.smtp_from_name' => 'required',
|
||||
'team.smtp_host' => 'required',
|
||||
'team.smtp_port' => 'required|numeric',
|
||||
'team.smtp_encryption' => 'nullable',
|
||||
'team.smtp_username' => 'nullable',
|
||||
'team.smtp_password' => 'nullable',
|
||||
'team.smtp_timeout' => 'nullable',
|
||||
]);
|
||||
if (!$this->team->use_instance_email_settings) {
|
||||
$this->validate([
|
||||
'team.smtp_from_address' => 'required|email',
|
||||
'team.smtp_from_name' => 'required',
|
||||
'team.smtp_host' => 'required',
|
||||
'team.smtp_port' => 'required|numeric',
|
||||
'team.smtp_encryption' => 'nullable',
|
||||
'team.smtp_username' => 'nullable',
|
||||
'team.smtp_password' => 'nullable',
|
||||
'team.smtp_timeout' => 'nullable',
|
||||
]);
|
||||
}
|
||||
$this->team->save();
|
||||
refreshSession();
|
||||
$this->dispatch('success', 'Settings saved.');
|
||||
|
@ -9,7 +9,7 @@
|
||||
class Index extends Component
|
||||
{
|
||||
public Application $application;
|
||||
public array|Collection $deployments = [];
|
||||
public ?Collection $deployments;
|
||||
public int $deployments_count = 0;
|
||||
public string $current_url;
|
||||
public int $skip = 0;
|
||||
@ -48,9 +48,9 @@ private function show_pull_request_only()
|
||||
}
|
||||
private function show_more()
|
||||
{
|
||||
if (count($this->deployments) !== 0) {
|
||||
if ($this->deployments->count() !== 0) {
|
||||
$this->show_next = true;
|
||||
if (count($this->deployments) < $this->default_take) {
|
||||
if ($this->deployments->count() < $this->default_take) {
|
||||
$this->show_next = false;
|
||||
}
|
||||
return;
|
||||
@ -63,7 +63,6 @@ public function reload_deployments()
|
||||
}
|
||||
public function previous_page(?int $take = null)
|
||||
{
|
||||
|
||||
if ($take) {
|
||||
$this->skip = $this->skip - $take;
|
||||
}
|
||||
|
@ -2,14 +2,73 @@
|
||||
|
||||
namespace App\Livewire\Tags;
|
||||
|
||||
use App\Http\Controllers\Api\Deploy;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Attributes\Url;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $tags = [];
|
||||
public function mount() {
|
||||
$this->tags = Tag::where('team_id', currentTeam()->id)->get()->unique('name')->sortBy('name');
|
||||
#[Url()]
|
||||
public ?string $tag = null;
|
||||
|
||||
public Collection $tags;
|
||||
public Collection $applications;
|
||||
public Collection $services;
|
||||
public $webhook = null;
|
||||
public $deployments_per_tag_per_server = [];
|
||||
|
||||
public function updatedTag()
|
||||
{
|
||||
$tag = $this->tags->where('name', $this->tag)->first();
|
||||
$this->webhook = generatTagDeployWebhook($tag->name);
|
||||
$this->applications = $tag->applications()->get();
|
||||
$this->services = $tag->services()->get();
|
||||
$this->get_deployments();
|
||||
}
|
||||
public function get_deployments()
|
||||
{
|
||||
try {
|
||||
$resource_ids = $this->applications->pluck('id');
|
||||
$this->deployments_per_tag_per_server = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->whereIn('application_id', $resource_ids)->get([
|
||||
"id",
|
||||
"application_id",
|
||||
"application_name",
|
||||
"deployment_url",
|
||||
"pull_request_id",
|
||||
"server_name",
|
||||
"server_id",
|
||||
"status"
|
||||
])->sortBy('id')->groupBy('server_name')->toArray();
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function redeploy_all()
|
||||
{
|
||||
try {
|
||||
$message = collect([]);
|
||||
$this->applications->each(function ($resource) use ($message) {
|
||||
$deploy = new Deploy();
|
||||
$message->push($deploy->deploy_resource($resource));
|
||||
});
|
||||
$this->services->each(function ($resource) use ($message) {
|
||||
$deploy = new Deploy();
|
||||
$message->push($deploy->deploy_resource($resource));
|
||||
});
|
||||
$this->dispatch('success', 'Mass deployment started.');
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function mount()
|
||||
{
|
||||
$this->tags = Tag::ownedByCurrentTeam()->get()->unique('name')->sortBy('name');
|
||||
if ($this->tag) {
|
||||
$this->updatedTag();
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ public function __construct(
|
||||
public ?string $helper = null,
|
||||
public string|bool $instantSave = false,
|
||||
public bool $disabled = false,
|
||||
public string $defaultClass = "border-coolgray-500 text-warning focus:ring-warning bg-coolgray-100 rounded cursor-pointer",
|
||||
public string $defaultClass = "border-coolgray-500 text-warning focus:ring-warning dark:bg-coolgray-100 rounded cursor-pointer dark:disabled:bg-base dark:disabled:cursor-not-allowed",
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public function __construct(
|
||||
public ?string $helper = null,
|
||||
public bool $allowToPeak = true,
|
||||
public bool $isMultiline = false,
|
||||
public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/20"
|
||||
public string $defaultClass = "input",
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,12 @@ class Select extends Component
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(
|
||||
public string|null $id = null,
|
||||
public string|null $name = null,
|
||||
public string|null $label = null,
|
||||
public string|null $helper = null,
|
||||
public bool $required = false,
|
||||
public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black "
|
||||
public ?string $id = null,
|
||||
public ?string $name = null,
|
||||
public ?string $label = null,
|
||||
public ?string $helper = null,
|
||||
public bool $required = false,
|
||||
public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black "
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ public function __construct(
|
||||
public ?string $helper = null,
|
||||
public bool $realtimeValidation = false,
|
||||
public bool $allowToPeak = true,
|
||||
public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/20 scrollbar",
|
||||
public string $defaultClassInput = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/20"
|
||||
public string $defaultClass = "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 scrollbar dark:read-only:text-neutral-500",
|
||||
public string $defaultClassInput = "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"
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
@ -11,16 +11,20 @@ body {
|
||||
@apply text-sm antialiased scrollbar;
|
||||
}
|
||||
|
||||
button[isError] {
|
||||
button[isError]:not(:disabled) {
|
||||
@apply bg-red-600 hover:bg-red-700;
|
||||
}
|
||||
|
||||
button[isHighlighted] {
|
||||
button[isHighlighted]:not(:disabled) {
|
||||
@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 {
|
||||
@apply pb-6 text-2xl font-bold dark:text-white text-neutral-800;
|
||||
@apply text-2xl font-bold dark:text-white text-neutral-800;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@ -36,7 +40,7 @@ h4 {
|
||||
}
|
||||
|
||||
a {
|
||||
@apply dark:text-neutral-400 text-neutral-600;
|
||||
@apply dark:hover:text-white dark:text-neutral-400 text-neutral-600;
|
||||
}
|
||||
|
||||
label {
|
||||
@ -75,28 +79,44 @@ tr td:first-child {
|
||||
@apply pl-4 pr-3 font-bold sm:pl-6;
|
||||
}
|
||||
|
||||
input.input-sm {
|
||||
input {
|
||||
@apply pr-10;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
|
||||
option {
|
||||
@apply text-white;
|
||||
}
|
||||
.badge {
|
||||
@apply inline-block w-3 h-3 text-xs font-bold leading-none border border-black rounded-full ;
|
||||
.alert-success {
|
||||
@apply flex items-center gap-2 text-success;
|
||||
}
|
||||
.alert-error {
|
||||
@apply flex items-center gap-2 text-error;
|
||||
}
|
||||
.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
|
||||
}
|
||||
|
||||
.badge {
|
||||
@apply inline-block w-3 h-3 text-xs font-bold leading-none border border-black rounded-full;
|
||||
}
|
||||
|
||||
.badge-success {
|
||||
@apply bg-success;
|
||||
}
|
||||
|
||||
.badge-warning {
|
||||
@apply bg-warning;
|
||||
}
|
||||
|
||||
.badge-error {
|
||||
@apply bg-error;
|
||||
}
|
||||
.button {
|
||||
@apply px-3 py-1 text-sm font-normal normal-case rounded dark:bg-coolgray-200 dark:text-white dark:hover:bg-coolgray-100;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[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");
|
||||
}
|
||||
@ -104,12 +124,15 @@ [type='checkbox']:checked {
|
||||
.menu {
|
||||
@apply flex items-center gap-1;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.menu-item-active {
|
||||
@apply rounded-none bg-coolgray-200 text-warning;
|
||||
@apply rounded-none dark:bg-coolgray-200 dark:text-warning;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@apply w-4 h-4;
|
||||
}
|
||||
@ -123,10 +146,9 @@ .main {
|
||||
}
|
||||
|
||||
.custom-modal {
|
||||
@apply flex flex-col gap-2 px-8 py-4 border bg-coolgray-100 border-coolgray-200;
|
||||
@apply z-50 flex flex-col gap-2 px-8 py-4 border dark:bg-coolgray-100 dark:border-coolgray-200;
|
||||
}
|
||||
|
||||
|
||||
.navbar-main {
|
||||
@apply flex items-end gap-6 py-2 border-b-2 border-solid border-coolgray-200;
|
||||
}
|
||||
@ -197,12 +219,13 @@ .text-helper {
|
||||
@apply inline-block font-bold text-warning;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.buyme {
|
||||
@apply block px-3 py-2 mt-10 text-sm font-semibold leading-6 text-center text-white rounded-md shadow-sm bg-coolgray-200 hover:bg-coolgray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-coolgray-200 hover:no-underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
@apply hidden pb-0 lg:block lg:pb-8 ;
|
||||
}
|
||||
.subtitle {
|
||||
@apply pt-2 pb-10;
|
||||
}
|
||||
|
@ -1,54 +1,76 @@
|
||||
<div class="group">
|
||||
@if (
|
||||
(data_get($application, 'fqdn') ||
|
||||
collect(json_decode($this->application->docker_compose_domains))->count() > 0 ||
|
||||
data_get($application, 'previews', collect([]))->count() > 0 ||
|
||||
data_get($application, 'ports_mappings_array')) &&
|
||||
data_get($application, 'settings.is_raw_compose_deployment_enabled') !== true)
|
||||
<label tabindex="0" class="flex items-center gap-2 cursor-pointer hover:text-white"> Open Application
|
||||
<x-chevron-down />
|
||||
</label>
|
||||
<div x-data="{
|
||||
dropdownOpen: false
|
||||
}" class="relative" @click.outside="dropdownOpen = false">
|
||||
|
||||
<div class="absolute z-50 hidden group-hover:block">
|
||||
<ul tabindex="0"
|
||||
class="relative -ml-24 text-xs text-white normal-case rounded min-w-max menu bg-coolgray-200">
|
||||
<button @click="dropdownOpen=true"
|
||||
class="inline-flex items-center justify-center py-1 pr-12 text-sm font-medium transition-colors focus:outline-none disabled:opacity-50 disabled:pointer-events-none">
|
||||
<span class="flex flex-col items-start flex-shrink-0 h-full ml-2 leading-none translate-y-px">
|
||||
Open Application
|
||||
</span>
|
||||
<svg class="absolute right-0 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div x-show="dropdownOpen" @click.away="dropdownOpen=false" x-transition:enter="ease-out duration-200"
|
||||
x-transition:enter-start="-translate-y-2" x-transition:enter-end="translate-y-0"
|
||||
class="absolute top-0 z-50 w-64 mt-6 -translate-x-1/2 left-1/2" x-cloak>
|
||||
<div class="p-1 mt-1 dark:bg-coolgray-100 ">
|
||||
{{-- <div class="px-2 py-1.5 text-sm font-semibold">Domains</div> --}}
|
||||
{{-- <div class="h-px my-1 -mx-1 "></div> --}}
|
||||
@if (
|
||||
(data_get($application, 'fqdn') ||
|
||||
collect(json_decode($this->application->docker_compose_domains))->count() > 0 ||
|
||||
data_get($application, 'previews', collect([]))->count() > 0 ||
|
||||
data_get($application, 'ports_mappings_array')) &&
|
||||
data_get($application, 'settings.is_raw_compose_deployment_enabled') !== true)
|
||||
@if (data_get($application, 'gitBrancLocation'))
|
||||
<li>
|
||||
<a target="_blank"
|
||||
class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
href="{{ $application->gitBranchLocation }}">
|
||||
<x-git-icon git="{{ $application->source?->getMorphClass() }}" />
|
||||
Git Repository
|
||||
</a>
|
||||
</li>
|
||||
<a target="_blank" class="dropdown-item" href="{{ $application->gitBranchLocation }}">
|
||||
<x-git-icon git="{{ $application->source?->getMorphClass() }}" />
|
||||
Git Repository
|
||||
</a>
|
||||
@endif
|
||||
@if (data_get($application, 'build_pack') === 'dockercompose')
|
||||
@foreach (collect(json_decode($this->application->docker_compose_domains)) as $fqdn)
|
||||
@if (data_get($fqdn, 'domain'))
|
||||
@foreach (explode(',', data_get($fqdn, 'domain')) as $domain)
|
||||
<li>
|
||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
target="_blank" href="{{ getFqdnWithoutPort($domain) }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>{{ getFqdnWithoutPort($domain) }}
|
||||
</a>
|
||||
</li>
|
||||
<a class="dropdown-item" target="_blank" href="{{ getFqdnWithoutPort($domain) }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>{{ getFqdnWithoutPort($domain) }}
|
||||
</a>
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@if (data_get($application, 'fqdn'))
|
||||
@foreach (str(data_get($application, 'fqdn'))->explode(',') as $fqdn)
|
||||
<li>
|
||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
target="_blank" href="{{ getFqdnWithoutPort($fqdn) }}">
|
||||
<a class="dropdown-item" target="_blank" href="{{ getFqdnWithoutPort($fqdn) }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>{{ getFqdnWithoutPort($fqdn) }}
|
||||
</a>
|
||||
@endforeach
|
||||
@endif
|
||||
@if (data_get($application, 'previews', collect([]))->count() > 0)
|
||||
@foreach (data_get($application, 'previews') as $preview)
|
||||
@if (data_get($preview, 'fqdn'))
|
||||
<a class="dropdown-item" target="_blank"
|
||||
href="{{ getFqdnWithoutPort(data_get($preview, 'fqdn')) }}">
|
||||
<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">
|
||||
@ -57,92 +79,66 @@ class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hove
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>{{ getFqdnWithoutPort($fqdn) }}
|
||||
</svg>
|
||||
PR{{ data_get($preview, 'pull_request_id') }} |
|
||||
{{ data_get($preview, 'fqdn') }}
|
||||
</a>
|
||||
</li>
|
||||
@endforeach
|
||||
@endif
|
||||
@if (data_get($application, 'previews', collect([]))->count() > 0)
|
||||
@foreach (data_get($application, 'previews') as $preview)
|
||||
@if (data_get($preview, 'fqdn'))
|
||||
<li>
|
||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
target="_blank" href="{{ getFqdnWithoutPort(data_get($preview, 'fqdn')) }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
PR{{ data_get($preview, 'pull_request_id') }} |
|
||||
{{ data_get($preview, 'fqdn') }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@if (data_get($application, 'ports_mappings_array'))
|
||||
@foreach ($application->ports_mappings_array as $port)
|
||||
@if ($application->destination->server->id === 0)
|
||||
<li>
|
||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
target="_blank" href="http://localhost:{{ explode(':', $port)[0] }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
Port {{ $port }}
|
||||
</a>
|
||||
</li>
|
||||
<a class="dropdown-item" target="_blank"
|
||||
href="http://localhost:{{ explode(':', $port)[0] }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
Port {{ $port }}
|
||||
</a>
|
||||
@else
|
||||
<li>
|
||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
target="_blank"
|
||||
href="http://{{ $application->destination->server->ip }}:{{ explode(':', $port)[0] }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
{{ $application->destination->server->ip }}:{{ explode(':', $port)[0] }}
|
||||
</a>
|
||||
</li>
|
||||
<a class="dropdown-item" target="_blank"
|
||||
href="http://{{ $application->destination->server->ip }}:{{ explode(':', $port)[0] }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
{{ $application->destination->server->ip }}:{{ explode(':', $port)[0] }}
|
||||
</a>
|
||||
@if (count($application->additional_servers) > 0)
|
||||
@foreach ($application->additional_servers as $server)
|
||||
<li>
|
||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs hover:text-white"
|
||||
target="_blank"
|
||||
href="http://{{ $server->ip }}:{{ explode(':', $port)[0] }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
{{ $server->ip }}:{{ explode(':', $port)[0] }}
|
||||
</a>
|
||||
</li>
|
||||
<a class="dropdown-item" target="_blank"
|
||||
href="http://{{ $server->ip }}:{{ explode(':', $port)[0] }}">
|
||||
<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="M9 15l6 -6" />
|
||||
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||
<path
|
||||
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||
</svg>
|
||||
{{ $server->ip }}:{{ explode(':', $port)[0] }}
|
||||
</a>
|
||||
@endforeach
|
||||
@endif
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
</ul>
|
||||
@else
|
||||
<div class="px-2 py-1.5 text-sm font-semibold">No links available</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1 +1 @@
|
||||
<img class="inline-flex w-3 h-3" src="{{ asset('svgs/external-link.svg') }}">
|
||||
<img class="inline-flex w-3 h-3 ml-1" src="{{ asset('svgs/external-link.svg') }}">
|
||||
|
@ -10,11 +10,10 @@
|
||||
|
||||
{{ $slot }}
|
||||
@if ($attributes->get('type') === 'submit')
|
||||
<span wire:target="submit" wire:loading.delay class="loading loading-xs text-warning loading-spinner"></span>
|
||||
<x-loading wire:target="submit" wire:loading.delay />
|
||||
@else
|
||||
@if ($attributes->whereStartsWith('wire:click')->first())
|
||||
<span wire:target="{{ $attributes->whereStartsWith('wire:click')->first() }}" wire:loading.delay
|
||||
class="loading loading-xs loading-spinner"></span>
|
||||
<x-loading wire:target="{{ $attributes->whereStartsWith('wire:click')->first() }}" wire:loading.delay />
|
||||
@endif
|
||||
@endif
|
||||
</button>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="flex flex-row items-center gap-4 px-2 py-1 form-control min-w-fit dark:hover:bg-coolgray-100">
|
||||
<div class="flex flex-row items-center gap-4 px-2 py-1 my-2 form-control min-w-fit dark:hover:bg-coolgray-100">
|
||||
<label class="flex gap-4 px-0 min-w-fit label">
|
||||
<span class="flex gap-2">
|
||||
@if ($label)
|
||||
|
@ -28,9 +28,9 @@ class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:te
|
||||
<input x-cloak x-show="type" value="{{ $value }}"
|
||||
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required)
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
wire:dirty.class.remove='dark:text-white text-black' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
||||
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' wire:dirty.class="dark:focus:ring-warning dark:ring-warning"
|
||||
wire:loading.attr="disabled" type="{{ $type }}" @readonly($readonly) @disabled($disabled)
|
||||
id="{{ $id }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||
aria-placeholder="{{ $attributes->get('placeholder') }}">
|
||||
|
||||
</div>
|
||||
@ -38,8 +38,8 @@ class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:te
|
||||
<input @if ($value) value="{{ $value }}" @endif
|
||||
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly)
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
wire:dirty.class.remove='dark:text-white text-black' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||
type="{{ $type }}" @disabled($disabled)
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' wire:dirty.class="dark:focus:ring-warning dark:ring-warning"
|
||||
wire:loading.attr="disabled" type="{{ $type }}" @disabled($disabled)
|
||||
@if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}"
|
||||
placeholder="{{ $attributes->get('placeholder') }}">
|
||||
@endif
|
||||
|
@ -25,7 +25,8 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer
|
||||
<input x-cloak x-show="type === 'password'" value="{{ $value }}"
|
||||
{{ $attributes->merge(['class' => $defaultClassInput]) }} @required($required)
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300'
|
||||
wire:dirty.class="dark:focus:ring-warning dark:ring-warning" wire:loading.attr="disabled"
|
||||
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
||||
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||
aria-placeholder="{{ $attributes->get('placeholder') }}">
|
||||
@ -34,7 +35,7 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer
|
||||
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||
@else
|
||||
wire:model={{ $value ?? $id }}
|
||||
wire:dirty.class="input-warning" @endif
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' wire:dirty.class="dark:focus:ring-warning dark:ring-warning" @endif
|
||||
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}"
|
||||
name="{{ $name }}" name={{ $id }}></textarea>
|
||||
|
||||
@ -44,7 +45,7 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer
|
||||
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||
@else
|
||||
wire:model={{ $value ?? $id }}
|
||||
wire:dirty.class="input-warning" @endif
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' wire:dirty.class="dark:focus:ring-warning dark:ring-warning" @endif
|
||||
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}"
|
||||
name="{{ $name }}" name={{ $id }}></textarea>
|
||||
@endif
|
||||
|
@ -1,11 +1,11 @@
|
||||
@props(['text' => null])
|
||||
<button type="button" class="inline-flex items-center px-2 " {{ $attributes }}>
|
||||
<svg class="w-4 h-4 mr-3 -ml-1 text-warning animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
<div class="inline-flex items-center justify-center" {{ $attributes }}>
|
||||
<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">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor"
|
||||
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>
|
||||
</svg>
|
||||
{{ $text }}
|
||||
</button>
|
||||
<div>{{ $text }}</div>
|
||||
</div>
|
||||
|
@ -34,7 +34,7 @@ class="absolute inset-0 w-full h-full bg-black bg-opacity-20 backdrop-blur-sm"><
|
||||
x-transition:leave="ease-in duration-100"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="relative w-full py-6 border rounded shadow-lg bg-coolgray-100 px-7 border-coolgray-300 sm:max-w-lg">
|
||||
class="relative w-full py-6 border rounded shadow-lg dark:bg-base px-7 dark:border-coolgray-300 sm:max-w-lg">
|
||||
<div class="flex items-center justify-between pb-3">
|
||||
<h3 class="text-2xl font-bold">{{ $title }}</h3>
|
||||
{{-- <button @click="modalOpen=false"
|
53
resources/views/components/modal-input.blade.php
Normal file
53
resources/views/components/modal-input.blade.php
Normal file
@ -0,0 +1,53 @@
|
||||
@props([
|
||||
'title' => 'Are you sure?',
|
||||
'buttonTitle' => 'Open Modal',
|
||||
'isErrorButton' => false,
|
||||
'disabled' => false,
|
||||
'action' => 'delete',
|
||||
'content' => null,
|
||||
])
|
||||
<div x-data="{ modalOpen: false }" :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto">
|
||||
@if ($content)
|
||||
<div @click="modalOpen=true">
|
||||
{{ $content }}
|
||||
</div>
|
||||
@else
|
||||
@if ($disabled)
|
||||
<x-forms.button isError disabled>{{ $buttonTitle }}</x-forms.button>
|
||||
@elseif ($isErrorButton)
|
||||
<x-forms.button isError @click="modalOpen=true">{{ $buttonTitle }}</x-forms.button>
|
||||
@else
|
||||
<x-forms.button @click="modalOpen=true">{{ $buttonTitle }}</x-forms.button>
|
||||
@endif
|
||||
@endif
|
||||
<template x-teleport="body">
|
||||
<div x-show="modalOpen" class="fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen"
|
||||
x-cloak>
|
||||
<div x-show="modalOpen" x-transition:enter="ease-out duration-100" x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-100"
|
||||
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
|
||||
class="absolute inset-0 w-full h-full bg-black bg-opacity-20 backdrop-blur-sm"></div>
|
||||
<div x-show="modalOpen" x-trap.inert.noscroll="modalOpen" x-transition:enter="ease-out duration-100"
|
||||
x-transition:enter-start="opacity-0 -translate-y-2 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="ease-in duration-100"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="relative w-full py-6 border rounded min-w-[36rem] max-w-fit dark:bg-base px-7 dark:border-coolgray-300">
|
||||
<div class="flex items-center justify-between pb-3">
|
||||
<h3 class="text-2xl font-bold">{{ $title }}</h3>
|
||||
<button @click="modalOpen=false"
|
||||
class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-white rounded-full hover:bg-coolgray-300">
|
||||
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="relative flex items-center justify-center w-auto pb-4">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
216
resources/views/components/navbar-old.blade.php
Normal file
216
resources/views/components/navbar-old.blade.php
Normal file
@ -0,0 +1,216 @@
|
||||
@auth
|
||||
<nav class="h-screen pt-[4.5rem] border-r scrollbar bg-coolgray-100/40 border-r-coolgray-200">
|
||||
{{-- <div class="px-2 pb-2" id="vue">
|
||||
<magic-bar></magic-bar>
|
||||
</div> --}}
|
||||
<a href="/" class="fixed top-0 z-50 mx-3 mt-3 bg-transparent cursor-pointer"><img
|
||||
class="transition rounded w-11 h-11" src="{{ asset('coolify-transparent.png') }}"></a>
|
||||
<ul class="flex flex-col h-full gap-4 menu flex-nowrap">
|
||||
<a title="Dashboard" href="/" class="{{ request()->is('/') ? 'menu-item-active menu-item' : 'menu-item' }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
||||
</svg>
|
||||
Dashboard
|
||||
</a>
|
||||
<a title="Projects"
|
||||
class="{{ request()->is('project/*') || request()->is('projects') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="/projects">
|
||||
<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="M12 4l-8 4l8 4l8 -4l-8 -4" />
|
||||
<path d="M4 12l8 4l8 -4" />
|
||||
<path d="M4 16l8 4l8 -4" />
|
||||
</svg>
|
||||
Projects
|
||||
</a>
|
||||
<a title="Servers"
|
||||
class="{{ request()->is('server/*') || request()->is('servers') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="/servers">
|
||||
<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="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>
|
||||
Servers
|
||||
</a>
|
||||
<a title="Security" class="{{ request()->is('security*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('security.private-key.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m16.555 3.843l3.602 3.602a2.877 2.877 0 0 1 0 4.069l-2.643 2.643a2.877 2.877 0 0 1-4.069 0l-.301-.301l-6.558 6.558a2 2 0 0 1-1.239.578L5.172 21H4a1 1 0 0 1-.993-.883L3 20v-1.172a2 2 0 0 1 .467-1.284l.119-.13L4 17h2v-2h2v-2l2.144-2.144l-.301-.301a2.877 2.877 0 0 1 0-4.069l2.643-2.643a2.877 2.877 0 0 1 4.069 0zM15 9h.01" />
|
||||
</svg>
|
||||
Security
|
||||
</a>
|
||||
<a title="Source" class="{{ request()->is('source*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('source.all') }}">
|
||||
<svg class="icon" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="m6.793 1.207l.353.354l-.353-.354ZM1.207 6.793l-.353-.354l.353.354Zm0 1.414l.354-.353l-.354.353Zm5.586 5.586l-.354.353l.354-.353Zm1.414 0l-.353-.354l.353.354Zm5.586-5.586l.353.354l-.353-.354Zm0-1.414l-.354.353l.354-.353ZM8.207 1.207l.354-.353l-.354.353ZM6.44.854L.854 6.439l.707.707l5.585-5.585L6.44.854ZM.854 8.56l5.585 5.585l.707-.707l-5.585-5.585l-.707.707Zm7.707 5.585l5.585-5.585l-.707-.707l-5.585 5.585l.707.707Zm5.585-7.707L8.561.854l-.707.707l5.585 5.585l.707-.707Zm0 2.122a1.5 1.5 0 0 0 0-2.122l-.707.707a.5.5 0 0 1 0 .708l.707.707ZM6.44 14.146a1.5 1.5 0 0 0 2.122 0l-.707-.707a.5.5 0 0 1-.708 0l-.707.707ZM.854 6.44a1.5 1.5 0 0 0 0 2.122l.707-.707a.5.5 0 0 1 0-.708L.854 6.44Zm6.292-4.878a.5.5 0 0 1 .708 0L8.56.854a1.5 1.5 0 0 0-2.122 0l.707.707Zm-2 1.293l1 1l.708-.708l-1-1l-.708.708ZM7.5 5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 6V5Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 4.5H8ZM7.5 4a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 3v1Zm0-1A1.5 1.5 0 0 0 6 4.5h1a.5.5 0 0 1 .5-.5V3Zm.646 2.854l1.5 1.5l.707-.708l-1.5-1.5l-.707.708ZM10.5 8a.5.5 0 0 1-.5-.5H9A1.5 1.5 0 0 0 10.5 9V8Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 12 7.5h-1Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 10.5 6v1Zm0-1A1.5 1.5 0 0 0 9 7.5h1a.5.5 0 0 1 .5-.5V6ZM7 5.5v4h1v-4H7Zm.5 5.5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 12v-1Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 10.5H8Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 9v1Zm0-1A1.5 1.5 0 0 0 6 10.5h1a.5.5 0 0 1 .5-.5V9Z" />
|
||||
</svg>
|
||||
Sources
|
||||
</a>
|
||||
<a title="Notifications"
|
||||
class="{{ request()->is('notifications*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('notification.index') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3H4a4 4 0 0 0 2-3v-3a7 7 0 0 1 4-6M9 17v1a3 3 0 0 0 6 0v-1" />
|
||||
</svg>
|
||||
Notifications
|
||||
</a>
|
||||
<a title="Tags" class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('tags.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
|
||||
<path
|
||||
d="M3 8v4.172a2 2 0 0 0 .586 1.414l5.71 5.71a2.41 2.41 0 0 0 3.408 0l3.592-3.592a2.41 2.41 0 0 0 0-3.408l-5.71-5.71A2 2 0 0 0 9.172 6H5a2 2 0 0 0-2 2" />
|
||||
<path d="m18 19l1.592-1.592a4.82 4.82 0 0 0 0-6.816L15 6m-8 4h-.01" />
|
||||
</g>
|
||||
</svg>
|
||||
Tags
|
||||
</a>
|
||||
<a title="Command Center"
|
||||
class="{{ request()->is('command-center*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('command-center') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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="M5 7l5 5l-5 5" />
|
||||
<path d="M12 19l7 0" />
|
||||
</svg>
|
||||
Command Center
|
||||
</a>
|
||||
<a title="Profile" class="{{ request()->is('profile*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('profile') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
|
||||
<path d="M12 10m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
|
||||
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855" />
|
||||
</svg>
|
||||
Profile
|
||||
</a>
|
||||
<a title="Teams" class="{{ request()->is('team*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('team.index') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" />
|
||||
<path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M17 10h2a2 2 0 0 1 2 2v1" />
|
||||
<path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M3 13v-1a2 2 0 0 1 2 -2h2" />
|
||||
</svg>
|
||||
Teams
|
||||
</a>
|
||||
@if (isCloud())
|
||||
<a title="Subscription"
|
||||
class="{{ request()->is('subscription*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('subscription.show') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm0 2h18M7 15h.01M11 15h2" />
|
||||
</svg>
|
||||
Subscription
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if (isInstanceAdmin())
|
||||
<a title="Settings" class="{{ request()->is('settings*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="/settings">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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>
|
||||
Settings
|
||||
</a>
|
||||
@endif
|
||||
<a title="Onboarding" class="{{ request()->is('onboarding*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('onboarding') }}">
|
||||
<svg class="icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M224 128a8 8 0 0 1-8 8h-88a8 8 0 0 1 0-16h88a8 8 0 0 1 8 8m-96-56h88a8 8 0 0 0 0-16h-88a8 8 0 0 0 0 16m88 112h-88a8 8 0 0 0 0 16h88a8 8 0 0 0 0-16M82.34 42.34L56 68.69L45.66 58.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 132.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 196.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32" />
|
||||
</svg>
|
||||
Onboarding
|
||||
</a>
|
||||
{{-- <div class="menu-item" x-data="{ open: false }">
|
||||
<div>
|
||||
<button x-on:click.prevent="open = !open" x-on:click.away="open = false" type="button" id="menu-button"
|
||||
aria-expanded="true" aria-haspopup="true">
|
||||
<svg class="icon text-neutral-400" xmlns="http://www.w3.org/2000/svg" width="200" height="200"
|
||||
viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="open" x-cloak
|
||||
class="absolute left-0 z-10 w-56 mx-4 mt-2 origin-top-right rounded shadow-lg bg-coolgray-100 ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
|
||||
<div class="py-1" role="none">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
@if (isCloud() && isInstanceAdmin())
|
||||
<a title="Admin" class="menu-item" href="/admin">
|
||||
<svg class="text-pink-600 icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M177.62 159.6a52 52 0 0 1-34 34a12.2 12.2 0 0 1-3.6.55a12 12 0 0 1-3.6-23.45a28 28 0 0 0 18.32-18.32a12 12 0 0 1 22.9 7.2ZM220 144a92 92 0 0 1-184 0c0-28.81 11.27-58.18 33.48-87.28a12 12 0 0 1 17.9-1.33l19.69 19.11L127 19.89a12 12 0 0 1 18.94-5.12C168.2 33.25 220 82.85 220 144m-24 0c0-41.71-30.61-78.39-52.52-99.29l-20.21 55.4a12 12 0 0 1-19.63 4.5L80.71 82.36C67 103.38 60 124.06 60 144a68 68 0 0 0 136 0" />
|
||||
</svg>
|
||||
Admin
|
||||
</a>
|
||||
@endif
|
||||
<div class="flex-1"></div>
|
||||
@if (isInstanceAdmin() && !isCloud())
|
||||
@persist('upgrade')
|
||||
<livewire:upgrade />
|
||||
@endpersist
|
||||
@endif
|
||||
<a title="Help us!" class="menu-item" href="https://coolify.io/sponsorships" target="_blank">
|
||||
<svg class="icon hover:text-pink-500" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2">
|
||||
<path d="M19.5 12.572L12 20l-7.5-7.428A5 5 0 1 1 12 6.006a5 5 0 1 1 7.5 6.572" />
|
||||
<path
|
||||
d="M12 6L8.707 9.293a1 1 0 0 0 0 1.414l.543.543c.69.69 1.81.69 2.5 0l1-1a3.182 3.182 0 0 1 4.5 0l2.25 2.25m-7 3l2 2M15 13l2 2" />
|
||||
</g>
|
||||
</svg>
|
||||
Help us!
|
||||
</a>
|
||||
|
||||
<div title="Send us feedback or get help!" class="menu-item" wire:click="help" onclick="help.showModal()">
|
||||
<svg class="icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M140 180a12 12 0 1 1-12-12a12 12 0 0 1 12 12M128 72c-22.06 0-40 16.15-40 36v4a8 8 0 0 0 16 0v-4c0-11 10.77-20 24-20s24 9 24 20s-10.77 20-24 20a8 8 0 0 0-8 8v8a8 8 0 0 0 16 0v-.72c18.24-3.35 32-17.9 32-35.28c0-19.85-17.94-36-40-36m104 56A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104m-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88" />
|
||||
</svg>
|
||||
Feedback
|
||||
</div>
|
||||
<form action="/logout" method="POST" class="mb-6 menu-item">
|
||||
@csrf
|
||||
<button title="Logout" type="submit" class="flex gap-2">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22m7-6v-3h-8v-2h8V8l5 4z" />
|
||||
</svg>
|
||||
Logout
|
||||
</button>
|
||||
</form>
|
||||
</ul>
|
||||
</nav>
|
||||
@endauth
|
@ -1,216 +1,293 @@
|
||||
@auth
|
||||
<nav class="h-screen pt-[4.5rem] border-r scrollbar bg-coolgray-100/40 border-r-coolgray-200">
|
||||
{{-- <div class="px-2 pb-2" id="vue">
|
||||
<magic-bar></magic-bar>
|
||||
</div> --}}
|
||||
<a href="/" class="fixed top-0 z-50 mx-3 mt-3 bg-transparent cursor-pointer"><img
|
||||
class="transition rounded w-11 h-11" src="{{ asset('coolify-transparent.png') }}"></a>
|
||||
<ul class="flex flex-col h-full gap-4 menu flex-nowrap">
|
||||
<a title="Dashboard" href="/" class="{{ request()->is('/') ? 'menu-item-active menu-item' : 'menu-item' }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
||||
</svg>
|
||||
Dashboard
|
||||
</a>
|
||||
<a title="Projects"
|
||||
class="{{ request()->is('project/*') || request()->is('projects') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="/projects">
|
||||
<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="M12 4l-8 4l8 4l8 -4l-8 -4" />
|
||||
<path d="M4 12l8 4l8 -4" />
|
||||
<path d="M4 16l8 4l8 -4" />
|
||||
</svg>
|
||||
Projects
|
||||
</a>
|
||||
<a title="Servers"
|
||||
class="{{ request()->is('server/*') || request()->is('servers') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="/servers">
|
||||
<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="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>
|
||||
Servers
|
||||
</a>
|
||||
<a title="Security" class="{{ request()->is('security*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('security.private-key.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m16.555 3.843l3.602 3.602a2.877 2.877 0 0 1 0 4.069l-2.643 2.643a2.877 2.877 0 0 1-4.069 0l-.301-.301l-6.558 6.558a2 2 0 0 1-1.239.578L5.172 21H4a1 1 0 0 1-.993-.883L3 20v-1.172a2 2 0 0 1 .467-1.284l.119-.13L4 17h2v-2h2v-2l2.144-2.144l-.301-.301a2.877 2.877 0 0 1 0-4.069l2.643-2.643a2.877 2.877 0 0 1 4.069 0zM15 9h.01" />
|
||||
</svg>
|
||||
Security
|
||||
</a>
|
||||
<a title="Source" class="{{ request()->is('source*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('source.all') }}">
|
||||
<svg class="icon" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="m6.793 1.207l.353.354l-.353-.354ZM1.207 6.793l-.353-.354l.353.354Zm0 1.414l.354-.353l-.354.353Zm5.586 5.586l-.354.353l.354-.353Zm1.414 0l-.353-.354l.353.354Zm5.586-5.586l.353.354l-.353-.354Zm0-1.414l-.354.353l.354-.353ZM8.207 1.207l.354-.353l-.354.353ZM6.44.854L.854 6.439l.707.707l5.585-5.585L6.44.854ZM.854 8.56l5.585 5.585l.707-.707l-5.585-5.585l-.707.707Zm7.707 5.585l5.585-5.585l-.707-.707l-5.585 5.585l.707.707Zm5.585-7.707L8.561.854l-.707.707l5.585 5.585l.707-.707Zm0 2.122a1.5 1.5 0 0 0 0-2.122l-.707.707a.5.5 0 0 1 0 .708l.707.707ZM6.44 14.146a1.5 1.5 0 0 0 2.122 0l-.707-.707a.5.5 0 0 1-.708 0l-.707.707ZM.854 6.44a1.5 1.5 0 0 0 0 2.122l.707-.707a.5.5 0 0 1 0-.708L.854 6.44Zm6.292-4.878a.5.5 0 0 1 .708 0L8.56.854a1.5 1.5 0 0 0-2.122 0l.707.707Zm-2 1.293l1 1l.708-.708l-1-1l-.708.708ZM7.5 5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 6V5Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 4.5H8ZM7.5 4a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 3v1Zm0-1A1.5 1.5 0 0 0 6 4.5h1a.5.5 0 0 1 .5-.5V3Zm.646 2.854l1.5 1.5l.707-.708l-1.5-1.5l-.707.708ZM10.5 8a.5.5 0 0 1-.5-.5H9A1.5 1.5 0 0 0 10.5 9V8Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 12 7.5h-1Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 10.5 6v1Zm0-1A1.5 1.5 0 0 0 9 7.5h1a.5.5 0 0 1 .5-.5V6ZM7 5.5v4h1v-4H7Zm.5 5.5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 12v-1Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 10.5H8Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 9v1Zm0-1A1.5 1.5 0 0 0 6 10.5h1a.5.5 0 0 1 .5-.5V9Z" />
|
||||
</svg>
|
||||
Sources
|
||||
</a>
|
||||
<a title="Notifications"
|
||||
class="{{ request()->is('notifications*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('notification.index') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3H4a4 4 0 0 0 2-3v-3a7 7 0 0 1 4-6M9 17v1a3 3 0 0 0 6 0v-1" />
|
||||
</svg>
|
||||
Notifications
|
||||
</a>
|
||||
<a title="Tags" class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('tags.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
|
||||
<path
|
||||
d="M3 8v4.172a2 2 0 0 0 .586 1.414l5.71 5.71a2.41 2.41 0 0 0 3.408 0l3.592-3.592a2.41 2.41 0 0 0 0-3.408l-5.71-5.71A2 2 0 0 0 9.172 6H5a2 2 0 0 0-2 2" />
|
||||
<path d="m18 19l1.592-1.592a4.82 4.82 0 0 0 0-6.816L15 6m-8 4h-.01" />
|
||||
</g>
|
||||
</svg>
|
||||
Tags
|
||||
</a>
|
||||
<a title="Command Center"
|
||||
class="{{ request()->is('command-center*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('command-center') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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="M5 7l5 5l-5 5" />
|
||||
<path d="M12 19l7 0" />
|
||||
</svg>
|
||||
Command Center
|
||||
</a>
|
||||
<a title="Profile" class="{{ request()->is('profile*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('profile') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
|
||||
<path d="M12 10m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
|
||||
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855" />
|
||||
</svg>
|
||||
Profile
|
||||
</a>
|
||||
<a title="Teams" class="{{ request()->is('team*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('team.index') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" />
|
||||
<path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M17 10h2a2 2 0 0 1 2 2v1" />
|
||||
<path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M3 13v-1a2 2 0 0 1 2 -2h2" />
|
||||
</svg>
|
||||
Teams
|
||||
</a>
|
||||
@if (isCloud())
|
||||
<a title="Subscription"
|
||||
class="{{ request()->is('subscription*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('subscription.show') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm0 2h18M7 15h.01M11 15h2" />
|
||||
</svg>
|
||||
Subscription
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if (isInstanceAdmin())
|
||||
<a title="Settings" class="{{ request()->is('settings*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="/settings">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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>
|
||||
Settings
|
||||
</a>
|
||||
@endif
|
||||
<a title="Onboarding" class="{{ request()->is('onboarding*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('onboarding') }}">
|
||||
<svg class="icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M224 128a8 8 0 0 1-8 8h-88a8 8 0 0 1 0-16h88a8 8 0 0 1 8 8m-96-56h88a8 8 0 0 0 0-16h-88a8 8 0 0 0 0 16m88 112h-88a8 8 0 0 0 0 16h88a8 8 0 0 0 0-16M82.34 42.34L56 68.69L45.66 58.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 132.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 196.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32" />
|
||||
</svg>
|
||||
Onboarding
|
||||
</a>
|
||||
{{-- <div class="menu-item" x-data="{ open: false }">
|
||||
<div>
|
||||
<button x-on:click.prevent="open = !open" x-on:click.away="open = false" type="button" id="menu-button"
|
||||
aria-expanded="true" aria-haspopup="true">
|
||||
<svg class="icon text-neutral-400" xmlns="http://www.w3.org/2000/svg" width="200" height="200"
|
||||
viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
<div class="flex items-center h-16 pt-2 lg:pt-4 shrink-0">
|
||||
<a href="/" class="flex items-center w-12 h-12 -mx-1 text-xl font-bold text-white"><img
|
||||
class="transition rounded " src="{{ asset('coolify-transparent.png') }}"></a>
|
||||
</div>
|
||||
<nav class="flex flex-col flex-1">
|
||||
<ul role="list" class="flex flex-col flex-1 gap-y-7">
|
||||
<li class="flex-1">
|
||||
<ul role="list" class="flex flex-col h-full -mx-2 space-y-1">
|
||||
<li>
|
||||
<a title="Dashboard" href="/"
|
||||
class="{{ request()->is('/') ? 'menu-item-active menu-item' : 'menu-item' }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="open" x-cloak
|
||||
class="absolute left-0 z-10 w-56 mx-4 mt-2 origin-top-right rounded shadow-lg bg-coolgray-100 ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
|
||||
<div class="py-1" role="none">
|
||||
Dashboard
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Projects"
|
||||
class="{{ request()->is('project/*') || request()->is('projects') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="/projects">
|
||||
<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="M12 4l-8 4l8 4l8 -4l-8 -4" />
|
||||
<path d="M4 12l8 4l8 -4" />
|
||||
<path d="M4 16l8 4l8 -4" />
|
||||
</svg>
|
||||
Projects
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Servers"
|
||||
class="{{ request()->is('server/*') || request()->is('servers') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="/servers">
|
||||
<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="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>
|
||||
Servers
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Security"
|
||||
class="{{ request()->is('security*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('security.private-key.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m16.555 3.843l3.602 3.602a2.877 2.877 0 0 1 0 4.069l-2.643 2.643a2.877 2.877 0 0 1-4.069 0l-.301-.301l-6.558 6.558a2 2 0 0 1-1.239.578L5.172 21H4a1 1 0 0 1-.993-.883L3 20v-1.172a2 2 0 0 1 .467-1.284l.119-.13L4 17h2v-2h2v-2l2.144-2.144l-.301-.301a2.877 2.877 0 0 1 0-4.069l2.643-2.643a2.877 2.877 0 0 1 4.069 0zM15 9h.01" />
|
||||
</svg>
|
||||
Security
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Source"
|
||||
class="{{ request()->is('source*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('source.all') }}">
|
||||
<svg class="icon" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="m6.793 1.207l.353.354l-.353-.354ZM1.207 6.793l-.353-.354l.353.354Zm0 1.414l.354-.353l-.354.353Zm5.586 5.586l-.354.353l.354-.353Zm1.414 0l-.353-.354l.353.354Zm5.586-5.586l.353.354l-.353-.354Zm0-1.414l-.354.353l.354-.353ZM8.207 1.207l.354-.353l-.354.353ZM6.44.854L.854 6.439l.707.707l5.585-5.585L6.44.854ZM.854 8.56l5.585 5.585l.707-.707l-5.585-5.585l-.707.707Zm7.707 5.585l5.585-5.585l-.707-.707l-5.585 5.585l.707.707Zm5.585-7.707L8.561.854l-.707.707l5.585 5.585l.707-.707Zm0 2.122a1.5 1.5 0 0 0 0-2.122l-.707.707a.5.5 0 0 1 0 .708l.707.707ZM6.44 14.146a1.5 1.5 0 0 0 2.122 0l-.707-.707a.5.5 0 0 1-.708 0l-.707.707ZM.854 6.44a1.5 1.5 0 0 0 0 2.122l.707-.707a.5.5 0 0 1 0-.708L.854 6.44Zm6.292-4.878a.5.5 0 0 1 .708 0L8.56.854a1.5 1.5 0 0 0-2.122 0l.707.707Zm-2 1.293l1 1l.708-.708l-1-1l-.708.708ZM7.5 5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 6V5Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 4.5H8ZM7.5 4a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 3v1Zm0-1A1.5 1.5 0 0 0 6 4.5h1a.5.5 0 0 1 .5-.5V3Zm.646 2.854l1.5 1.5l.707-.708l-1.5-1.5l-.707.708ZM10.5 8a.5.5 0 0 1-.5-.5H9A1.5 1.5 0 0 0 10.5 9V8Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 12 7.5h-1Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 10.5 6v1Zm0-1A1.5 1.5 0 0 0 9 7.5h1a.5.5 0 0 1 .5-.5V6ZM7 5.5v4h1v-4H7Zm.5 5.5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 12v-1Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 10.5H8Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 9v1Zm0-1A1.5 1.5 0 0 0 6 10.5h1a.5.5 0 0 1 .5-.5V9Z" />
|
||||
</svg>
|
||||
Sources
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Notifications"
|
||||
class="{{ request()->is('notifications*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('notification.index') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3H4a4 4 0 0 0 2-3v-3a7 7 0 0 1 4-6M9 17v1a3 3 0 0 0 6 0v-1" />
|
||||
</svg>
|
||||
Notifications
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Tags" class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('tags.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2">
|
||||
<path
|
||||
d="M3 8v4.172a2 2 0 0 0 .586 1.414l5.71 5.71a2.41 2.41 0 0 0 3.408 0l3.592-3.592a2.41 2.41 0 0 0 0-3.408l-5.71-5.71A2 2 0 0 0 9.172 6H5a2 2 0 0 0-2 2" />
|
||||
<path d="m18 19l1.592-1.592a4.82 4.82 0 0 0 0-6.816L15 6m-8 4h-.01" />
|
||||
</g>
|
||||
</svg>
|
||||
Tags
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Command Center"
|
||||
class="{{ request()->is('command-center*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('command-center') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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="M5 7l5 5l-5 5" />
|
||||
<path d="M12 19l7 0" />
|
||||
</svg>
|
||||
Command Center
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Profile"
|
||||
class="{{ request()->is('profile*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('profile') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
|
||||
<path d="M12 10m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
|
||||
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855" />
|
||||
</svg>
|
||||
Profile
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Teams"
|
||||
class="{{ request()->is('team*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('team.index') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" />
|
||||
<path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M17 10h2a2 2 0 0 1 2 2v1" />
|
||||
<path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M3 13v-1a2 2 0 0 1 2 -2h2" />
|
||||
</svg>
|
||||
Teams
|
||||
</a>
|
||||
</li>
|
||||
@if (isCloud())
|
||||
<li>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
@if (isCloud() && isInstanceAdmin())
|
||||
<a title="Admin" class="menu-item" href="/admin">
|
||||
<svg class="text-pink-600 icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M177.62 159.6a52 52 0 0 1-34 34a12.2 12.2 0 0 1-3.6.55a12 12 0 0 1-3.6-23.45a28 28 0 0 0 18.32-18.32a12 12 0 0 1 22.9 7.2ZM220 144a92 92 0 0 1-184 0c0-28.81 11.27-58.18 33.48-87.28a12 12 0 0 1 17.9-1.33l19.69 19.11L127 19.89a12 12 0 0 1 18.94-5.12C168.2 33.25 220 82.85 220 144m-24 0c0-41.71-30.61-78.39-52.52-99.29l-20.21 55.4a12 12 0 0 1-19.63 4.5L80.71 82.36C67 103.38 60 124.06 60 144a68 68 0 0 0 136 0" />
|
||||
</svg>
|
||||
Admin
|
||||
</a>
|
||||
@endif
|
||||
<div class="flex-1"></div>
|
||||
@if (isInstanceAdmin() && !isCloud())
|
||||
@persist('upgrade')
|
||||
<livewire:upgrade />
|
||||
@endpersist
|
||||
@endif
|
||||
<a title="Help us!" class="menu-item" href="https://coolify.io/sponsorships" target="_blank">
|
||||
<svg class="icon hover:text-pink-500" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2">
|
||||
<path d="M19.5 12.572L12 20l-7.5-7.428A5 5 0 1 1 12 6.006a5 5 0 1 1 7.5 6.572" />
|
||||
<path
|
||||
d="M12 6L8.707 9.293a1 1 0 0 0 0 1.414l.543.543c.69.69 1.81.69 2.5 0l1-1a3.182 3.182 0 0 1 4.5 0l2.25 2.25m-7 3l2 2M15 13l2 2" />
|
||||
</g>
|
||||
</svg>
|
||||
Help us!
|
||||
<a title="Subscription"
|
||||
class="{{ request()->is('subscription*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('subscription.show') }}">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"
|
||||
d="M3 8a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm0 2h18M7 15h.01M11 15h2" />
|
||||
</svg>
|
||||
Subscription
|
||||
</li>
|
||||
</a>
|
||||
@endif
|
||||
@if (isInstanceAdmin())
|
||||
<li>
|
||||
|
||||
<a title="Settings"
|
||||
class="{{ request()->is('settings*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="/settings">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" 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>
|
||||
Settings
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if (isCloud() && isInstanceAdmin())
|
||||
<li>
|
||||
|
||||
<a title="Admin" class="menu-item" href="/admin">
|
||||
<svg class="text-pink-600 icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M177.62 159.6a52 52 0 0 1-34 34a12.2 12.2 0 0 1-3.6.55a12 12 0 0 1-3.6-23.45a28 28 0 0 0 18.32-18.32a12 12 0 0 1 22.9 7.2ZM220 144a92 92 0 0 1-184 0c0-28.81 11.27-58.18 33.48-87.28a12 12 0 0 1 17.9-1.33l19.69 19.11L127 19.89a12 12 0 0 1 18.94-5.12C168.2 33.25 220 82.85 220 144m-24 0c0-41.71-30.61-78.39-52.52-99.29l-20.21 55.4a12 12 0 0 1-19.63 4.5L80.71 82.36C67 103.38 60 124.06 60 144a68 68 0 0 0 136 0" />
|
||||
</svg>
|
||||
Admin
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<div class="flex-1"></div>
|
||||
@if (isInstanceAdmin() && !isCloud())
|
||||
<li>
|
||||
@persist('upgrade')
|
||||
<livewire:upgrade />
|
||||
@endpersist
|
||||
</li>
|
||||
@endif
|
||||
<li>
|
||||
<a title="Onboarding"
|
||||
class="{{ request()->is('onboarding*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('onboarding') }}">
|
||||
<svg class="icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M224 128a8 8 0 0 1-8 8h-88a8 8 0 0 1 0-16h88a8 8 0 0 1 8 8m-96-56h88a8 8 0 0 0 0-16h-88a8 8 0 0 0 0 16m88 112h-88a8 8 0 0 0 0 16h88a8 8 0 0 0 0-16M82.34 42.34L56 68.69L45.66 58.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 132.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 196.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32" />
|
||||
</svg>
|
||||
Onboarding
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Help us!" class="menu-item" href="https://coolify.io/sponsorships" target="_blank">
|
||||
<svg class="icon hover:text-pink-500" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2">
|
||||
<path d="M19.5 12.572L12 20l-7.5-7.428A5 5 0 1 1 12 6.006a5 5 0 1 1 7.5 6.572" />
|
||||
<path
|
||||
d="M12 6L8.707 9.293a1 1 0 0 0 0 1.414l.543.543c.69.69 1.81.69 2.5 0l1-1a3.182 3.182 0 0 1 4.5 0l2.25 2.25m-7 3l2 2M15 13l2 2" />
|
||||
</g>
|
||||
</svg>
|
||||
Help us!
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<x-modal-input title="How can we help?">
|
||||
<x-slot:content>
|
||||
<div title="Send us feedback or get help!" class="cursor-pointer menu-item"
|
||||
wire:click="help" onclick="help.showModal()">
|
||||
<svg class="icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M140 180a12 12 0 1 1-12-12a12 12 0 0 1 12 12M128 72c-22.06 0-40 16.15-40 36v4a8 8 0 0 0 16 0v-4c0-11 10.77-20 24-20s24 9 24 20s-10.77 20-24 20a8 8 0 0 0-8 8v8a8 8 0 0 0 16 0v-.72c18.24-3.35 32-17.9 32-35.28c0-19.85-17.94-36-40-36m104 56A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104m-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88" />
|
||||
</svg>
|
||||
Feedback
|
||||
</div>
|
||||
</x-slot:content>
|
||||
<livewire:help />
|
||||
</x-modal-input>
|
||||
</li>
|
||||
<li>
|
||||
<form action="/logout" method="POST" class="mb-6 menu-item">
|
||||
@csrf
|
||||
<button title="Logout" type="submit" class="flex gap-2">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22m7-6v-3h-8v-2h8V8l5 4z" />
|
||||
</svg>
|
||||
Logout
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
{{-- <li>
|
||||
<div class="text-xs font-semibold leading-6 text-gray-400">Your teams</div>
|
||||
<ul role="list" class="mt-2 -mx-2 space-y-1">
|
||||
<li>
|
||||
<a href="#"
|
||||
class="flex p-2 text-sm font-semibold leading-6 text-gray-700 rounded-md hover:text-indigo-600 hover:bg-gray-50 group gap-x-3">
|
||||
<span
|
||||
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">H</span>
|
||||
<span class="truncate">Heroicons</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"
|
||||
class="flex p-2 text-sm font-semibold leading-6 text-gray-700 rounded-md hover:text-indigo-600 hover:bg-gray-50 group gap-x-3">
|
||||
<span
|
||||
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">T</span>
|
||||
<span class="truncate">Tailwind Labs</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"
|
||||
class="flex p-2 text-sm font-semibold leading-6 text-gray-700 rounded-md hover:text-indigo-600 hover:bg-gray-50 group gap-x-3">
|
||||
<span
|
||||
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">W</span>
|
||||
<span class="truncate">Workcation</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li> --}}
|
||||
{{-- <li class="mt-auto -mx-6">
|
||||
<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">
|
||||
<img class="w-8 h-8 rounded-full bg-gray-50"
|
||||
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
alt="">
|
||||
<span class="sr-only">Your profile</span>
|
||||
<span aria-hidden="true">Tom Cook</span>
|
||||
</a>
|
||||
|
||||
<div title="Send us feedback or get help!" class="menu-item" wire:click="help" onclick="help.showModal()">
|
||||
<svg class="icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M140 180a12 12 0 1 1-12-12a12 12 0 0 1 12 12M128 72c-22.06 0-40 16.15-40 36v4a8 8 0 0 0 16 0v-4c0-11 10.77-20 24-20s24 9 24 20s-10.77 20-24 20a8 8 0 0 0-8 8v8a8 8 0 0 0 16 0v-.72c18.24-3.35 32-17.9 32-35.28c0-19.85-17.94-36-40-36m104 56A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104m-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88" />
|
||||
</svg>
|
||||
Feedback
|
||||
</div>
|
||||
<form action="/logout" method="POST" class="mb-6 menu-item">
|
||||
@csrf
|
||||
<button title="Logout" type="submit" class="flex gap-2">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22m7-6v-3h-8v-2h8V8l5 4z" />
|
||||
</svg>
|
||||
Logout
|
||||
</button>
|
||||
</form>
|
||||
</ul>
|
||||
</nav>
|
||||
@endauth
|
||||
</li> --}}
|
||||
</ul>
|
||||
</nav>
|
||||
|
30
resources/views/components/popup.blade.php
Normal file
30
resources/views/components/popup.blade.php
Normal file
@ -0,0 +1,30 @@
|
||||
@props(['title' => 'Default title', 'description' => 'Default Description', 'buttonText' => 'Default Button Text'])
|
||||
<div x-data="{
|
||||
bannerVisible: false,
|
||||
bannerVisibleAfter: 300
|
||||
}" x-show="bannerVisible" x-transition:enter="transition ease-out duration-500"
|
||||
x-transition:enter-start="translate-y-full" x-transition:enter-end="translate-y-0"
|
||||
x-transition:leave="transition ease-in duration-300" x-transition:leave-start="translate-y-0"
|
||||
x-transition:leave-end="translate-y-full" x-init="setTimeout(() => { bannerVisible = true }, bannerVisibleAfter);"
|
||||
class="fixed bottom-0 right-0 w-full h-auto duration-300 ease-out sm:px-5 sm:pb-5 sm:w-[26rem] lg:w-full" x-cloak>
|
||||
<div
|
||||
class="flex flex-col items-center justify-between w-full h-full max-w-4xl p-6 mx-auto bg-white border-t shadow-lg dark:bg-coolgray-100 lg:p-8 lg:flex-row sm:border-0 sm:rounded-xl">
|
||||
<div
|
||||
class="flex flex-col items-start h-full pb-6 text-xs lg:items-center lg:flex-row lg:pb-0 lg:pr-6 lg:space-x-5 dark:text-neutral-300">
|
||||
<img src="https://cdn-icons-png.flaticon.com/512/8236/8236748.png"
|
||||
class="w-8 h-8 sm:w-12 sm:h-12 lg:w-16 lg:h-16">
|
||||
<div class="pt-6 lg:pt-0">
|
||||
<h4 class="w-full mb-1 text-xl font-bold leading-none -translate-y-1 text-neutral-900 dark:text-white">
|
||||
{{ $title }}
|
||||
</h4>
|
||||
<p class="">{{ $description }}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-end justify-end w-full pl-3 space-x-3 lg:flex-shrink-0 lg:w-auto">
|
||||
<button @click="bannerVisible=false;" {{ $buttonText->attributes }}
|
||||
class="inline-flex items-center justify-center flex-shrink-0 w-1/2 px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-200 bg-white rounded-md dark:bg-coolgray-200 lg:w-auto dark:text-neutral-200 dark:hover:bg-coolgray-300 focus:shadow-outline focus:outline-none">
|
||||
{{ $buttonText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,14 +1,7 @@
|
||||
<div class="pb-6">
|
||||
<h1>Security</h1>
|
||||
<nav class="flex pt-2 pb-10">
|
||||
<ol class="inline-flex items-center">
|
||||
<li>
|
||||
<div class="flex items-center">
|
||||
<span>Security related settings</span>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="subtitle">Security related settings.</div>
|
||||
|
||||
<nav class="navbar-main">
|
||||
<a href="{{ route('security.private-key.index') }}">
|
||||
<button>Private Keys</button>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<livewire:server.proxy.status :server="$server" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="subtitle ">{{ data_get($server, 'name') }}</div>
|
||||
<div class="subtitle ">{{ data_get($server, 'name') }}.</div>
|
||||
<nav class="navbar-main">
|
||||
<a class="{{ request()->routeIs('server.show') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.show', [
|
||||
@ -18,18 +18,18 @@
|
||||
]) }}">
|
||||
<button>General</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.resources') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.resources', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Resources</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.private-key') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.private-key', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Private Key</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.resources') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.resources', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Resources</button>
|
||||
</a>
|
||||
@if (!$server->isSwarmWorker() && !$server->settings->is_build_server)
|
||||
<a class="{{ request()->routeIs('server.proxy') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.proxy', [
|
||||
@ -52,7 +52,11 @@
|
||||
@endif
|
||||
|
||||
<div class="flex-1"></div>
|
||||
@if ($server->proxyType() !== 'NONE' && $server->isFunctional() && !$server->isSwarmWorker() && !$server->settings->is_build_server)
|
||||
@if (
|
||||
$server->proxyType() !== 'NONE' &&
|
||||
$server->isFunctional() &&
|
||||
!$server->isSwarmWorker() &&
|
||||
!$server->settings->is_build_server)
|
||||
<livewire:server.proxy.deploy :server="$server" />
|
||||
@endif
|
||||
</nav>
|
||||
|
@ -1,13 +1,15 @@
|
||||
@props([
|
||||
'status' => 'Degraded',
|
||||
])
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<div class="flex items-center" wire:loading.remove.delay.longer>
|
||||
<div class="badge badge-warning "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-widerr text-warning">
|
||||
{{ str($status)->before(':')->headline() }}
|
||||
</div>
|
||||
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
|
||||
<div class="text-xs text-warning">({{ str($status)->after(':') }})</div>
|
||||
@endif
|
||||
<div class="flex items-center" >
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<span wire:loading.remove.delay.longer class="flex items-center">
|
||||
<div class="badge badge-warning "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-widerr text-warning">
|
||||
{{ str($status)->before(':')->headline() }}
|
||||
</div>
|
||||
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
|
||||
<div class="text-xs text-warning">({{ str($status)->after(':') }})</div>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,13 +1,15 @@
|
||||
@props([
|
||||
'status' => 'Restarting',
|
||||
])
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<div class="flex items-center" wire:loading.remove.delay.longer>
|
||||
<div class="badge badge-warning "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-widerr text-warning">
|
||||
{{ str($status)->before(':')->headline() }}
|
||||
</div>
|
||||
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
|
||||
<div class="text-xs text-warning">({{ str($status)->after(':') }})</div>
|
||||
@endif
|
||||
<div class="flex items-center" >
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<span wire:loading.remove.delay.longer class="flex items-center">
|
||||
<div class="badge badge-warning "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-widerr text-warning">
|
||||
{{ str($status)->before(':')->headline() }}
|
||||
</div>
|
||||
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
|
||||
<div class="text-xs text-warning">({{ str($status)->after(':') }})</div>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,8 +1,9 @@
|
||||
@props([
|
||||
'status' => 'Running',
|
||||
])
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<div class="flex items-center" wire:loading.remove.delay.longer>
|
||||
<div class="flex items-center" >
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<span wire:loading.remove.delay.longer class="flex items-center">
|
||||
<div class="badge badge-success "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-wider text-success">
|
||||
{{ str($status)->before(':')->headline() }}
|
||||
@ -10,4 +11,5 @@
|
||||
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
|
||||
<div class="text-xs {{ str($status)->contains('unhealthy') ? 'text-warning' : 'text-success' }}">({{ str($status)->after(':') }})</div>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,8 +1,10 @@
|
||||
@props([
|
||||
'status' => 'Stopped',
|
||||
])
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<div class="flex items-center" wire:loading.remove.delay.longer>
|
||||
<div class="badge badge-error "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-wider text-error">{{ str($status)->before(':')->headline() }}</div>
|
||||
<div class="flex items-center">
|
||||
<x-loading wire:loading.delay.longer />
|
||||
<span wire:loading.remove.delay.longer class="flex items-center">
|
||||
<div class="badge badge-error "></div>
|
||||
<div class="pl-2 pr-1 text-xs font-bold tracking-wider text-error">{{ str($status)->before(':')->headline() }}</div>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,2 +1,2 @@
|
||||
<a {{ $attributes->merge(['class' => 'text-xs cursor-pointer opacity-60 hover:opacity-100 hover:text-white z-50']) }}
|
||||
<a {{ $attributes->merge(['class' => 'text-xs cursor-pointer opacity-60 hover:opacity-100 hover:text-white z-[60]']) }}
|
||||
href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('version') }}">v{{ config('version') }}</a>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<x-layout>
|
||||
<h1>Destinations</h1>
|
||||
<div class="subtitle ">All Destinations</div>
|
||||
<div class="subtitle ">All Destinations.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@forelse ($destinations as $destination)
|
||||
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
||||
|
@ -1,15 +1,64 @@
|
||||
@extends('layouts.base')
|
||||
@section('body')
|
||||
@parent
|
||||
|
||||
<livewire:layout-popups />
|
||||
@auth
|
||||
<livewire:realtime-connection />
|
||||
@endauth
|
||||
<main class="flex gap-2">
|
||||
<x-navbar />
|
||||
<div class="w-full px-10 pt-4">
|
||||
{{ $slot }}
|
||||
@auth
|
||||
<div x-data="{ open: false }" x-cloak>
|
||||
<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 flex">
|
||||
<div class="relative flex flex-1 w-full mr-16 max-w-56 ">
|
||||
<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">
|
||||
<span class="sr-only">Close sidebar</span>
|
||||
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col px-6 pb-2 overflow-y-auto dark:bg-coolgray-100 gap-y-5 scrollbar">
|
||||
<x-navbar />
|
||||
</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="flex flex-col px-4 overflow-y-auto grow gap-y-5 scrollbar">
|
||||
<x-navbar />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
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">
|
||||
<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">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="flex-1 text-xl font-bold leading-6 dark:text-white">Dashboard</div>
|
||||
{{-- <a href="#">
|
||||
<span class="sr-only">Your profile</span>
|
||||
<img class="w-8 h-8 rounded-full bg-gray-50"
|
||||
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
alt="">
|
||||
</a> --}}
|
||||
</div>
|
||||
|
||||
<main class="lg:pl-56">
|
||||
<div>
|
||||
<div class="p-4 sm:px-6 lg:px-8 lg:py-6">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</main>
|
||||
@endauth
|
||||
@endsection
|
||||
|
@ -40,14 +40,8 @@
|
||||
<body>
|
||||
{{-- <button onclick="changeTheme()" class="fixed z-50 left-52">Dark/light</button> --}}
|
||||
@livewire('wire-elements-modal')
|
||||
<dialog id="help" class="modal">
|
||||
<livewire:help />
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
<x-toast />
|
||||
<x-version class="fixed left-2 bottom-1" />
|
||||
<x-version class="fixed left-7 bottom-1" />
|
||||
<script data-navigate-once>
|
||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia(
|
||||
'(prefers-color-scheme: dark)').matches)) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
</div>
|
||||
@endif
|
||||
<div
|
||||
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 pt-6 text-xs text-white">
|
||||
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 text-xs text-white">
|
||||
|
||||
<pre class="font-mono whitespace-pre-wrap" @if ($isPollingActive) wire:poll.1000ms="polling" @endif>{{ RunRemoteProcess::decodeOutput($this->activity) }}</pre>
|
||||
</div>
|
||||
|
@ -2,10 +2,10 @@
|
||||
@if (session('error'))
|
||||
<span x-data x-init="$wire.emit('error', '{{ session('error') }}')" />
|
||||
@endif
|
||||
<h1>Dashboard</h1>
|
||||
<h1 class="title">Dashboard</h1>
|
||||
{{-- <div class="subtitle">Your self-hosted environment</div> --}}
|
||||
@if (request()->query->get('success'))
|
||||
<div class="mb-10 text-white rounded alert alert-success">
|
||||
<div class="mb-10 text-white rounded alert-success">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
|
@ -6,14 +6,14 @@
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if ($destination->network !== 'coolify')
|
||||
<x-new-modal isErrorButton buttonTitle="Delete Destination">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete Destination">
|
||||
This destination will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
||||
<div class="subtitle ">A Docker network in a non-swarm environment</div>
|
||||
<div class="subtitle ">A Docker network in a non-swarm environment.</div>
|
||||
@else
|
||||
<div class="subtitle ">Your swarm docker network. WIP</div>
|
||||
@endif
|
||||
|
@ -1,11 +1,10 @@
|
||||
<div class="flex flex-col w-11/12 max-w-5xl gap-2 modal-box">
|
||||
<h3>How can we help?</h3>
|
||||
<div class="flex flex-col w-full gap-2">
|
||||
<div>Your feedback helps us to improve Coolify. Thank you! 💜</div>
|
||||
<form wire:submit="submit" class="flex flex-col gap-4 pt-4">
|
||||
<x-forms.input id="subject" label="Subject" placeholder="Summary of your problem."></x-forms.input>
|
||||
<x-forms.textarea rows="10" id="description" label="Description"
|
||||
placeholder="Please provide as much information as possible."></x-forms.textarea>
|
||||
<div></div>
|
||||
<x-forms.button class="w-full mt-4" type="submit" onclick="help.close()">Send</x-forms.button>
|
||||
<x-forms.button class="w-full mt-4" type="submit" @click="modalOpen=false">Send</x-forms.button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,6 +1,22 @@
|
||||
<div>
|
||||
@if (data_get(auth()->user(), 'is_notification_sponsorship_enabled'))
|
||||
<div class="toast">
|
||||
<x-popup>
|
||||
<x-slot:title>
|
||||
Love Coolify as we do?
|
||||
</x-slot:title>
|
||||
<x-slot:description>
|
||||
<span>Please
|
||||
consider donating on <a href="https://github.com/sponsors/coollabsio"
|
||||
class="text-xs text-white underline">GitHub</a> or <a href="https://opencollective.com/coollabsio"
|
||||
class="text-xs text-white underline">OpenCollective</a>.<br><br></span>
|
||||
<span>It enables us to keep creating features without paywalls, ensuring our work remains free and
|
||||
open.</span>
|
||||
</x-slot:description>
|
||||
<x-slot:button-text wire:click='disableSponsorship'>
|
||||
Disable This Popup
|
||||
</x-slot:button-text>
|
||||
</x-popup>
|
||||
{{-- <div class="toast">
|
||||
<div class="flex flex-col text-white rounded alert bg-coolgray-200">
|
||||
<span>Love Coolify as we do? <a href="https://coolify.io/sponsorships"
|
||||
class="underline text-warning">Please
|
||||
@ -10,8 +26,9 @@ class="underline text-warning">Please
|
||||
<x-forms.button class="bg-coolgray-400" wire:click='disableSponsorship'>Disable This
|
||||
Popup</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
@endif
|
||||
{{-- <x-popup /> --}}
|
||||
@if (currentTeam()->serverOverflow())
|
||||
<x-banner :closable=false>
|
||||
<div><span class="font-bold text-red-500">WARNING:</span> The number of active servers exceeds the limit
|
||||
@ -24,10 +41,12 @@ class="text-white underline">/subscription</a> to update your subscription or re
|
||||
@if (!currentTeam()->isAnyNotificationEnabled())
|
||||
<div class="toast">
|
||||
<div class="flex flex-col text-white rounded alert bg-coolgray-200">
|
||||
<span><span class="font-bold text-red-500">WARNING:</span> No notifications enabled.<br><br> It is highly recommended to enable at least
|
||||
<span><span class="font-bold text-red-500">WARNING:</span> No notifications enabled.<br><br> It is
|
||||
highly recommended to enable at least
|
||||
one
|
||||
notification channel to receive important alerts.<br>Visit <a href="{{ route('notification.index') }}"
|
||||
class="text-white underline">/notification</a> to enable notifications.</span>
|
||||
notification channel to receive important alerts.<br>Visit <a
|
||||
href="{{ route('notification.index') }}" class="text-white underline">/notification</a> to
|
||||
enable notifications.</span>
|
||||
<x-forms.button class="bg-coolgray-400" wire:click='disableNotifications'>Disable This
|
||||
Popup</x-forms.button>
|
||||
</div>
|
||||
|
@ -1,15 +1,4 @@
|
||||
<div>
|
||||
<dialog id="sendTestEmail" class="modal">
|
||||
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit='submit'>
|
||||
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
||||
<x-forms.button onclick="sendTestEmail.close()" wire:click="sendTestNotification">
|
||||
Send Email
|
||||
</x-forms.button>
|
||||
</form>
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
<form wire:submit='submit' class="flex flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Email</h2>
|
||||
@ -21,15 +10,17 @@
|
||||
Copy from Instance Settings
|
||||
</x-forms.button>
|
||||
@endif
|
||||
@if (isEmailEnabled($team) &&
|
||||
auth()->user()->isAdminFromSession() &&
|
||||
isTestEmailEnabled($team))
|
||||
<x-forms.button onclick="sendTestEmail.showModal()"
|
||||
class="text-white normal-case btn btn-xs no-animation btn-primary">
|
||||
Send Test Email
|
||||
</x-forms.button>
|
||||
@if (isEmailEnabled($team) && auth()->user()->isAdminFromSession() && isTestEmailEnabled($team))
|
||||
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
||||
<form wire:submit='submit' class="flex flex-col w-full gap-2">
|
||||
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
||||
<x-forms.button onclick="sendTestEmail.close()" wire:click="sendTestNotification"
|
||||
@click="modalOpen=false">
|
||||
Send Email
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</x-modal-input>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</form>
|
||||
@if (isCloud())
|
||||
@ -45,7 +36,7 @@ class="text-white normal-case btn btn-xs no-animation btn-primary">
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="pb-4 w-96">
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave="instantSaveInstance" id="team.use_instance_email_settings"
|
||||
label="Use system wide (transactional) email settings" />
|
||||
</div>
|
||||
|
@ -1,12 +1,8 @@
|
||||
<dialog id="newEmptyProject" class="modal">
|
||||
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit='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>
|
||||
<form class="flex flex-col gap-2 rounded" wire:submit='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" />
|
||||
<div class="subtitle">New project will have a default production environment.</div>
|
||||
<x-forms.button type="submit" @click="slideOverOpen=false">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</form>
|
||||
|
@ -1,11 +1,6 @@
|
||||
<dialog id="newEnvironment" class="modal">
|
||||
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit='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>
|
||||
<form class="flex flex-col gap-2 rounded" wire:submit='submit'>
|
||||
<x-forms.input placeholder="production" id="name" label="Name" required />
|
||||
<x-forms.button type="submit" @click="slideOverOpen=false">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</form>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<h2>Advanced</h2>
|
||||
</div>
|
||||
<div>Advanced configuration for your application.</div>
|
||||
<div class="flex flex-col gap-2 pt-4 w-96">
|
||||
<div class="pt-4 w-96">
|
||||
<h3>General</h3>
|
||||
@if ($application->git_based())
|
||||
<x-forms.checkbox helper="Automatically deploy new commits based on Git webhooks." instantSave
|
||||
|
@ -6,39 +6,30 @@
|
||||
@if ($skip == 0) wire:poll.5000ms='reload_deployments' @endif>
|
||||
<div class="flex items-end gap-2 pt-4">
|
||||
<h2>Deployments <span class="text-xs">({{ $deployments_count }})</span></h2>
|
||||
@if ($show_prev)
|
||||
<x-forms.button wire:click="previous_page({{ $default_take }})"><svg class="w-6 h-6" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
@if ($deployments_count > 0)
|
||||
<x-forms.button disabled="{{ !$show_prev }}" wire:click="previous_page('{{ $default_take }}')"><svg
|
||||
class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg></x-forms.button>
|
||||
@else
|
||||
<x-forms.button disabled><svg class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg></x-forms.button>
|
||||
@endif
|
||||
@if ($show_next)
|
||||
<x-forms.button wire:click="next_page({{ $default_take }})"><svg class="w-6 h-6" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg></x-forms.button>
|
||||
@else
|
||||
<x-forms.button disabled><svg class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<x-forms.button disabled="{{ !$show_next }}" wire:click="next_page('{{ $default_take }}')"><svg
|
||||
class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg></x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
<form class="flex items-end gap-2">
|
||||
<x-forms.input id="pull_request_id" label="Pull Request"></x-forms.input>
|
||||
<x-forms.button type="submit">Filter</x-forms.button>
|
||||
</form>
|
||||
@if ($deployments_count > 0)
|
||||
<form class="flex items-end gap-2">
|
||||
<x-forms.input id="pull_request_id" label="Pull Request"></x-forms.input>
|
||||
<x-forms.button type="submit">Filter</x-forms.button>
|
||||
</form>
|
||||
@endif
|
||||
@forelse ($deployments as $deployment)
|
||||
<a @class([
|
||||
'bg-coolgray-100 p-2 border-l border-dashed transition-colors hover:no-underline',
|
||||
'hover:bg-coolgray-200' => data_get($deployment, 'status') === 'queued',
|
||||
'dark:bg-coolgray-100 p-2 border-l border-dashed transition-colors hover:no-underline',
|
||||
'dark:hover:bg-coolgray-200' =>
|
||||
data_get($deployment, 'status') === 'queued',
|
||||
'border-warning hover:bg-warning hover:text-black' =>
|
||||
data_get($deployment, 'status') === 'in_progress' ||
|
||||
data_get($deployment, 'status') === 'cancelled-by-user',
|
||||
@ -98,42 +89,44 @@ class="hover:no-underline">
|
||||
@empty
|
||||
<div class="">No deployments found</div>
|
||||
@endforelse
|
||||
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/utc.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/relativeTime.js"></script>
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
let timers = {};
|
||||
@if ($deployments_count > 0)
|
||||
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/utc.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/relativeTime.js"></script>
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
let timers = {};
|
||||
|
||||
dayjs.extend(window.dayjs_plugin_utc);
|
||||
dayjs.extend(window.dayjs_plugin_relativeTime);
|
||||
dayjs.extend(window.dayjs_plugin_utc);
|
||||
dayjs.extend(window.dayjs_plugin_relativeTime);
|
||||
|
||||
Alpine.data('elapsedTime', (uuid, status, created_at, updated_at) => ({
|
||||
finished_time: 'calculating...',
|
||||
started_time: 'calculating...',
|
||||
init() {
|
||||
if (timers[uuid]) {
|
||||
clearInterval(timers[uuid]);
|
||||
Alpine.data('elapsedTime', (uuid, status, created_at, updated_at) => ({
|
||||
finished_time: 'calculating...',
|
||||
started_time: 'calculating...',
|
||||
init() {
|
||||
if (timers[uuid]) {
|
||||
clearInterval(timers[uuid]);
|
||||
}
|
||||
if (status === 'in_progress') {
|
||||
timers[uuid] = setInterval(() => {
|
||||
this.finished_time = dayjs().diff(dayjs.utc(created_at),
|
||||
'second') + 's'
|
||||
}, 1000);
|
||||
} else {
|
||||
let seconds = dayjs.utc(updated_at).diff(dayjs.utc(created_at), 'second')
|
||||
this.finished_time = seconds + 's';
|
||||
}
|
||||
},
|
||||
measure_finished_time() {
|
||||
return this.finished_time;
|
||||
},
|
||||
measure_since_started() {
|
||||
return dayjs.utc(created_at).fromNow();
|
||||
}
|
||||
if (status === 'in_progress') {
|
||||
timers[uuid] = setInterval(() => {
|
||||
this.finished_time = dayjs().diff(dayjs.utc(created_at),
|
||||
'second') + 's'
|
||||
}, 1000);
|
||||
} else {
|
||||
let seconds = dayjs.utc(updated_at).diff(dayjs.utc(created_at), 'second')
|
||||
this.finished_time = seconds + 's';
|
||||
}
|
||||
},
|
||||
measure_finished_time() {
|
||||
return this.finished_time;
|
||||
},
|
||||
measure_since_started() {
|
||||
return dayjs.utc(created_at).fromNow();
|
||||
}
|
||||
}))
|
||||
})
|
||||
</script>
|
||||
}))
|
||||
})
|
||||
</script>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -3,13 +3,13 @@
|
||||
<h2>Rollback</h2>
|
||||
<x-forms.button wire:click='loadImages(true)'>Reload Available Images</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4 ">You can easily rollback to a previously built <span class="text-warning">(local)</span> images
|
||||
<div class="pb-4 ">You can easily rollback to a previously built (local) images
|
||||
quickly.</div>
|
||||
<div wire:target='loadImages'>
|
||||
<div class="flex flex-wrap">
|
||||
@forelse ($images as $image)
|
||||
<div class="w-2/4 p-2">
|
||||
<div class="rounded shadow-lg bg-coolgray-200">
|
||||
<div class="rounded shadow-lg bg-coolgray-100">
|
||||
<div class="p-2">
|
||||
<div class="">
|
||||
@if (data_get($image, 'is_current'))
|
||||
|
@ -1,7 +1,7 @@
|
||||
<form>
|
||||
<div class="flex flex-col">
|
||||
<h1>Clone</h1>
|
||||
<div class="subtitle ">Quickly clone all resources to a new project or environment</div>
|
||||
<div class="subtitle ">Quickly clone all resources to a new project or environment.</div>
|
||||
</div>
|
||||
<x-forms.input required id="newName" label="New Name" />
|
||||
<x-forms.button isHighlighted wire:click="clone('project')" class="mt-4">Clone to a new Project</x-forms.button>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div>
|
||||
<h2>Import Backup</h2>
|
||||
<div class="mt-2 mb-4 rounded alert alert-error">
|
||||
<div class="mt-2 mb-4 rounded alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
@ -23,7 +23,7 @@
|
||||
<x-forms.input class="mb-2" label="Custom Import Command"
|
||||
wire:model='mariadbRestoreCommand'></x-forms.input>
|
||||
@endif
|
||||
<div x-on:livewire-upload-start="isUploading = true; isFinished = false"
|
||||
<div x-on:livewire-upload-start="isUploading = true; isFinished = false"
|
||||
x-on:livewire-upload-finish="isUploading = false; isFinished = true"
|
||||
x-on:livewire-upload-error="isUploading = false"
|
||||
x-on:livewire-upload-progress="progress = $event.detail.progress">
|
||||
|
@ -82,7 +82,7 @@
|
||||
<div class="pb-16">
|
||||
<div class="flex gap-2 pt-4 pb-2">
|
||||
<h3>Initialization scripts</h3>
|
||||
<x-forms.button class="btn" onclick="newInitScript.showModal()">+ Add</x-forms.button>
|
||||
<x-forms.button onclick="newInitScript.showModal()">+ Add</x-forms.button>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
@forelse(data_get($database,'init_scripts', []) as $script)
|
||||
|
@ -1,3 +1,3 @@
|
||||
<x-new-modal isErrorButton buttonTitle="Delete Environment" disabled="{{ $disabled }}">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete Environment" disabled="{{ $disabled }}">
|
||||
This environment will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
|
@ -1,3 +1,3 @@
|
||||
<x-new-modal isErrorButton buttonTitle="Delete Project" disabled="{{ $disabled }}">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete Project" disabled="{{ $disabled }}">
|
||||
This project will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
|
@ -2,10 +2,17 @@
|
||||
<div class="flex gap-2">
|
||||
<h1>Projects</h1>
|
||||
@if ($servers > 0)
|
||||
<x-forms.button onclick="newEmptyProject.showModal()">+ Add</x-forms.button>
|
||||
<livewire:project.add-empty />
|
||||
<x-slide-over>
|
||||
<x-slot:title>New Project</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.add-empty />
|
||||
</x-slot:content>
|
||||
<button @click="slideOverOpen=true" class="button">+
|
||||
Add</button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<div class="subtitle">All your projects.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@if ($servers === 0)
|
||||
<div>
|
||||
|
@ -10,13 +10,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="pb-4 ">Deploy resources, like Applications, Databases, Services...</div>
|
||||
<div class="flex flex-col gap-4 pt-10 sm:px-20">
|
||||
<div class="flex flex-col gap-4 pt-10">
|
||||
@if ($current_step === 'type')
|
||||
<ul class="pb-10 steps">
|
||||
{{-- <ul class="pb-10 steps">
|
||||
<li class="step step-secondary">Select Resource Type</li>
|
||||
<li class="step">Select a Server</li>
|
||||
<li class="step">Select a Destination</li>
|
||||
</ul>
|
||||
</ul> --}}
|
||||
<h2>Applications</h2>
|
||||
<div class="grid justify-start grid-cols-1 gap-4 text-left xl:grid-cols-3">
|
||||
<x-resource-view wire="setType('public')">
|
||||
@ -167,7 +167,7 @@
|
||||
<h2 class="py-4">Services</h2>
|
||||
<x-forms.button wire:click="loadServices('force')">Reload List</x-forms.button>
|
||||
<input
|
||||
class="w-full text-white rounded input input-sm bg-coolgray-200 disabled:bg-coolgray-200/50 disabled:border-none placeholder:text-coolgray-500 read-only:text-neutral-500 read-only:bg-coolgray-200/50"
|
||||
class="input"
|
||||
wire:model.live.debounce.200ms="search" autofocus placeholder="Search...">
|
||||
</div>
|
||||
<div class="grid justify-start grid-cols-1 gap-4 text-left xl:grid-cols-3">
|
||||
@ -254,11 +254,11 @@ class="w-full text-white rounded input input-sm bg-coolgray-200 disabled:bg-cool
|
||||
companies, and use of them does not imply any affiliation or endorsement.</div>
|
||||
@endif
|
||||
@if ($current_step === 'servers')
|
||||
<ul class="pb-10 steps">
|
||||
{{-- <ul class="pb-10 steps">
|
||||
<li class="step step-secondary">Select Resource Type</li>
|
||||
<li class="step step-secondary">Select a Server</li>
|
||||
<li class="step">Select a Destination</li>
|
||||
</ul>
|
||||
</ul> --}}
|
||||
|
||||
{{-- @if ($isDatabase)
|
||||
<div class="flex items-center justify-center pt-4">
|
||||
@ -295,11 +295,11 @@ class="w-full text-white rounded input input-sm bg-coolgray-200 disabled:bg-cool
|
||||
@endif --}}
|
||||
@endif
|
||||
@if ($current_step === 'destinations')
|
||||
<ul class="pb-10 steps">
|
||||
{{-- <ul class="pb-10 steps">
|
||||
<li class="step step-secondary">Select Resource Type</li>
|
||||
<li class="step step-secondary">Select a Server</li>
|
||||
<li class="step step-secondary">Select a Destination</li>
|
||||
</ul>
|
||||
</ul> --}}
|
||||
|
||||
<div class="flex flex-col justify-center gap-4 text-left xl:flex-row xl:flex-wrap">
|
||||
@if ($server->isSwarm())
|
||||
|
@ -3,15 +3,15 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>Resources</h1>
|
||||
@if ($environment->isEmpty())
|
||||
<a class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation"
|
||||
<a class="button"
|
||||
href="{{ route('project.clone-me', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}">
|
||||
Clone
|
||||
</a>
|
||||
@else
|
||||
<a href="{{ route('project.resource.create', ['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">+
|
||||
class="button">+
|
||||
New</a>
|
||||
<a class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation"
|
||||
<a class="button"
|
||||
href="{{ route('project.clone-me', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}">
|
||||
Clone
|
||||
</a>
|
||||
@ -45,7 +45,7 @@ class="font-normal text-white normal-case border-none rounded hover:no-underline
|
||||
class="items-center justify-center box">+ Add New Resource</a>
|
||||
@else
|
||||
<div x-data="searchComponent()">
|
||||
<x-forms.input autofocus="true" placeholder="Search for name, fqdn..." class="w-full" x-model="search" />
|
||||
<x-forms.input autofocus placeholder="Search for name, fqdn..." class="w-full" x-model="search" />
|
||||
<div class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<template x-for="item in filteredApplications" :key="item.id">
|
||||
<span>
|
||||
|
@ -11,13 +11,17 @@
|
||||
helper="For Preview Deployments, storage has a <span class='text-helper'>-pr-#PRNumber</span> in their
|
||||
volume
|
||||
name, example: <span class='text-helper'>-pr-1</span>" />
|
||||
<x-forms.button class="btn" onclick="newStorage.showModal()">+ Add</x-forms.button>
|
||||
<livewire:project.shared.storages.add :uuid="$resource->uuid" />
|
||||
<x-slide-over>
|
||||
<x-slot:title>New Persistent Storage</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.storages.add :uuid="$resource->uuid" />
|
||||
</x-slot:content>
|
||||
<button @click="slideOverOpen=true" class="button">+ Add</button>
|
||||
</x-slide-over>
|
||||
{{-- <x-forms.button onclick="newStorage.showModal()">+ Add</x-forms.button> --}}
|
||||
</div>
|
||||
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
|
||||
@if (
|
||||
$resource->persistentStorages()->get()->count() === 0 &&
|
||||
$resource->fileStorages()->get()->count() == 0)
|
||||
@if ($resource->persistentStorages()->get()->count() === 0 && $resource->fileStorages()->get()->count() == 0)
|
||||
<div>No storage found.</div>
|
||||
@else
|
||||
@if ($resource->persistentStorages()->get()->count() > 0)
|
||||
@ -33,9 +37,7 @@
|
||||
@endif
|
||||
@endif
|
||||
@else
|
||||
@if (
|
||||
$resource->persistentStorages()->get()->count() > 0 ||
|
||||
$resource->fileStorages()->get()->count() > 0)
|
||||
@if ($resource->persistentStorages()->get()->count() > 0 || $resource->fileStorages()->get()->count() > 0)
|
||||
<h3 class="pt-4">{{ Str::headline($resource->name) }} </h3>
|
||||
@endif
|
||||
@if ($resource->persistentStorages()->get()->count() > 0)
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="pb-4">This will stop your containers, delete all related data, etc. Beware! There is no coming
|
||||
back!
|
||||
</div>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This resource will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
|
@ -55,12 +55,12 @@ class="absolute bg-error -top-1 -left-1 badge "></div>
|
||||
<x-forms.button isError
|
||||
wire:click="stop('{{ data_get($destination, 'server.id') }}')">Stop</x-forms.button>
|
||||
@endif
|
||||
<x-new-modal
|
||||
<x-modal-confirmation
|
||||
action="removeServer({{ data_get($destination, 'id') }},{{ data_get($destination, 'server.id') }})"
|
||||
isErrorButton buttonTitle="Remove Server">
|
||||
This will stop the running application in this server and remove it as a deployment
|
||||
destination.<br><br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
|
||||
</div>
|
||||
@endforeach
|
||||
|
@ -39,10 +39,10 @@ class="flex flex-col gap-2 p-4 m-2 border lg:items-center border-coolgray-300 lg
|
||||
@endif
|
||||
<div class="flex gap-2">
|
||||
@if ($isLocked)
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
You will delete environment variable <span
|
||||
class="font-bold text-warning">{{ $env->key }}</span>.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@else
|
||||
@if ($isDisabled)
|
||||
<x-forms.button disabled type="submit">
|
||||
@ -51,10 +51,10 @@ class="font-bold text-warning">{{ $env->key }}</span>.
|
||||
<x-forms.button wire:click='lock'>
|
||||
Lock
|
||||
</x-forms.button>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
You will delete environment variable <span
|
||||
class="font-bold text-warning">{{ $env->key }}</span>.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@else
|
||||
<x-forms.button type="submit">
|
||||
Update
|
||||
@ -62,10 +62,10 @@ class="font-bold text-warning">{{ $env->key }}</span>.
|
||||
<x-forms.button wire:click='lock'>
|
||||
Lock
|
||||
</x-forms.button>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
You will delete environment variable <span
|
||||
class="font-bold text-warning">{{ $env->key }}</span>.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
@ -50,7 +50,7 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="container w-full pt-10 mx-auto">
|
||||
<div class="w-full pt-10 mx-auto">
|
||||
<livewire:activity-monitor header="Command output" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div>
|
||||
<div class="grid grid-cols-1 gap-2 pb-4 lg:grid-cols-4">
|
||||
@foreach ($server->destinations() as $destination)
|
||||
<x-new-modal action="cloneTo({{ data_get($destination, 'id') }})">
|
||||
<x-modal-confirmation action="cloneTo({{ data_get($destination, 'id') }})">
|
||||
<x:slot name="content">
|
||||
<div class="flex flex-col gap-2 box">
|
||||
<div class="font-bold text-white">{{ $server->name }}</div>
|
||||
@ -19,7 +19,7 @@
|
||||
</div>
|
||||
</x:slot>
|
||||
<div>You are about to clone this resource.</div>
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@ -37,7 +37,7 @@ class="font-bold text-warning">{{ $resource->environment->project->name }} /
|
||||
@forelse ($projects as $project)
|
||||
<div class="flex flex-row flex-wrap gap-2">
|
||||
@foreach ($project->environments as $environment)
|
||||
<x-new-modal action="moveTo({{ data_get($environment, 'id') }})">
|
||||
<x-modal-confirmation action="moveTo({{ data_get($environment, 'id') }})">
|
||||
<x:slot name="content">
|
||||
<div class="flex flex-col gap-2 box">
|
||||
<div class="font-bold text-white">{{ $project->name }}</div>
|
||||
@ -45,7 +45,7 @@ class="font-bold text-warning">{{ $resource->environment->project->name }} /
|
||||
</div>
|
||||
</x:slot>
|
||||
<div>You are about to move this resource.</div>
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
|
@ -13,9 +13,9 @@
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete Scheduled Task">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete Scheduled Task">
|
||||
You will delete scheduled task <span class="font-bold text-warning">{{ $task->name }}</span>.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full gap-2">
|
||||
|
@ -1,28 +1,18 @@
|
||||
<dialog id="newStorage" class="modal">
|
||||
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit='submit'>
|
||||
<h3 class="text-lg font-bold">Add Storage Volume</h3>
|
||||
@if ($isSwarm)
|
||||
<h5>Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you would like to use a persistent volumes.</h5>
|
||||
@endif
|
||||
<x-forms.input placeholder="pv-name" id="name" label="Name" required helper="Volume name." />
|
||||
@if ($isSwarm)
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" required helper="Directory on the host system." />
|
||||
@else
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" helper="Directory on the host system." />
|
||||
@endif
|
||||
<x-forms.input placeholder="/tmp/root" id="mount_path" label="Destination Path" required helper="Directory inside the container." />
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</form>
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
<script>
|
||||
document.addEventListener('livewire:initialized', () => {
|
||||
Livewire.on('closeStorageModal', () => {
|
||||
document.getElementById('newStorage').close()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</dialog>
|
||||
<form class="flex flex-col gap-2 rounded" wire:submit='submit'>
|
||||
@if ($isSwarm)
|
||||
<h5>Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you would
|
||||
like to use a persistent volumes.</h5>
|
||||
@endif
|
||||
<x-forms.input placeholder="pv-name" id="name" label="Name" required helper="Volume name." />
|
||||
@if ($isSwarm)
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" required
|
||||
helper="Directory on the host system." />
|
||||
@else
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" helper="Directory on the host system." />
|
||||
@endif
|
||||
<x-forms.input placeholder="/tmp/root" id="mount_path" label="Destination Path" required
|
||||
helper="Directory inside the container." />
|
||||
<x-forms.button type="submit" @click="slideOverOpen=false">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</form>
|
||||
|
@ -24,12 +24,12 @@
|
||||
<x-forms.button type="submit">
|
||||
Update
|
||||
</x-forms.button>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This storage will be deleted <span class="font-bold text-warning">{{ $storage->name }}</span>. It
|
||||
is
|
||||
not
|
||||
reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
|
@ -9,7 +9,7 @@
|
||||
helper="See details in our <a target='_blank' class='text-white underline' href='https://coolify.io/docs/api/authentication'>documentation</a>."
|
||||
label="Deploy Webhook (auth required)" id="deploywebhook"></x-forms.input>
|
||||
</div>
|
||||
@if ($resource->type() !== 'service')
|
||||
@if ($resource->type() === 'application')
|
||||
<div>
|
||||
<h3>Manual Git Webhooks</h3>
|
||||
@if ($githubManualWebhook && $gitlabManualWebhook)
|
||||
@ -35,7 +35,10 @@
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input readonly label="Bitbucket" id="bitbucketManualWebhook"></x-forms.input>
|
||||
<x-forms.input type="password" helper="Need to set a secret to be able to use this webhook. It should match with the secret in Bitbucket." label="Bitbucket Webhook Secret" id="resource.manual_webhook_secret_bitbucket"></x-forms.input>
|
||||
<x-forms.input type="password"
|
||||
helper="Need to set a secret to be able to use this webhook. It should match with the secret in Bitbucket."
|
||||
label="Bitbucket Webhook Secret"
|
||||
id="resource.manual_webhook_secret_bitbucket"></x-forms.input>
|
||||
</div>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
</form>
|
||||
|
@ -1,11 +1,17 @@
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>Environments</h1>
|
||||
<x-forms.button class="btn" onclick="newEnvironment.showModal()">+ Add</x-forms.button>
|
||||
<livewire:project.add-environment :project="$project" />
|
||||
<x-slide-over>
|
||||
<x-slot:title>New Environment</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.add-environment :project="$project" />
|
||||
</x-slot:content>
|
||||
<button @click="slideOverOpen=true" class="button">+
|
||||
Add</button>
|
||||
</x-slide-over>
|
||||
<livewire:project.delete-project :disabled="$project->resource_count() > 0" :project_id="$project->id" />
|
||||
</div>
|
||||
<div class="text-xs truncate subtitle lg:text-sm">{{ $project->name }}</div>
|
||||
<div class="text-xs truncate subtitle lg:text-sm">{{ $project->name }}.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@forelse ($project->environments as $environment)
|
||||
<div class="gap-2 border border-transparent cursor-pointer box group" x-data
|
||||
|
@ -13,7 +13,7 @@
|
||||
<x-forms.button type="submit">Execute Command
|
||||
</x-forms.button>
|
||||
</form>
|
||||
<div class="container w-full pt-10 mx-auto">
|
||||
<div class="w-full pt-10 mx-auto">
|
||||
<livewire:activity-monitor header="Command output" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<x-forms.button type="submit">Create New Token</x-forms.button>
|
||||
</form>
|
||||
@if (session()->has('token'))
|
||||
<div class="pb-4 font-bold text-warning">Please copy this token now. For your security, it won't be shown again.
|
||||
<div class="py-4 font-bold text-warning">Please copy this token now. For your security, it won't be shown again.
|
||||
</div>
|
||||
<div class="pb-4 font-bold text-white"> {{ session('token') }}</div>
|
||||
@endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div>
|
||||
<h2>Private Key</h2>
|
||||
<div class="subtitle ">Private Keys are used to connect to your servers without passwords.</div>
|
||||
<h1>Private Key</h1>
|
||||
<div class="subtitle">Private Keys are used to connect to your servers without passwords.</div>
|
||||
<x-forms.button class="mb-4" wire:click="generateNewKey">Generate new SSH key for me</x-forms.button>
|
||||
<form class="flex flex-col gap-2" wire:submit='createPrivateKey'>
|
||||
<div class="flex gap-2">
|
||||
|
@ -8,9 +8,9 @@
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if (data_get($private_key, 'id') > 0)
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This private key will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.input id="private_key.name" label="Name" required />
|
||||
|
@ -8,13 +8,13 @@
|
||||
</div>
|
||||
@if ($server->definedResources()->count() > 0)
|
||||
<div class="pb-2 text-red-500">You need to delete all resources before deleting this server.</div>
|
||||
<x-new-modal disabled isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation disabled isErrorButton buttonTitle="Delete">
|
||||
This server will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@else
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This server will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
@ -3,11 +3,11 @@
|
||||
<div class="flex gap-2">
|
||||
<h2>General</h2>
|
||||
@if ($server->id === 0)
|
||||
<x-new-modal buttonTitle="Save" title="Change Localhost" action="submit">
|
||||
<x-modal-confirmation buttonTitle="Save" title="Change Localhost" action="submit">
|
||||
You could lose a lot of functionalities if you change the server details of the server where Coolify
|
||||
is
|
||||
running on.<br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@else
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
@if ($server->isFunctional())
|
||||
|
@ -2,9 +2,11 @@
|
||||
<div class="flex items-start gap-2">
|
||||
<h1>Servers</h1>
|
||||
<a class="text-white hover:no-underline" href="{{ route('server.create') }}">
|
||||
<x-forms.button class="btn">+ Add</x-forms.button>
|
||||
<x-forms.button >+ Add</x-forms.button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="subtitle">All your projects.</div>
|
||||
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@forelse ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
|
@ -1,69 +1,70 @@
|
||||
<div>
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
<h2>Log Drains</h2>
|
||||
<div class="pb-4">Sends service logs to 3rd party tools.</div>
|
||||
<div class="flex flex-col gap-4 pt-4">
|
||||
<div class="p-4 border border-coolgray-500">
|
||||
<form wire:submit='submit("newrelic")' class="flex flex-col">
|
||||
<h3>New Relic</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("newrelic")'
|
||||
id="server.settings.is_logdrain_newrelic_enabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required
|
||||
id="server.settings.logdrain_newrelic_license_key" label="License Key" />
|
||||
<x-forms.input disabled required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
@else
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_newrelic_license_key"
|
||||
label="License Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
@endif
|
||||
@if ($server->isFunctional())
|
||||
<h2>Log Drains</h2>
|
||||
<div class="pb-4">Sends service logs to 3rd party tools.</div>
|
||||
<div class="flex flex-col gap-4 pt-4">
|
||||
<div class="p-4 border border-coolgray-500">
|
||||
<form wire:submit='submit("newrelic")' class="flex flex-col">
|
||||
<h3>New Relic</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("newrelic")'
|
||||
id="server.settings.is_logdrain_newrelic_enabled" label="Enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required
|
||||
id="server.settings.logdrain_newrelic_license_key" label="License Key" />
|
||||
<x-forms.input disabled required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
@else
|
||||
<x-forms.input type="password" required
|
||||
id="server.settings.logdrain_newrelic_license_key" label="License Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h3>Axiom</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("axiom")' id="server.settings.is_logdrain_axiom_enabled"
|
||||
label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submit("axiom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required id="server.settings.logdrain_axiom_api_key"
|
||||
label="API Key" />
|
||||
<x-forms.input disabled required id="server.settings.logdrain_axiom_dataset_name"
|
||||
label="Dataset Name" />
|
||||
@else
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_axiom_api_key"
|
||||
label="API Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_axiom_dataset_name"
|
||||
label="Dataset Name" />
|
||||
@endif
|
||||
<h3>Axiom</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("axiom")' id="server.settings.is_logdrain_axiom_enabled"
|
||||
label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submit("axiom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required
|
||||
id="server.settings.logdrain_axiom_api_key" label="API Key" />
|
||||
<x-forms.input disabled required id="server.settings.logdrain_axiom_dataset_name"
|
||||
label="Dataset Name" />
|
||||
@else
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_axiom_api_key"
|
||||
label="API Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_axiom_dataset_name"
|
||||
label="Dataset Name" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
{{-- <h3>Highlight.io</h3>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
{{-- <h3>Highlight.io</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("highlight")'
|
||||
id="server.settings.is_logdrain_highlight_enabled" label="Enabled" />
|
||||
@ -81,33 +82,36 @@
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form> --}}
|
||||
<h3>Custom FluentBit configuration</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("custom")' id="server.settings.is_logdrain_custom_enabled"
|
||||
label="Enabled" />
|
||||
<h3>Custom FluentBit configuration</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("custom")'
|
||||
id="server.settings.is_logdrain_custom_enabled" label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submit("custom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.textarea disabled rows="6" required
|
||||
id="server.settings.logdrain_custom_config" label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea disabled id="server.settings.logdrain_custom_config_parser"
|
||||
label="Custom Parser Configuration" />
|
||||
@else
|
||||
<x-forms.textarea rows="6" required id="server.settings.logdrain_custom_config"
|
||||
label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea id="server.settings.logdrain_custom_config_parser"
|
||||
label="Custom Parser Configuration" />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<form wire:submit='submit("custom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.textarea disabled rows="6" required id="server.settings.logdrain_custom_config"
|
||||
label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea disabled id="server.settings.logdrain_custom_config_parser"
|
||||
label="Custom Parser Configuration" />
|
||||
@else
|
||||
<x-forms.textarea rows="6" required id="server.settings.logdrain_custom_config"
|
||||
label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea id="server.settings.logdrain_custom_config_parser"
|
||||
label="Custom Parser Configuration" />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>Server is not validated. Validate first.</div>
|
||||
@endif
|
||||
</div>
|
||||
|
@ -2,8 +2,7 @@
|
||||
@if ($limit_reached)
|
||||
<x-limit-reached name="servers" />
|
||||
@else
|
||||
<h1>Create a new Server</h1>
|
||||
<div class="subtitle">Servers are the main blocks of your infrastructure.</div>
|
||||
<h1 class="title">New Server</h1>
|
||||
<form class="flex flex-col gap-2" wire:submit='submit'>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="name" label="Name" required />
|
||||
@ -29,8 +28,8 @@
|
||||
<x-forms.checkbox instantSave type="checkbox" id="is_build_server" label="Use it as a build server?" />
|
||||
</div>
|
||||
<div class="w-96">
|
||||
<h3 class="pt-6">Swarm Support</h3>
|
||||
<div> Swarm support is experimental. Read the docs <a class='text-white'
|
||||
<h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span></h3>
|
||||
<div class="pb-4">Read the docs <a class='text-white'
|
||||
href='https://coolify.io/docs/docker/swarm#deploy-with-persistent-storage'
|
||||
target='_blank'>here</a>.</div>
|
||||
@if ($is_swarm_worker || $is_build_server)
|
||||
|
@ -1,142 +1,165 @@
|
||||
<div>
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'managed' }" class="flex h-full">
|
||||
<div class="flex flex-col gap-4 xl:w-32">
|
||||
<a :class="activeTab === 'managed' && 'text-white'"
|
||||
@click.prevent="activeTab = 'managed'; window.location.hash = 'managed'" href="#">Managed</a>
|
||||
<a :class="activeTab === 'unmanaged' && 'text-white'"
|
||||
@click.prevent="activeTab = 'unmanaged'; window.location.hash = 'unmanaged'" href="#">Unmanaged</a>
|
||||
</div>
|
||||
<div class="w-full pl-8">
|
||||
<div x-cloak x-show="activeTab === 'managed'" class="h-full">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<h2>Resources</h2>
|
||||
<x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4 title">Here you can find all resources that are managed by Coolify.</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-coolgray-400">
|
||||
<thead>
|
||||
<tr class="text-neutral-500">
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Project
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Environment</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Type</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Status
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-coolgray-400">
|
||||
@forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource)
|
||||
<tr class="text-white bg-coolblack hover:bg-coolgray-100">
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource->project(), 'name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'environment.name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap"><a class=""
|
||||
href="{{ $resource->link() }}">{{ $resource->name }}
|
||||
<x-internal-link /></a>
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ str($resource->type())->headline() }}</td>
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">
|
||||
@if ($resource->type() === 'service')
|
||||
<x-status.services :service="$resource" :showRefreshButton="false" />
|
||||
@else
|
||||
<x-status.index :resource="$resource" :showRefreshButton="false" />
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if ($server->isFunctional())
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'managed' }" class="flex h-full">
|
||||
<div class="flex flex-col gap-4 xl:w-32">
|
||||
<a :class="activeTab === 'managed' && 'text-white'"
|
||||
@click.prevent="activeTab = 'managed'; window.location.hash = 'managed'" href="#">Managed</a>
|
||||
<a :class="activeTab === 'unmanaged' && 'text-white'"
|
||||
@click.prevent="activeTab = 'unmanaged'; window.location.hash = 'unmanaged'"
|
||||
href="#">Unmanaged</a>
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'unmanaged'" class="h-full">
|
||||
<div class="flex flex-col" x-init="$wire.loadUnmanagedContainers()">
|
||||
<div class="flex gap-2">
|
||||
<h2>Resources</h2>
|
||||
<x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4 title">Here you can find all other containers running on the server.</div>
|
||||
</div>
|
||||
@if ($unmanagedContainers->count() > 0)
|
||||
<div class="w-full pl-8">
|
||||
<div x-cloak x-show="activeTab === 'managed'" class="h-full">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<h2>Resources</h2>
|
||||
<x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
|
||||
</div>
|
||||
<div class="subtitle">Here you can find all resources that are managed by Coolify.</div>
|
||||
</div>
|
||||
@if ($server->definedResources()->count() > 0)
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-coolgray-400">
|
||||
<thead>
|
||||
<tr class="text-neutral-500">
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Image
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Status
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Action
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-coolgray-400">
|
||||
@forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource)
|
||||
<tr class="text-white bg-coolblack hover:bg-coolgray-100">
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'Names') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'Image') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'State') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
@if (data_get($resource, 'State') === 'running')
|
||||
<x-forms.button
|
||||
wire:click="restartUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Restart</x-forms.button>
|
||||
<x-forms.button isError
|
||||
wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
|
||||
@elseif (data_get($resource, 'State') === 'exited')
|
||||
<x-forms.button
|
||||
wire:click="startUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Start</x-forms.button>
|
||||
@elseif (data_get($resource, 'State') === 'restarting')
|
||||
<x-forms.button
|
||||
wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
|
||||
@endif
|
||||
</td>
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-coolgray-400">
|
||||
<thead>
|
||||
<tr class="text-neutral-500">
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Project
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Environment</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Name
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Type
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Status
|
||||
</th>
|
||||
</tr>
|
||||
@empty
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-coolgray-400">
|
||||
@forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource)
|
||||
<tr class="text-white bg-coolblack hover:bg-coolgray-100">
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource->project(), 'name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'environment.name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap"><a
|
||||
class=""
|
||||
href="{{ $resource->link() }}">{{ $resource->name }}
|
||||
<x-internal-link /></a>
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ str($resource->type())->headline() }}</td>
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">
|
||||
@if ($resource->type() === 'service')
|
||||
<x-status.services :service="$resource"
|
||||
:showRefreshButton="false" />
|
||||
@else
|
||||
<x-status.index :resource="$resource"
|
||||
:showRefreshButton="false" />
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>No resources found.</div>
|
||||
@endif
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'unmanaged'" class="h-full">
|
||||
<div class="flex flex-col" x-init="$wire.loadUnmanagedContainers()">
|
||||
<div class="flex gap-2">
|
||||
<h2>Resources</h2>
|
||||
<x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>
|
||||
</div>
|
||||
<div class="subtitle">Here you can find all other containers running on the server.</div>
|
||||
</div>
|
||||
@endif
|
||||
@if ($unmanagedContainers->count() > 0)
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-coolgray-400">
|
||||
<thead>
|
||||
<tr class="text-neutral-500">
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Name
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Image
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Status
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Action
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-coolgray-400">
|
||||
@forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource)
|
||||
<tr class="text-white bg-coolblack hover:bg-coolgray-100">
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'Names') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'Image') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'State') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
@if (data_get($resource, 'State') === 'running')
|
||||
<x-forms.button
|
||||
wire:click="restartUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Restart</x-forms.button>
|
||||
<x-forms.button isError
|
||||
wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
|
||||
@elseif (data_get($resource, 'State') === 'exited')
|
||||
<x-forms.button
|
||||
wire:click="startUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Start</x-forms.button>
|
||||
@elseif (data_get($resource, 'State') === 'restarting')
|
||||
<x-forms.button
|
||||
wire:click="stopUnmanaged('{{ data_get($resource, 'ID') }}')"
|
||||
wire:key="{{ data_get($resource, 'ID') }}">Stop</x-forms.button>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>No resources found.</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>Server is not validated. Validate first.</div>
|
||||
@endif
|
||||
</div>
|
||||
|
@ -11,7 +11,9 @@
|
||||
<div class="flex flex-col gap-2 pt-4">
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input id="settings.fqdn" label="Instance's Domain" placeholder="https://coolify.io" />
|
||||
<x-forms.input id="settings.custom_dns_servers" label="DNS Servers" helper="DNS servers for validation FQDNS againts. A comma separated list of DNS servers." placeholder="1.1.1.1,8.8.8.8" />
|
||||
<x-forms.input id="settings.custom_dns_servers" label="DNS Servers"
|
||||
helper="DNS servers for validation FQDNS againts. A comma separated list of DNS servers."
|
||||
placeholder="1.1.1.1,8.8.8.8" />
|
||||
<x-forms.checkbox instantSave id="is_dns_validation_enabled" label="Validate DNS settings?" />
|
||||
</div>
|
||||
|
||||
@ -22,12 +24,12 @@
|
||||
</div>
|
||||
</form>
|
||||
<h2 class="pt-6">Advanced</h2>
|
||||
<div class="flex flex-col py-6 text-right w-80">
|
||||
@if(!is_null(env('AUTOUPDATE', null)))
|
||||
<div class="text-right w-80">
|
||||
@if (!is_null(env('AUTOUPDATE', null)))
|
||||
<x-forms.checkbox instantSave helper="AUTOUPDATE is set in .env file, you need to modify it there." disabled
|
||||
id="is_auto_update_enabled" label="Auto Update Coolify" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Auto Update Coolify" />
|
||||
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Auto Update Coolify" />
|
||||
@endif
|
||||
<x-forms.checkbox instantSave id="is_registration_enabled" label="Registration Allowed" />
|
||||
<x-forms.checkbox instantSave id="do_not_track" label="Do Not Track" />
|
||||
|
@ -1,15 +1,4 @@
|
||||
<div>
|
||||
<dialog id="sendTestEmail" class="modal">
|
||||
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit='submit'>
|
||||
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
||||
<x-forms.button onclick="sendTestEmail.close()" wire:click="sendTestNotification">
|
||||
Send Email
|
||||
</x-forms.button>
|
||||
</form>
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Transactional Email</h2>
|
||||
</div>
|
||||
@ -22,13 +11,16 @@
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if (isEmailEnabled($settings) &&
|
||||
auth()->user()->isAdminFromSession() &&
|
||||
isTestEmailEnabled($settings))
|
||||
<x-forms.button onclick="sendTestEmail.showModal()"
|
||||
class="text-white normal-case btn btn-xs no-animation btn-primary">
|
||||
Send Test Email
|
||||
</x-forms.button>
|
||||
@if (isEmailEnabled($settings) && auth()->user()->isAdminFromSession() && isTestEmailEnabled($settings))
|
||||
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
||||
<form wire:submit='submit' class="flex flex-col gap-2">
|
||||
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
||||
<x-forms.button onclick="sendTestEmail.close()" wire:click="sendTestNotification"
|
||||
@click="modalOpen=false">
|
||||
Send Email
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</x-modal-input>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
@ -13,14 +13,14 @@
|
||||
</x-forms.button>
|
||||
</a>
|
||||
@endif
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This source will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subtitle">Your Private GitHub App for private repositories.</div>
|
||||
@if (!data_get($github_app, 'installation_id'))
|
||||
<div class="mb-10 rounded alert alert-warning">
|
||||
<div class="mb-10 rounded alert-error">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
@ -148,12 +148,12 @@
|
||||
<div class="flex items-center gap-2 pb-4">
|
||||
<h1>GitHub App</h1>
|
||||
<div class="flex gap-2">
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This source will be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-10 rounded alert alert-warning">
|
||||
<div class="mb-10 rounded alert-error">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
|
@ -14,7 +14,7 @@
|
||||
class="text-warning">{{ session('currentTeam.name') }}</span></span>
|
||||
</div>
|
||||
@if (request()->query->get('cancelled'))
|
||||
<div class="mb-6 rounded alert alert-error">
|
||||
<div class="mb-6 rounded alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
|
@ -1,14 +1,81 @@
|
||||
<div>
|
||||
<h1>Tags</h1>
|
||||
<div class="flex flex-col gap-2 pb-6 ">
|
||||
<div>Available tags: </div>
|
||||
<div class="subtitle">Tags help you to perform actions on multiple resources.</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@forelse ($tags as $oneTag)
|
||||
<a class="flex items-center justify-center h-6 px-2 text-white min-w-14 w-fit hover:no-underline hover:bg-coolgray-200 bg-coolgray-100"
|
||||
href="{{ route('tags.show', ['tag_name' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
||||
@empty
|
||||
@if ($tags->count() === 0)
|
||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||
@endforelse
|
||||
@else
|
||||
<x-forms.select wire:model.live="tag">
|
||||
<option value="null" disabled selected>Select a tag</option>
|
||||
@foreach ($tags as $oneTag)
|
||||
<option value="{{ $oneTag->name }}">{{ $oneTag->name }}</option>
|
||||
@endforeach
|
||||
</x-forms.select>
|
||||
@if ($tag)
|
||||
<div>
|
||||
<div class="flex items-end gap-2 ">
|
||||
<div class="w-[500px]">
|
||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||
</div>
|
||||
<x-modal-confirmation isHighlighted buttonTitle="Redeploy All" action="redeploy_all">
|
||||
All resources will be redeployed.
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
@foreach ($applications as $application)
|
||||
<a href="{{ $application->link() }}" class="flex flex-col box group">
|
||||
<span
|
||||
class="font-bold text-white">{{ $application->project()->name }}/{{ $application->environment->name }}</span>
|
||||
<span class="text-white ">{{ $application->name }}</span>
|
||||
<span class="description">{{ $application->description }}</span>
|
||||
</a>
|
||||
@endforeach
|
||||
@foreach ($services as $service)
|
||||
<a href="{{ $service->link() }}" class="flex flex-col box group">
|
||||
<span
|
||||
class="font-bold text-white">{{ $service->project()->name }}/{{ $service->environment->name }}</span>
|
||||
<span class="text-white ">{{ $service->name }}</span>
|
||||
<span class="description">{{ $service->description }}</span>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deployments_per_tag_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
</div>
|
||||
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_tag_per_server as $server_name => $deployments)
|
||||
<h4 class="py-4">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}"
|
||||
@class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'border-coolgray-500' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -5,11 +5,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 pb-6 ">
|
||||
<div>Available tags: </div>
|
||||
<div>Available tags</div>
|
||||
<div class="flex flex-wrap gap-2 ">
|
||||
@forelse ($tags as $oneTag)
|
||||
<a :class="{{ $tag->id == $oneTag->id }} && 'bg-coollabs hover:bg-coollabs-100'"
|
||||
class="flex items-center justify-center h-6 px-2 text-white min-w-14 w-fit hover:no-underline hover:bg-coolgray-200 bg-coolgray-100"
|
||||
class="w-64 box"
|
||||
href="{{ route('tags.show', ['tag_name' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
||||
@empty
|
||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||
@ -22,9 +22,9 @@ class="flex items-center justify-center h-6 px-2 text-white min-w-14 w-fit hover
|
||||
<div class="w-[500px]">
|
||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||
</div>
|
||||
<x-new-modal isHighlighted buttonTitle="Redeploy All" action="redeploy_all">
|
||||
<x-modal-confirmation isHighlighted buttonTitle="Redeploy All" action="redeploy_all">
|
||||
All resources will be redeployed.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
@foreach ($applications as $application)
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div>
|
||||
<h1>New Team</h1>
|
||||
<div class="subtitle">Add a new team</div>
|
||||
<div class="subtitle">Add a new team.</div>
|
||||
<form class="flex flex-col gap-2" wire:submit='submit'>
|
||||
<x-forms.input autofocus id="name" label="Name" required />
|
||||
<x-forms.input id="description" label="Description" />
|
||||
|
@ -28,9 +28,9 @@
|
||||
@else
|
||||
@if (currentTeam()->isEmpty())
|
||||
<div class="pb-4">This will delete your team. Beware! There is no coming back!</div>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This team be deleted. It is not reversible. <br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
@else
|
||||
<div>
|
||||
<div class="pb-4">You need to delete the following resources to be able to delete the team:</div>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($member, 'pivot.role') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
<td class="flex gap-2 px-5 py-4 text-sm whitespace-nowrap">
|
||||
@if (auth()->user()->isAdminFromSession())
|
||||
@if ($member->id !== auth()->user()->id)
|
||||
@if (auth()->user()->isOwner())
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div>
|
||||
<h1>Create a new S3 Storage</h1>
|
||||
<div class="subtitle">S3 Storage used to save backups / files</div>
|
||||
<h1>New S3 Storage</h1>
|
||||
<div class="subtitle">S3 Storage used to save backups / files.</div>
|
||||
<form class="flex flex-col gap-2" wire:submit='submit'>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Name" id="name" />
|
||||
|
@ -16,9 +16,9 @@
|
||||
<x-forms.button wire:click="test_s3_connection">
|
||||
Validate Connection
|
||||
</x-forms.button>
|
||||
<x-new-modal isErrorButton buttonTitle="Delete">
|
||||
<x-modal-confirmation isErrorButton buttonTitle="Delete">
|
||||
This storage will be deleted. It is not reversible. Your data won't be touched!<br>Please think again.
|
||||
</x-new-modal>
|
||||
</x-modal-confirmation>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Name" id="storage.name" />
|
||||
|
@ -4,7 +4,7 @@
|
||||
->currentTeam()" />
|
||||
<div class="flex items-start gap-2">
|
||||
<h2 class="pb-4">S3 Storages</h2>
|
||||
<a class="text-white hover:no-underline" href="/team/storages/new"> <x-forms.button class="btn">+ Add
|
||||
<a class="text-white hover:no-underline" href="/team/storages/new"> <x-forms.button >+ Add
|
||||
</x-forms.button></a>
|
||||
</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
|
@ -2,10 +2,10 @@
|
||||
<div class="flex items-start gap-2">
|
||||
<h1>Sources</h1>
|
||||
<a class="text-white hover:no-underline" href="{{ route('source.new') }}">
|
||||
<x-forms.button class="btn">+ Add</x-forms.button>
|
||||
<x-forms.button >+ Add</x-forms.button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="subtitle ">All Sources</div>
|
||||
<div class="subtitle ">All Sources.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@forelse ($sources as $source)
|
||||
@if ($source->getMorphClass() === 'App\Models\GithubApp')
|
||||
|
@ -1,52 +1,40 @@
|
||||
<div>
|
||||
@isset($jsPath)
|
||||
<script>{!! file_get_contents($jsPath) !!}</script>
|
||||
<script>
|
||||
{!! file_get_contents($jsPath) !!}
|
||||
</script>
|
||||
@endisset
|
||||
@isset($cssPath)
|
||||
<style>{!! file_get_contents($cssPath) !!}</style>
|
||||
<style>
|
||||
{!! file_get_contents($cssPath) !!}
|
||||
</style>
|
||||
@endisset
|
||||
|
||||
<div
|
||||
x-data="LivewireUIModal()"
|
||||
x-on:close.stop="setShowPropertyTo(false)"
|
||||
x-on:keydown.escape.window="closeModalOnEscape()"
|
||||
x-show="show"
|
||||
class="fixed inset-0 z-10 overflow-y-auto"
|
||||
style="display: none;"
|
||||
>
|
||||
<div x-data="LivewireUIModal()" x-on:close.stop="setShowPropertyTo(false)"
|
||||
x-on:keydown.escape.window="closeModalOnEscape()" x-show="show" class="fixed inset-0 overflow-y-auto z-[60]"
|
||||
style="display: none;">
|
||||
<div class="flex items-end justify-center min-h-screen px-4 pt-4 pb-10 text-center sm:block sm:p-0">
|
||||
<div
|
||||
x-show="show"
|
||||
x-on:click="closeModalOnClickAway()"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="fixed inset-0 transition-all transform"
|
||||
>
|
||||
<div x-show="show" x-on:click="closeModalOnClickAway()" x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0" class="fixed inset-0 transition-all transform">
|
||||
<div class="absolute inset-0 bg-black opacity-70"></div>
|
||||
</div>
|
||||
|
||||
{{-- <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span> --}}
|
||||
|
||||
<div
|
||||
x-show="show && showActiveComponent"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-bind:class="modalWidth"
|
||||
class="w-full overflow-hidden text-left align-bottom transition-all transform sm:align-middle sm:w-full"
|
||||
id="modal-container"
|
||||
x-trap.noscroll.inert="show && showActiveComponent"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div x-show="show && showActiveComponent" x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-bind:class="modalWidth"
|
||||
class="w-full overflow-hidden text-left align-bottom transition-all transform sm:align-middle sm:w-full"
|
||||
id="modal-container" x-trap.noscroll.inert="show && showActiveComponent" aria-modal="true">
|
||||
@forelse($components as $id => $component)
|
||||
<div class="sm:mx-20 sm:my-8" x-show.immediate="activeComponent == '{{ $id }}'" x-ref="{{ $id }}" wire:key="{{ $id }}">
|
||||
<div class="sm:mx-20 sm:my-8" x-show.immediate="activeComponent == '{{ $id }}'"
|
||||
x-ref="{{ $id }}" wire:key="{{ $id }}">
|
||||
@livewire($component['name'], $component['arguments'], key($id))
|
||||
</div>
|
||||
@empty
|
||||
|
@ -30,11 +30,6 @@ module.exports = {
|
||||
colors
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
scrollbar: ["dark"],
|
||||
extend: {},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
require("tailwindcss-scrollbar"),
|
||||
require("@tailwindcss/typography"),
|
||||
|
Loading…
Reference in New Issue
Block a user