This commit is contained in:
Andras Bacsai 2023-06-13 10:02:58 +02:00
parent a4177ca0ec
commit e4704fb7e6
16 changed files with 123 additions and 54 deletions

View File

@ -38,24 +38,29 @@ public function mount()
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
$found = ModelsStandaloneDocker::where('server_id', $this->server_id)->where('network', $this->network)->first(); try {
if ($found) { $found = ModelsStandaloneDocker::where('server_id', $this->server_id)->where('network', $this->network)->first();
$this->addError('network', 'Network already added to this server.'); if ($found) {
return; $this->addError('network', 'Network already added to this server.');
return;
}
$server = Server::find($this->server_id);
instant_remote_process(['docker network create --attachable ' . $this->network], $server);
instant_remote_process(["docker network connect $this->network coolify-proxy"], $server);
$docker = ModelsStandaloneDocker::create([
'name' => $this->name,
'network' => $this->network,
'server_id' => $this->server_id,
'team_id' => session('currentTeam')->id
]);
return redirect()->route('destination.show', $docker->uuid);
} catch (\Exception $e) {
return general_error_handler(err: $e);
} }
$server = Server::find($this->server_id);
instant_remote_process(['docker network create --attachable ' . $this->network], $server, throwError: false);
instant_remote_process(["docker network connect $this->network coolify-proxy"], $server, throwError: false);
$docker = ModelsStandaloneDocker::create([
'name' => $this->name,
'network' => $this->network,
'server_id' => $this->server_id,
'team_id' => session('currentTeam')->id
]);
return redirect()->route('destination.show', $docker->uuid);
} }
} }

View File

@ -33,7 +33,12 @@ public function scopeWithExtraAttributes(): Builder
{ {
return $this->extra_attributes->modelScope(); return $this->extra_attributes->modelScope();
} }
public function destinations()
{
$standalone_docker = $this->hasMany(StandaloneDocker::class)->get();
$swarm_docker = $this->hasMany(SwarmDocker::class)->get();
return $standalone_docker->concat($swarm_docker);
}
public function standaloneDockers() public function standaloneDockers()
{ {
return $this->hasMany(StandaloneDocker::class); return $this->hasMany(StandaloneDocker::class);

View File

@ -38,7 +38,7 @@ textarea {
@apply textarea placeholder:text-neutral-700 text-white rounded scrollbar; @apply textarea placeholder:text-neutral-700 text-white rounded scrollbar;
} }
select { select {
@apply select select-sm text-sm disabled:bg-coolgray-200 border-none disabled:opacity-50 font-normal placeholder:text-neutral-700 text-white rounded; @apply h-7 select select-sm text-sm disabled:bg-coolgray-200 border-none disabled:opacity-50 font-normal placeholder:text-neutral-700 text-white rounded;
} }
.loading { .loading {
@apply w-4 text-warning; @apply w-4 text-warning;
@ -67,7 +67,7 @@ a {
} }
.main-navbar { .main-navbar {
@apply fixed h-full overflow-hidden pt-14; @apply fixed h-full overflow-hidden pt-16;
} }
.kbd-custom { .kbd-custom {
@apply px-2 text-xs border border-dashed rounded border-neutral-700 text-warning; @apply px-2 text-xs border border-dashed rounded border-neutral-700 text-warning;

View File

@ -1,7 +1,7 @@
<template> <template>
<Transition name="fade"> <Transition name="fade">
<div> <div>
<div class="flex items-center p-1 px-2 overflow-hidden transition-all transform rounded cursor-pointer bg-coolgray-200" <div class="flex items-center p-1 px-2 mt-2 overflow-hidden transition-all transform rounded cursor-pointer bg-coolgray-200"
@click="showCommandPalette = true"> @click="showCommandPalette = true">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 icon" viewBox="0 0 24 24" stroke-width="2" <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 icon" viewBox="0 0 24 24" stroke-width="2"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
@ -319,36 +319,42 @@ const magicActions = [{
}, },
{ {
id: 12, id: 12,
name: 'Goto: Settings', name: 'Goto: Destinations',
icon: 'goto', icon: 'goto',
sequence: ['main', 'redirect'] sequence: ['main', 'redirect']
}, },
{ {
id: 13, id: 13,
name: 'Goto: Command Center', name: 'Goto: Settings',
icon: 'goto', icon: 'goto',
sequence: ['main', 'redirect'] sequence: ['main', 'redirect']
}, },
{ {
id: 14, id: 14,
name: 'Goto: Notifications', name: 'Goto: Command Center',
icon: 'goto', icon: 'goto',
sequence: ['main', 'redirect'] sequence: ['main', 'redirect']
}, },
{ {
id: 15, id: 15,
name: 'Goto: Profile', name: 'Goto: Notifications',
icon: 'goto', icon: 'goto',
sequence: ['main', 'redirect'] sequence: ['main', 'redirect']
}, },
{ {
id: 16, id: 16,
name: 'Goto: Teams', name: 'Goto: Profile',
icon: 'goto', icon: 'goto',
sequence: ['main', 'redirect'] sequence: ['main', 'redirect']
}, },
{ {
id: 17, id: 17,
name: 'Goto: Teams',
icon: 'goto',
sequence: ['main', 'redirect']
},
{
id: 18,
name: 'Goto: Switch Teams', name: 'Goto: Switch Teams',
icon: 'goto', icon: 'goto',
sequence: ['main', 'redirect'] sequence: ['main', 'redirect']
@ -545,23 +551,26 @@ async function redirect() {
targetUrl.pathname = `/sources` targetUrl.pathname = `/sources`
break; break;
case 12: case 12:
targetUrl.pathname = `/settings` targetUrl.pathname = `/destinations`
break; break;
case 13: case 13:
targetUrl.pathname = `/command-center` targetUrl.pathname = `/settings`
break; break;
case 14: case 14:
targetUrl.pathname = `/profile/team/notifications` targetUrl.pathname = `/command-center`
break; break;
case 15: case 15:
targetUrl.pathname = `/profile` targetUrl.pathname = `/profile/team/notifications`
break; break;
case 16: case 16:
targetUrl.pathname = `/profile/team` targetUrl.pathname = `/profile`
break; break;
case 17: case 17:
targetUrl.pathname = `/profile/team` targetUrl.pathname = `/profile/team`
break; break;
case 18:
targetUrl.pathname = `/profile/team`
break;
} }
window.location.href = targetUrl; window.location.href = targetUrl;
} }

View File

@ -32,7 +32,7 @@ class="w-4 h-4 stroke-current">
</span> </span>
</label> </label>
@endif @endif
<select class="select-xs h-7" {{ $attributes }} <select {{ $attributes }}
@if ($id) name={{ $id }} wire:model.defer={{ $id }} @endif> @if ($id) name={{ $id }} wire:model.defer={{ $id }} @endif>
{{ $slot }} {{ $slot }}
</select> </select>

View File

@ -70,7 +70,7 @@ class="{{ request()->is('settings*') ? 'text-warning icon' : 'icon' }}" viewBox=
@endif @endif
</ul> </ul>
</nav> </nav>
<div class="fixed top-0 right-0 p-2"> <div class="fixed right-0 p-2 top-1">
<div class="group"> <div class="group">
<label tabindex="0" <label tabindex="0"
class="absolute top-0 right-0 p-2 m-2 cursor-pointer hover:bg-transparent hover:text-warning"> class="absolute top-0 right-0 p-2 m-2 cursor-pointer hover:bg-transparent hover:text-warning">

View File

@ -0,0 +1,30 @@
<x-layout>
<h1>Destinations</h1>
<div class="pt-2 pb-10 text-sm">All Destinations</div>
<div class="grid grid-cols-2 gap-2">
@forelse ($destinations as $destination)
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
<a class="flex gap-4 text-center hover:no-underline box group"
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
<div class="group-hover:text-white">
<div>{{ $destination->name }}</div>
</div>
</a>
@endif
@if ($destination->getMorphClass() === 'App\Models\SwarmDocker')
<a class="flex gap-4 text-center hover:no-underline box group"
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
<div class="group-hover:text-white">
<div>{{ $destination->name }}</div>
</div>
</a>
@endif
@empty
<div>
<div>No destinations found.</div>
<x-use-magic-bar />
</div>
@endforelse
</div>
</x-layout>

View File

@ -1,4 +1,3 @@
<x-layout> <x-layout>
<h1>Destination</h1>
<livewire:destination.form :destination="$destination" /> <livewire:destination.form :destination="$destination" />
</x-layout> </x-layout>

View File

@ -2,7 +2,7 @@
@if ($this->activity) @if ($this->activity)
@if ($header) @if ($header)
<div class="flex gap-2 pb-2"> <div class="flex gap-2 pb-2">
<h2>Logs</h2> <h3>Logs</h3>
@if ($isPollingActive) @if ($isPollingActive)
<x-loading /> <x-loading />
@endif @endif

View File

@ -1,18 +1,27 @@
<div x-data="{ deleteDestination: false }"> <div x-data="{ deleteDestination: false }">
<x-naked-modal show="deleteDestination" message='Are you sure you would like to delete this destination?' /> <x-naked-modal show="deleteDestination" message='Are you sure you would like to delete this destination?' />
<form class="flex flex-col gap-4" wire:submit.prevent='submit'> <form class="flex flex-col">
<x-forms.input id="destination.name" label="Name" /> <div class="flex items-center gap-2">
<x-forms.input id="destination.server.ip" label="Server IP" readonly /> <h1>Destination</h1>
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') <x-forms.button wire:click.prevent='submit' type="submit">
<x-forms.input id="destination.network" label="Docker Network" readonly />
@endif
<div>
<x-forms.button type="submit">
Save Save
</x-forms.button> </x-forms.button>
<x-forms.button x-on:click.prevent="deleteDestination = true"> <x-forms.button x-on:click.prevent="deleteDestination = true">
Delete Delete
</x-forms.button> </x-forms.button>
</div> </div>
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
<div class="pt-2 pb-10 text-sm">Your standalone docker network.</div>
@else
<div class="pt-2 pb-10 text-sm">Your swarm docker network.</div>
@endif
<div class="flex gap-2">
<x-forms.input id="destination.name" label="Name" />
<x-forms.input id="destination.server.ip" label="Server IP" readonly />
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
<x-forms.input id="destination.network" label="Docker Network" readonly />
@endif
</div>
</form> </form>
</div> </div>

View File

@ -25,7 +25,7 @@
<x-forms.checkbox class="pb-8" disabled instantSave noDirty id="is_part_of_swarm" <x-forms.checkbox class="pb-8" disabled instantSave noDirty id="is_part_of_swarm"
label="Is it part of a Swarm cluster?" /> label="Is it part of a Swarm cluster?" />
<x-forms.button type="submit"> <x-forms.button type="submit">
Save Server Save New Server
</x-forms.button> </x-forms.button>
</form> </form>
</div> </div>

View File

@ -7,6 +7,7 @@
<div wire:loading wire:target="checkProxySettingsInSync"> <div wire:loading wire:target="checkProxySettingsInSync">
<x-loading /> <x-loading />
</div> </div>
@isset($proxy_settings) @isset($proxy_settings)
@if ($selectedProxy->value === 'TRAEFIK_V2') @if ($selectedProxy->value === 'TRAEFIK_V2')
<form wire:submit.prevent='saveConfiguration({{ $server }})'> <form wire:submit.prevent='saveConfiguration({{ $server }})'>
@ -25,6 +26,9 @@
<div class="text-sm text-red-500">Configuration out of sync. Restart to get the new configs. <div class="text-sm text-red-500">Configuration out of sync. Restart to get the new configs.
</div> </div>
@endif @endif
<div class="container w-full py-4 mx-auto">
<livewire:activity-monitor :header="true" />
</div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<x-forms.textarea label="Configuration file: traefik.conf" class="text-xs" noDirty <x-forms.textarea label="Configuration file: traefik.conf" class="text-xs" noDirty
name="proxy_settings" wire:model.defer="proxy_settings" rows="30" /> name="proxy_settings" wire:model.defer="proxy_settings" rows="30" />
@ -54,9 +58,6 @@
</div> </div>
</div> </div>
@endif @endif
<div class="container w-full pt-4 mx-auto">
<livewire:activity-monitor :header="true" />
</div>
@else @else
<div class="text-sm">Server is not validated. Validate first.</div> <div class="text-sm">Server is not validated. Validate first.</div>
@endif @endif

View File

@ -56,12 +56,13 @@ class="mt-1 text-xs text-white normal-case rounded min-w-max menu bg-coolgray-20
</div> </div>
</div> </div>
@else @else
<x-forms.button wire:click='deploy'> <svg xmlns="http://www.w3.org/2000/svg" class="icon" width="44" <button wire:click='deploy' class="flex items-center gap-2 text-sm cursor-pointer hover:text-white"> <svg
height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24" stroke-width="1.5"
stroke-linecap="round" stroke-linejoin="round"> stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M7 4v16l13 -8z" /> <path d="M7 4v16l13 -8z" />
</svg>Start Proxy</x-forms.button> </svg>Start Proxy
</button>
@endif @endif
@endif @endif
</div> </div>

View File

@ -15,8 +15,8 @@
<x-forms.input id="custom_port" label="Custom Git Port" required /> <x-forms.input id="custom_port" label="Custom Git Port" required />
</div> </div>
<x-forms.checkbox class="pt-2" id="is_system_wide" label="System Wide" /> <x-forms.checkbox class="pt-2" id="is_system_wide" label="System Wide" />
<x-forms.button isHighlighted type="submit"> <x-forms.button type="submit">
Create New Source Save New Source
</x-forms.button> </x-forms.button>
</form> </form>
</div> </div>

View File

@ -1,3 +1,3 @@
<x-layout> <x-layout>
GitLab WIP WIP
</x-layout> </x-layout>

View File

@ -126,6 +126,16 @@
}); });
Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function () {
Route::get('/destinations', function () {
$servers = Server::all();
$destinations = collect([]);
foreach ($servers as $server) {
$destinations = $destinations->merge($server->destinations());
}
return view('destination.all', [
'destinations' => $destinations,
]);
})->name('destination.all');
Route::get('/destination/new', function () { Route::get('/destination/new', function () {
$servers = Server::validated()->get(); $servers = Server::validated()->get();
$pre_selected_server_uuid = data_get(request()->query(), 'server'); $pre_selected_server_uuid = data_get(request()->query(), 'server');