ui ui ui ui

This commit is contained in:
Andras Bacsai
2024-03-25 11:33:38 +01:00
parent a66090b594
commit 9ad6ce5851
41 changed files with 203 additions and 289 deletions

View File

@@ -36,6 +36,30 @@ class Configuration extends Component
$this->applications = $this->service->applications->sort(); $this->applications = $this->service->applications->sort();
$this->databases = $this->service->databases->sort(); $this->databases = $this->service->databases->sort();
} }
public function restartApplication($id)
{
try {
$application = $this->service->applications->find($id);
if ($application) {
$application->restart();
$this->dispatch('success', 'Application restarted successfully.');
}
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function restartDatabase($id)
{
try {
$database = $this->service->databases->find($id);
if ($database) {
$database->restart();
$this->dispatch('success', 'Database restarted successfully.');
}
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function check_status() public function check_status()
{ {
try { try {

View File

@@ -19,6 +19,11 @@ class ServiceApplication extends BaseModel
$service->fileStorages()->delete(); $service->fileStorages()->delete();
}); });
} }
public function restart()
{
$container_id = $this->name . '-' . $this->service->uuid;
instant_remote_process(["docker restart {$container_id}"], $this->service->server);
}
public function isLogDrainEnabled() public function isLogDrainEnabled()
{ {
return data_get($this, 'is_log_drain_enabled', false); return data_get($this, 'is_log_drain_enabled', false);

View File

@@ -17,6 +17,11 @@ class ServiceDatabase extends BaseModel
$service->fileStorages()->delete(); $service->fileStorages()->delete();
}); });
} }
public function restart()
{
$container_id = $this->name . '-' . $this->service->uuid;
remote_process(["docker restart {$container_id}"], $this->service->server);
}
public function isLogDrainEnabled() public function isLogDrainEnabled()
{ {
return data_get($this, 'is_log_drain_enabled', false); return data_get($this, 'is_log_drain_enabled', false);

View File

@@ -41,7 +41,7 @@ option {
} }
.button { .button {
@apply flex items-center justify-center gap-2 px-3 py-1 text-sm font-normal normal-case rounded cursor-pointer bg-neutral-200 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:bg-coolgray-100 dark:hover:dark:text-white dark:disabled:bg-coolgray-100/40 dark:disabled:text-neutral-800 min-w-fit hover:dark:text-white focus-visible:outline-none; @apply flex items-center justify-center gap-2 px-3 py-1 text-sm font-normal normal-case rounded cursor-pointer bg-neutral-200 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:bg-coolgray-100 dark:hover:dark:text-white dark:disabled:bg-coolgray-100/40 dark:disabled:text-neutral-800 disabled:bg-neutral-100 disabled:text-neutral-200 disabled:cursor-not-allowed min-w-fit hover:dark:text-white focus:outline-1 ;
} }
button[isError]:not(:disabled) { button[isError]:not(:disabled) {
@@ -195,7 +195,7 @@ tr td:first-child {
} }
.box-without-bg { .box-without-bg {
@apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem] dark:border-black border-neutral-200; @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem];
} }
.box-title { .box-title {

View File

@@ -1,4 +1,4 @@
<div class="group"> <div {{ $attributes->merge(['class' => "group"]) }}>
<div class="info-helper"> <div class="info-helper">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="w-4 h-4 stroke-current"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="w-4 h-4 stroke-current">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"

View File

@@ -16,11 +16,11 @@
@else @else
@if ($disabled) @if ($disabled)
@if ($buttonFullWidth) @if ($buttonFullWidth)
<x-forms.button class="w-full" isError disabled> <x-forms.button class="w-full" isError disabled wire:target>
{{ $buttonTitle }} {{ $buttonTitle }}
</x-forms.button> </x-forms.button>
@else @else
<x-forms.button isError disabled> <x-forms.button isError disabled wire:target>
{{ $buttonTitle }} {{ $buttonTitle }}
</x-forms.button> </x-forms.button>
@endif @endif
@@ -36,11 +36,11 @@
@endif @endif
@else @else
@if ($buttonFullWidth) @if ($buttonFullWidth)
<x-forms.button @click="modalOpen=true" class="flex w-full gap-2"> <x-forms.button @click="modalOpen=true" class="flex w-full gap-2" wire:target>
{{ $buttonTitle }} {{ $buttonTitle }}
</x-forms.button> </x-forms.button>
@else @else
<x-forms.button @click="modalOpen=true" class="flex gap-2"> <x-forms.button @click="modalOpen=true" class="flex gap-2" wire:target>
{{ $buttonTitle }} {{ $buttonTitle }}
</x-forms.button> </x-forms.button>
@endif @endif

View File

@@ -57,18 +57,7 @@
Servers Servers
</a> </a>
</li> </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> <li>
<a title="Sources" <a title="Sources"
class="{{ request()->is('source*') ? 'menu-item-active menu-item' : 'menu-item' }}" class="{{ request()->is('source*') ? 'menu-item-active menu-item' : 'menu-item' }}"
@@ -105,6 +94,18 @@
Notifications Notifications
</a> </a>
</li> </li>
<li>
<a title="Keys & Tokens"
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>
Keys & Tokens
</a>
</li>
<li> <li>
<a title="Tags" <a title="Tags"
class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}" class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}"

View File

@@ -8,7 +8,7 @@
<div x-show="slideOverOpen" @if (!$closeWithX) @keydown.window.escape="slideOverOpen=false" @endif <div x-show="slideOverOpen" @if (!$closeWithX) @keydown.window.escape="slideOverOpen=false" @endif
class="relative z-[99] "> class="relative z-[99] ">
<div x-show="slideOverOpen" @if (!$closeWithX) @click="slideOverOpen = false" @endif <div x-show="slideOverOpen" @if (!$closeWithX) @click="slideOverOpen = false" @endif
class="fixed inset-0 dark:bg-black bg-opacity-60"></div> class="fixed inset-0 dark:bg-black/60 backdrop-blur-sm"></div>
<div class="fixed inset-0 overflow-hidden"> <div class="fixed inset-0 overflow-hidden">
<div class="absolute inset-0 overflow-hidden "> <div class="absolute inset-0 overflow-hidden ">
<div class="fixed inset-y-0 right-0 flex max-w-full pl-10"> <div class="fixed inset-y-0 right-0 flex max-w-full pl-10">

View File

@@ -20,7 +20,6 @@
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2"> <div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
@foreach ($projects as $project) @foreach ($projects as $project)
<div class="gap-2 border border-transparent cursor-pointer box group"> <div class="gap-2 border border-transparent cursor-pointer box group">
@if (data_get($project, 'environments')->count() === 1) @if (data_get($project, 'environments')->count() === 1)
<a class="flex flex-col flex-1 mx-6 hover:no-underline" <a class="flex flex-col flex-1 mx-6 hover:no-underline"
href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}"> href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">

View File

@@ -1,4 +1,4 @@
<div> <div class="w-full ">
<div class="subtitle">Destinations are used to segregate resources by network.</div> <div class="subtitle">Destinations are used to segregate resources by network.</div>
<form class="flex flex-col gap-4" wire:submit='submit'> <form class="flex flex-col gap-4" wire:submit='submit'>
<div class="flex gap-2"> <div class="flex gap-2">

View File

@@ -2,15 +2,9 @@
@if ($server->isFunctional()) @if ($server->isFunctional())
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<h2>Destinations</h2> <h2>Destinations</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Destination">
<x-slot:title>New Destination</x-slot:title>
<x-slot:content>
<livewire:destination.new.docker :server_id="$server->id" /> <livewire:destination.new.docker :server_id="$server->id" />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
<x-forms.button wire:click='scan'>Scan Destinations</x-forms.button> <x-forms.button wire:click='scan'>Scan Destinations</x-forms.button>
</div> </div>
<div class="pt-2 pb-6 ">Destinations are used to segregate resources by network.</div> <div class="pt-2 pb-6 ">Destinations are used to segregate resources by network.</div>

View File

@@ -1,5 +1,5 @@
<form class="flex flex-col gap-2 rounded" wire:submit='submit'> <form class="flex flex-col w-full gap-2 rounded" wire:submit='submit'>
<x-forms.input placeholder="production" id="name" label="Name" required /> <x-forms.input autofocus placeholder="production" id="name" label="Name" required />
<x-forms.button type="submit" @click="slideOverOpen=false"> <x-forms.button type="submit" @click="slideOverOpen=false">
Save Save
</x-forms.button> </x-forms.button>

View File

@@ -1,16 +1,6 @@
<div> <div>
<h1>Backups</h1> <h1>Backups</h1>
<livewire:project.database.heading :database="$database" /> <livewire:project.database.heading :database="$database" />
<x-modal modalId="startDatabase">
<x-slot:modalBody>
<livewire:activity-monitor header="Database Startup Logs" />
</x-slot:modalBody>
<x-slot:modalSubmit>
<x-forms.button onclick="startDatabase.close()" type="submit">
Close
</x-forms.button>
</x-slot:modalSubmit>
</x-modal>
<div class="pt-6"> <div class="pt-6">
<livewire:project.database.backup-edit :backup="$backup" :s3s="$s3s" :status="data_get($database, 'status')" /> <livewire:project.database.backup-edit :backup="$backup" :s3s="$s3s" :status="data_get($database, 'status')" />
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">

View File

@@ -1,28 +1,12 @@
<div> <div>
<h1>Backups</h1> <h1>Backups</h1>
<livewire:project.database.heading :database="$database" /> <livewire:project.database.heading :database="$database" />
<x-modal modalId="startDatabase">
<x-slot:modalBody>
<livewire:activity-monitor header="Database Startup Logs" />
</x-slot:modalBody>
<x-slot:modalSubmit>
<x-forms.button onclick="startDatabase.close()" type="submit">
Close
</x-forms.button>
</x-slot:modalSubmit>
</x-modal>
<div class="pt-6"> <div class="pt-6">
<div class="flex gap-2 "> <div class="flex gap-2 ">
<h2 class="pb-4">Scheduled Backups</h2> <h2 class="pb-4">Scheduled Backups</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
<x-slot:title>New Scheduled Backup</x-slot:title>
<x-slot:content>
<livewire:project.database.create-scheduled-backup :database="$database" :s3s="$s3s" /> <livewire:project.database.create-scheduled-backup :database="$database" :s3s="$s3s" />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<livewire:project.database.scheduled-backups :database="$database" /> <livewire:project.database.scheduled-backups :database="$database" />
</div> </div>

View File

@@ -1,16 +1,6 @@
<div> <div>
<h1>Configuration</h1> <h1>Configuration</h1>
<livewire:project.database.heading :database="$database" /> <livewire:project.database.heading :database="$database" />
<x-modal modalId="startDatabase" noSubmit>
<x-slot:modalBody>
<livewire:activity-monitor header="Database Startup Logs" />
</x-slot:modalBody>
<x-slot:modalSubmit>
<x-forms.button onclick="startDatabase.close()" type="submit">
Close
</x-forms.button>
</x-slot:modalSubmit>
</x-modal>
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex h-full pt-6"> <div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex h-full pt-6">
<div class="flex flex-col gap-4 min-w-fit"> <div class="flex flex-col gap-4 min-w-fit">
<a :class="activeTab === 'general' && 'dark:text-white'" <a :class="activeTab === 'general' && 'dark:text-white'"

View File

@@ -1,5 +1,5 @@
<form class="flex flex-col gap-2 rounded" wire:submit='submit'> <form class="flex flex-col w-full gap-2 rounded" wire:submit='submit'>
<x-forms.input placeholder="0 0 * * * or daily" id="frequency" label="Frequency" required /> <x-forms.input autofocus placeholder="0 0 * * * or daily" id="frequency" label="Frequency" required />
<x-forms.checkbox id="save_s3" label="Save to S3" /> <x-forms.checkbox id="save_s3" label="Save to S3" />
<x-forms.select id="selected_storage_id"> <x-forms.select id="selected_storage_id">
@if ($s3s->count() === 0) @if ($s3s->count() === 0)

View File

@@ -3,7 +3,7 @@
<x-slide-over @startdatabase.window="slideOverOpen = true" closeWithX fullScreen> <x-slide-over @startdatabase.window="slideOverOpen = true" closeWithX fullScreen>
<x-slot:title>Database Startup Logs</x-slot:title> <x-slot:title>Database Startup Logs</x-slot:title>
<x-slot:content> <x-slot:content>
<livewire:activity-monitor showWaiting /> <livewire:activity-monitor header="Logs" showWaiting />
</x-slot:content> </x-slot:content>
</x-slide-over> </x-slide-over>
<div class="navbar-main"> <div class="navbar-main">

View File

@@ -82,21 +82,17 @@
<div class="pb-16"> <div class="pb-16">
<div class="flex gap-2 pt-4 pb-2"> <div class="flex gap-2 pt-4 pb-2">
<h3>Initialization scripts</h3> <h3>Initialization scripts</h3>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Init Script">
<x-slot:title>New Init Script</x-slot:title> <form class="flex flex-col w-full gap-2 rounded" wire:submit='save_new_init_script'>
<x-slot:content> <x-forms.input autofocus placeholder="create_test_db.sql" id="new_filename" label="Filename"
<form class="flex flex-col gap-2 rounded modal-box" wire:submit='save_new_init_script'>
<x-forms.input placeholder="create_test_db.sql" id="new_filename" label="Filename" required />
<x-forms.textarea placeholder="CREATE DATABASE test;" id="new_content" label="Content"
required /> required />
<x-forms.textarea rows="20" placeholder="CREATE DATABASE test;" id="new_content"
label="Content" required />
<x-forms.button type="submit"> <x-forms.button type="submit">
Save Save
</x-forms.button> </x-forms.button>
</form> </form>
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@forelse(data_get($database,'init_scripts', []) as $script) @forelse(data_get($database,'init_scripts', []) as $script)

View File

@@ -2,12 +2,14 @@
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
@forelse($database->scheduledBackups as $backup) @forelse($database->scheduledBackups as $backup)
@if ($type == 'database') @if ($type == 'database')
<a class="flex flex-col box" <div class="box">
<a class="flex flex-col"
href="{{ route('project.database.backup.execution', [...$parameters, 'backup_uuid' => $backup->uuid]) }}"> href="{{ route('project.database.backup.execution', [...$parameters, 'backup_uuid' => $backup->uuid]) }}">
<div>Frequency: {{ $backup->frequency }}</div> <div>Frequency: {{ $backup->frequency }}</div>
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div> <div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
<div>Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}</div> <div>Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}</div>
</a> </a>
</div>
@else @else
<div @class([ <div @class([
'border-coollabs' => 'border-coollabs' =>
@@ -25,8 +27,8 @@
</div> </div>
@if ($type === 'service-database' && $selectedBackup) @if ($type === 'service-database' && $selectedBackup)
<div class="pt-10"> <div class="pt-10">
<livewire:project.database.backup-edit wire:key="{{ $selectedBackup->id }}" :backup="$selectedBackup" :s3s="$s3s" <livewire:project.database.backup-edit wire:key="{{ $selectedBackup->id }}" :backup="$selectedBackup"
:status="data_get($database, 'status')" /> :s3s="$s3s" :status="data_get($database, 'status')" />
<h3 class="py-4">Executions</h3> <h3 class="py-4">Executions</h3>
<livewire:project.database.backup-executions wire:keykey="{{ $selectedBackup->id }}" :backup="$selectedBackup" <livewire:project.database.backup-executions wire:keykey="{{ $selectedBackup->id }}" :backup="$selectedBackup"
:executions="$selectedBackup->executions" /> :executions="$selectedBackup->executions" />

View File

@@ -16,18 +16,15 @@
</form> </form>
<div class="flex gap-2"> <div class="flex gap-2">
<h2>Shared Variables</h2> <h2>Shared Variables</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Shared Variable">
<x-slot:title>New Shared Variable</x-slot:title>
<x-slot:content>
<livewire:project.shared.environment-variable.add /> <livewire:project.shared.environment-variable.add />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class="flex items-center gap-2 pb-4">You can use these variables anywhere with <span <div class="pb-4 lg:flex lg:gap-1">
class="dark:text-warning text-coollabs">@{{ project.VARIABLENAME }}</span><x-helper <div>You can use these variables anywhere with</div>
helper="More info <a class='dark:text-white underline' href='https://coolify.io/docs/environment-variables#shared-variables' target='_blank'>here</a>."></x-helper> <div class=" dark:text-warning text-coollabs">@{{ project.VARIABLENAME }} </div>
<x-helper
helper="More info <a class='underline dark:text-white' href='https://coolify.io/docs/environment-variables#shared-variables' target='_blank'>here</a>."></x-helper>
</div> </div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@forelse ($project->environment_variables->sort()->sortBy('real_value') as $env) @forelse ($project->environment_variables->sort()->sortBy('real_value') as $env)

View File

@@ -44,18 +44,12 @@
</form> </form>
<div class="flex gap-2 pt-10"> <div class="flex gap-2 pt-10">
<h2>Shared Variables</h2> <h2>Shared Variables</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Shared Variable">
<x-slot:title>New Shared Variable</x-slot:title>
<x-slot:content>
<livewire:project.shared.environment-variable.add /> <livewire:project.shared.environment-variable.add />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true"
class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class="flex items-center gap-2 pb-4">You can use these variables anywhere with <span class="dark:text-warning">@{{environment.VARIABLENAME}}</span><x-helper <div class="flex items-center gap-2 pb-4">You can use these variables anywhere with <span class="dark:text-warning">@{{environment.VARIABLENAME}}</span><x-helper
helper="More info <a class='dark:text-white underline' href='https://coolify.io/docs/environment-variables#shared-variables' target='_blank'>here</a>."></x-helper> helper="More info <a class='underline dark:text-white' href='https://coolify.io/docs/environment-variables#shared-variables' target='_blank'>here</a>."></x-helper>
</div> </div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@forelse ($environment->environment_variables->sort()->sortBy('real_value') as $env) @forelse ($environment->environment_variables->sort()->sortBy('real_value') as $env)

View File

@@ -17,7 +17,7 @@
{{ $project->description }}</div> {{ $project->description }}</div>
</a> </a>
<div class="flex items-center"> <div class="flex items-center">
<a class="mx-4 font-bold hover:underline dark:hover:no-underline" <a class="mx-4 font-bold hover:underline"
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}"> href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}">
Settings Settings
</a> </a>

View File

@@ -75,17 +75,14 @@
<div class="text-xs">{{ $application->status }}</div> <div class="text-xs">{{ $application->status }}</div>
</div> </div>
<div class="flex items-center px-4"> <div class="flex items-center px-4">
<a class="flex flex-col flex-1 group-hover:dark:text-white hover:no-underline" <a class="mx-4 font-bold hover:underline"
href="{{ route('project.service.index', [...$parameters, 'stack_service_uuid' => $application->uuid]) }}"> href="{{ route('project.service.index', [...$parameters, 'stack_service_uuid' => $application->uuid]) }}">
<svg xmlns="http://www.w3.org/2000/svg" class="icon hover:dark:text-warning" Settings
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg>
</a> </a>
<x-modal-confirmation action="restartApplication({{ $application->id }})"
isErrorButton buttonTitle="Restart">
This application will be unavailable during the restart. <br>Please think again.
</x-modal-confirmation>
</div> </div>
</div> </div>
</div> </div>
@@ -100,8 +97,6 @@
$database->status)->contains(['restarting']), $database->status)->contains(['restarting']),
'flex gap-2 box-without-bg bg-coolgray-100 hover:text-neutral-300 group', 'flex gap-2 box-without-bg bg-coolgray-100 hover:text-neutral-300 group',
])> ])>
<div class="flex flex-row w-full"> <div class="flex flex-row w-full">
<div class="flex flex-col flex-1"> <div class="flex flex-col flex-1">
<div class="pb-2"> <div class="pb-2">
@@ -121,17 +116,15 @@
<div class="text-xs">{{ $database->status }}</div> <div class="text-xs">{{ $database->status }}</div>
</div> </div>
<div class="flex items-center px-4"> <div class="flex items-center px-4">
<a class="flex flex-col flex-1 group-hover:dark:text-white hover:no-underline" <a class="mx-4 font-bold hover:underline"
href="{{ route('project.service.index', [...$parameters, 'stack_service_uuid' => $database->uuid]) }}"> href="{{ route('project.service.index', [...$parameters, 'stack_service_uuid' => $database->uuid]) }}">
<svg xmlns="http://www.w3.org/2000/svg" class="icon hover:dark:text-warning" Settings
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg>
</a> </a>
<x-modal-confirmation action="restartDatabase({{ $database->id }})"
isErrorButton buttonTitle="Restart">
This database will be unavailable during the restart. <br>Please think again.
</x-modal-confirmation>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -55,14 +55,9 @@
<div x-cloak x-show="activeTab === 'backups'"> <div x-cloak x-show="activeTab === 'backups'">
<div class="flex gap-2 "> <div class="flex gap-2 ">
<h2 class="pb-4">Scheduled Backups</h2> <h2 class="pb-4">Scheduled Backups</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
<x-slot:title>New Scheduled Backup</x-slot:title>
<x-slot:content>
<livewire:project.database.create-scheduled-backup :database="$serviceDatabase" :s3s="$s3s" /> <livewire:project.database.create-scheduled-backup :database="$serviceDatabase" :s3s="$s3s" />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<livewire:project.database.scheduled-backups :database="$serviceDatabase" /> <livewire:project.database.scheduled-backups :database="$serviceDatabase" />
</div> </div>

View File

@@ -3,13 +3,9 @@
<div class="flex gap-2"> <div class="flex gap-2">
<h2>Service Stack</h2> <h2>Service Stack</h2>
<x-forms.button type="submit">Save</x-forms.button> <x-forms.button type="submit">Save</x-forms.button>
<x-slide-over closeWithX fullScreen> <x-modal-input buttonTitle="Edit Compose File" title="Docker Compose">
<x-slot:title>Docker Compose</x-slot:title>
<x-slot:content>
<livewire:project.service.edit-compose serviceId="{{ $service->id }}" /> <livewire:project.service.edit-compose serviceId="{{ $service->id }}" />
</x-slot:content> </x-modal-input>
<button @click.prevent="slideOverOpen=true" class="button">Edit Compose File</button>
</x-slide-over>
</div> </div>
<div>Configuration</div> <div>Configuration</div>
</div> </div>
@@ -19,7 +15,7 @@
</div> </div>
<div class="w-96"> <div class="w-96">
<x-forms.checkbox instantSave id="service.connect_to_docker_network" label="Connect To Predefined Network" <x-forms.checkbox instantSave id="service.connect_to_docker_network" label="Connect To Predefined Network"
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='dark:text-white underline' target='_blank' href='https://coolify.io/docs/docker/compose#connect-to-predefined-networks'>this</a>." /> helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='underline dark:text-white' target='_blank' href='https://coolify.io/docs/docker/compose#connect-to-predefined-networks'>this</a>." />
</div> </div>
@if ($fields) @if ($fields)
<div> <div>

View File

@@ -11,13 +11,9 @@
helper="For Preview Deployments, storage has a <span class='text-helper'>-pr-#PRNumber</span> in their helper="For Preview Deployments, storage has a <span class='text-helper'>-pr-#PRNumber</span> in their
volume volume
name, example: <span class='text-helper'>-pr-1</span>" /> name, example: <span class='text-helper'>-pr-1</span>" />
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Persistent Storage">
<x-slot:title>New Persistent Storage</x-slot:title>
<x-slot:content>
<livewire:project.shared.storages.add :uuid="$resource->uuid" /> <livewire:project.shared.storages.add :uuid="$resource->uuid" />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+ Add</button>
</x-slide-over>
</div> </div>
<div class="pb-4">Persistent storage to preserve data between deployments.</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)

View File

@@ -1,5 +1,5 @@
<form class="flex flex-col gap-2 rounded" wire:submit='submit'> <form class="flex flex-col w-full gap-2 rounded" wire:submit='submit'>
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required /> <x-forms.input autofocus placeholder="NODE_ENV" id="key" label="Name" required />
<x-forms.textarea x-show="$wire.is_multiline === true" x-cloak id="value" label="Value" required /> <x-forms.textarea x-show="$wire.is_multiline === true" x-cloak id="value" label="Value" required />
<x-forms.input x-show="$wire.is_multiline === false" x-cloak placeholder="production" id="value" <x-forms.input x-show="$wire.is_multiline === false" x-cloak placeholder="production" id="value"
x-bind:label="$wire.is_multiline === false && 'Value'" required /> x-bind:label="$wire.is_multiline === false && 'Value'" required />

View File

@@ -3,13 +3,9 @@
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h2>Environment Variables</h2> <h2>Environment Variables</h2>
@if ($resource->type() !== 'service') @if ($resource->type() !== 'service')
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Environment Variable">
<x-slot:title>New Environment Variable</x-slot:title>
<x-slot:content>
<livewire:project.shared.environment-variable.add /> <livewire:project.shared.environment-variable.add />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+ Add</button>
</x-slide-over>
@endif @endif
<x-forms.button <x-forms.button
wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button> wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>

View File

@@ -1,5 +1,5 @@
<form class="flex flex-col gap-2 rounded" wire:submit='submit'> <form class="flex flex-col w-full gap-2 rounded" wire:submit='submit'>
<x-forms.input placeholder="Run cron" id="name" label="Name" /> <x-forms.input autofocus placeholder="Run cron" id="name" label="Name" />
<x-forms.input placeholder="php artisan schedule:run" id="command" label="Command" /> <x-forms.input placeholder="php artisan schedule:run" id="command" label="Command" />
<x-forms.input placeholder="0 0 * * * or daily" id="frequency" label="Frequency" /> <x-forms.input placeholder="0 0 * * * or daily" id="frequency" label="Frequency" />
<x-forms.input placeholder="php" id="container" <x-forms.input placeholder="php" id="container"

View File

@@ -1,23 +1,18 @@
<div> <div>
<div class="flex gap-2"> <div class="flex gap-2">
<h2>Scheduled Tasks</h2> <h2>Scheduled Tasks</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Scheduled Task">
<x-slot:title>New Scheduled Task</x-slot:title>
<x-slot:content>
<livewire:project.shared.scheduled-task.add /> <livewire:project.shared.scheduled-task.add />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+ Add</button>
</x-slide-over>
</div> </div>
<div class="flex flex-wrap gap-2 pt-4"> <div class="flex flex-wrap gap-2 pt-4">
@forelse($resource->scheduled_tasks as $task) @forelse($resource->scheduled_tasks as $task)
<a class="flex flex-col box" <a class="flex flex-col box"
@if ($resource->type() == 'application') @if ($resource->type() == 'application') href="{{ route('project.application.scheduled-tasks', [...$parameters, 'task_uuid' => $task->uuid]) }}">
href="{{ route('project.application.scheduled-tasks', [...$parameters, 'task_uuid' => $task->uuid]) }}">
@elseif ($resource->type() == 'service') @elseif ($resource->type() == 'service')
href="{{ route('project.service.scheduled-tasks', [...$parameters, 'task_uuid' => $task->uuid]) }}"> href="{{ route('project.service.scheduled-tasks', [...$parameters, 'task_uuid' => $task->uuid]) }}"> @endif
@endif <div><span class="font-bold dark:text-warning">{{ $task->name }}<span>
<div><span class="font-bold dark:text-warning">{{ $task->name }}<span></div> </div>
<div>Frequency: {{ $task->frequency }}</div> <div>Frequency: {{ $task->frequency }}</div>
<div>Last run: {{ data_get($task->latest_log, 'status', 'No runs yet') }}</div> <div>Last run: {{ data_get($task->latest_log, 'status', 'No runs yet') }}</div>
</a> </a>

View File

@@ -1,4 +1,4 @@
<form class="flex flex-col gap-2 rounded" wire:submit='submit'> <form class="flex flex-col w-full gap-2 rounded" wire:submit='submit'>
@if ($isSwarm) @if ($isSwarm)
<h5>Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you would <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> like to use a persistent volumes.</h5>

View File

@@ -1,14 +1,9 @@
<div> <div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h1>Environments</h1> <h1>Environments</h1>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Environment">
<x-slot:title>New Environment</x-slot:title>
<x-slot:content>
<livewire:project.add-environment :project="$project" /> <livewire:project.add-environment :project="$project" />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
<livewire:project.delete-project :disabled="$project->resource_count() > 0" :project_id="$project->id" /> <livewire:project.delete-project :disabled="$project->resource_count() > 0" :project_id="$project->id" />
</div> </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>
@@ -23,7 +18,7 @@
{{ $environment->description }}</div> {{ $environment->description }}</div>
</a> </a>
<div class="flex items-center"> <div class="flex items-center">
<a class="mx-4 font-bold hover:underline dark:hover:no-underline" <a class="mx-4 font-bold hover:underline"
href="{{ route('project.environment.edit', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => $environment->name]) }}"> href="{{ route('project.environment.edit', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => $environment->name]) }}">
Settings Settings
</a> </a>

View File

@@ -1,15 +1,10 @@
<div class="flex gap-2"> <div class="flex gap-2">
<h3 class="dark:text-white">File: {{ str_replace('|', '.', $fileName) }}</h3> <h3 class="dark:text-white">File: {{ str_replace('|', '.', $fileName) }}</h3>
<div class="flex gap-2"> <div class="flex gap-2">
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="Edit Configuration">
<x-slot:title>Edit Configuration</x-slot:title>
<x-slot:content>
<livewire:server.proxy.new-dynamic-configuration :server_id="$server_id" :fileName="$fileName" :value="$value" <livewire:server.proxy.new-dynamic-configuration :server_id="$server_id" :fileName="$fileName" :value="$value"
:newFile="$newFile" wire:key="{{ $fileName }}" /> :newFile="$newFile" wire:key="{{ $fileName }}" />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true"
class="button">Edit</button>
</x-slide-over>
</div> </div>
<x-forms.button isError wire:click="delete('{{ $fileName }}')">Delete</x-forms.button> <x-forms.button isError wire:click="delete('{{ $fileName }}')">Delete</x-forms.button>
</div> </div>

View File

@@ -9,15 +9,9 @@
<div class="flex gap-2"> <div class="flex gap-2">
<h2>Dynamic Configurations</h2> <h2>Dynamic Configurations</h2>
<x-forms.button wire:click='loadDynamicConfigurations'>Reload</x-forms.button> <x-forms.button wire:click='loadDynamicConfigurations'>Reload</x-forms.button>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Dynamic Configuration">
<x-slot:title>New Dynamic Configuration</x-slot:title>
<x-slot:content>
<livewire:server.proxy.new-dynamic-configuration /> <livewire:server.proxy.new-dynamic-configuration />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true"
class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class='pb-4'>You can add dynamic proxy configurations here.</div> <div class='pb-4'>You can add dynamic proxy configurations here.</div>
</div> </div>
@@ -29,7 +23,10 @@
@if ($contents?->isNotEmpty()) @if ($contents?->isNotEmpty())
@foreach ($contents as $fileName => $value) @foreach ($contents as $fileName => $value)
<div class="flex flex-col gap-2 py-2"> <div class="flex flex-col gap-2 py-2">
@if (str_replace('|', '.', $fileName) === 'coolify.yaml' || str_replace('|', '.', $fileName) === 'Caddyfile' || str_replace('|', '.', $fileName) === 'coolify.caddy' || str_replace('|', '.', $fileName) === 'default_redirect_404.caddy') @if (str_replace('|', '.', $fileName) === 'coolify.yaml' ||
str_replace('|', '.', $fileName) === 'Caddyfile' ||
str_replace('|', '.', $fileName) === 'coolify.caddy' ||
str_replace('|', '.', $fileName) === 'default_redirect_404.caddy')
<div> <div>
<h3 class="dark:text-white">File: {{ str_replace('|', '.', $fileName) }}</h3> <h3 class="dark:text-white">File: {{ str_replace('|', '.', $fileName) }}</h3>
</div> </div>

View File

@@ -1,5 +1,5 @@
<form wire:submit.prevent="addDynamicConfiguration" class="flex flex-col gap-4"> <form wire:submit.prevent="addDynamicConfiguration" class="flex flex-col w-full gap-4">
<x-forms.input id="fileName" label="Filename" required /> <x-forms.input autofocus id="fileName" label="Filename" required />
<x-forms.textarea id="value" label="Configuration" required rows="20" /> <x-forms.textarea id="value" label="Configuration" required rows="20" />
<x-forms.button type="submit" @click="slideOverOpen=false">Save</x-forms.button> <x-forms.button type="submit" @click="slideOverOpen=false">Save</x-forms.button>
</form> </form>

View File

@@ -1,14 +1,9 @@
<div> <div>
<div class="flex items-end gap-2 pb-6 "> <div class="flex items-end gap-2 pb-6 ">
<h2>Private Key</h2> <h2>Private Key</h2>
<x-slide-over fullScreen closeWithX> <x-modal-input buttonTitle="+ Add" title="New Private Key">
<x-slot:title>New Team</x-slot:title>
<x-slot:content>
<livewire:security.private-key.create /> <livewire:security.private-key.create />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
<x-forms.button wire:click.prevent='checkConnection'> <x-forms.button wire:click.prevent='checkConnection'>
Check connection Check connection
</x-forms.button> </x-forms.button>
@@ -31,10 +26,12 @@
<h3 class="pb-4">Choose another Key</h3> <h3 class="pb-4">Choose another Key</h3>
<div class="grid grid-cols-3 gap-2"> <div class="grid grid-cols-3 gap-2">
@forelse ($privateKeys as $private_key) @forelse ($privateKeys as $private_key)
<x-forms.button class="flex flex-col box" wire:click='setPrivateKey({{ $private_key->id }})'> <div class="box group">
<div>{{ $private_key->name }}</div> <div class="flex flex-col " wire:click='setPrivateKey({{ $private_key->id }})'>
<div class="text-xs">{{ $private_key->description }}</div> <div class="box-title">{{ $private_key->name }}</div>
</x-forms.button> <div class="box-description">{{ $private_key->description }}</div>
</div>
</div>
@empty @empty
<div>No private keys found. </div> <div>No private keys found. </div>
@endforelse @endforelse

View File

@@ -1,5 +1,4 @@
<div> <form wire:submit='createGitHubApp' class="flex flex-col w-full gap-2">
<form wire:submit='createGitHubApp' class="flex flex-col gap-2">
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input id="name" label="Name" required /> <x-forms.input id="name" label="Name" required />
<x-forms.input helper="If empty, your GitHub user will be used." id="organization" label="Organization" /> <x-forms.input helper="If empty, your GitHub user will be used." id="organization" label="Organization" />
@@ -19,4 +18,3 @@
Continue Continue
</x-forms.button> </x-forms.button>
</form> </form>
</div>

View File

@@ -2,14 +2,9 @@
<x-team.navbar /> <x-team.navbar />
<div class="flex gap-2"> <div class="flex gap-2">
<h2>Shared Variables</h2> <h2>Shared Variables</h2>
<x-slide-over> <x-modal-input buttonTitle="+ Add" title="New Shared Variable">
<x-slot:title>New Shared Variable</x-slot:title>
<x-slot:content>
<livewire:project.shared.environment-variable.add /> <livewire:project.shared.environment-variable.add />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class="flex items-center gap-2 pb-4">You can use these variables anywhere with <span <div class="flex items-center gap-2 pb-4">You can use these variables anywhere with <span
class="dark:text-warning">@{{ team.VARIABLENAME }}</span> <x-helper class="dark:text-warning">@{{ team.VARIABLENAME }}</span> <x-helper

View File

@@ -2,14 +2,9 @@
<x-team.navbar :team="auth()->user()->currentTeam()" /> <x-team.navbar :team="auth()->user()->currentTeam()" />
<div class="flex items-start gap-2"> <div class="flex items-start gap-2">
<h2 class="pb-4">S3 Storages</h2> <h2 class="pb-4">S3 Storages</h2>
<x-slide-over fullScreen closeWithX> <x-modal-input buttonTitle="+ Add" title="New S3 Storage">
<x-slot:title>New S3 Storage</x-slot:title>
<x-slot:content>
<livewire:team.storage.create /> <livewire:team.storage.create />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
{{-- <a class="dark:text-white hover:no-underline" href="/team/storages/new"> <x-forms.button>+ Add {{-- <a class="dark:text-white hover:no-underline" href="/team/storages/new"> <x-forms.button>+ Add
</x-forms.button></a> --}} </x-forms.button></a> --}}
</div> </div>

View File

@@ -2,14 +2,9 @@
<x-security.navbar /> <x-security.navbar />
<div class="flex gap-2"> <div class="flex gap-2">
<h2 class="pb-4">Private Keys</h2> <h2 class="pb-4">Private Keys</h2>
<x-slide-over closeWithX fullScreen> <x-modal-input buttonTitle="+ Add" title="New Private Key">
<x-slot:title>New Private Key</x-slot:title>
<x-slot:content>
<livewire:security.private-key.create /> <livewire:security.private-key.create />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class="grid gap-2 lg:grid-cols-2"> <div class="grid gap-2 lg:grid-cols-2">
@forelse ($privateKeys as $key) @forelse ($privateKeys as $key)

View File

@@ -1,14 +1,9 @@
<x-layout> <x-layout>
<div class="flex items-start gap-2"> <div class="flex items-start gap-2">
<h1>Sources</h1> <h1>Sources</h1>
<x-slide-over fullScreen closeWithX> <x-modal-input buttonTitle="+ Add" title="New GitHub App">
<x-slot:title>New GitHub App</x-slot:title>
<x-slot:content>
<livewire:source.github.create /> <livewire:source.github.create />
</x-slot:content> </x-modal-input>
<button @click="slideOverOpen=true" class="button">+
Add</button>
</x-slide-over>
</div> </div>
<div class="subtitle ">Git sources for your applications.</div> <div class="subtitle ">Git sources for your applications.</div>
<div class="grid gap-2 lg:grid-cols-2"> <div class="grid gap-2 lg:grid-cols-2">