This commit is contained in:
Andras Bacsai 2023-05-23 09:53:24 +02:00
parent c023fdae8b
commit ee515ff940
16 changed files with 69 additions and 32 deletions

View File

@ -3,6 +3,7 @@
namespace App\Http\Livewire\Project\Application; namespace App\Http\Livewire\Project\Application;
use App\Enums\ActivityTypes; use App\Enums\ActivityTypes;
use Illuminate\Support\Facades\Redis;
use Livewire\Component; use Livewire\Component;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
@ -14,7 +15,7 @@ class PollDeployment extends Component
public function polling() public function polling()
{ {
if ( is_null($this->activity) && isset($this->deployment_uuid)) { if (is_null($this->activity) && isset($this->deployment_uuid)) {
$this->activity = Activity::query() $this->activity = Activity::query()
->where('properties->type', '=', ActivityTypes::DEPLOYMENT->value) ->where('properties->type', '=', ActivityTypes::DEPLOYMENT->value)
->where('properties->type_uuid', '=', $this->deployment_uuid) ->where('properties->type_uuid', '=', $this->deployment_uuid)
@ -23,7 +24,7 @@ public function polling()
$this->activity?->refresh(); $this->activity?->refresh();
} }
if (data_get($this->activity, 'properties.status') == 'finished' || data_get($this->activity, 'properties.status') == 'failed' ) { if (data_get($this->activity, 'properties.status') == 'finished' || data_get($this->activity, 'properties.status') == 'failed') {
$this->isKeepAliveOn = false; $this->isKeepAliveOn = false;
} }
} }

View File

@ -5,13 +5,14 @@
use App\Models\Application; use App\Models\Application;
use App\Models\Server; use App\Models\Server;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class ContainerStatusJob implements ShouldQueue class ContainerStatusJob implements ShouldQueue, ShouldBeUnique
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -19,6 +20,10 @@ public function __construct(
public string|null $container_id = null, public string|null $container_id = null,
) { ) {
} }
public function uniqueId(): string
{
return $this->container_id;
}
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -6,19 +6,18 @@
use App\Data\CoolifyTaskArgs; use App\Data\CoolifyTaskArgs;
use App\Enums\ActivityTypes; use App\Enums\ActivityTypes;
use App\Models\Application; use App\Models\Application;
use App\Models\InstanceSettings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Spatie\Url\Url; use Spatie\Url\Url;
use Illuminate\Queue\Middleware\WithoutOverlapping;
class DeployApplicationJob implements ShouldQueue class DeployApplicationJob implements ShouldQueue
{ {
@ -35,9 +34,15 @@ class DeployApplicationJob implements ShouldQueue
protected $env_args; protected $env_args;
public static int $batch_counter = 0; public static int $batch_counter = 0;
public $timeout = 3600; public $timeout = 3600;
/**
* Create a new job instance. public function middleware(): array
*/ {
return [new WithoutOverlapping($this->application_uuid)];
}
public function uniqueId(): string
{
return $this->application_uuid;
}
public function __construct( public function __construct(
public string $deployment_uuid, public string $deployment_uuid,
public string $application_uuid, public string $application_uuid,

View File

@ -31,7 +31,9 @@ textarea {
select { select {
@apply select select-sm disabled:opacity-40 font-normal placeholder:text-neutral-700 text-white rounded-none; @apply select select-sm disabled:opacity-40 font-normal placeholder:text-neutral-700 text-white rounded-none;
} }
.breadcrumbs > ul > li::before {
@apply text-warning opacity-100;
}
button[type="button"] { button[type="button"] {
@apply btn btn-xs bg-coolgray-200 no-animation normal-case text-white rounded-none; @apply btn btn-xs bg-coolgray-200 no-animation normal-case text-white rounded-none;
} }

View File

@ -25,7 +25,7 @@ class="w-4 h-4 stroke-current">
</svg> </svg>
</label> </label>
<div tabindex="0" <div tabindex="0"
class="border rounded shadow border-warning/30 card compact dropdown-content bg-coolgray-200 w-96"> class="border rounded shadow border-coolgray-400 card compact dropdown-content bg-coolgray-200 w-96">
<div class="card-body"> <div class="card-body">
{!! $helper !!} {!! $helper !!}
</div> </div>

View File

@ -31,7 +31,7 @@ class="w-4 h-4 stroke-current">
</svg> </svg>
</label> </label>
<div tabindex="0" <div tabindex="0"
class="border rounded shadow border-warning/30 card compact dropdown-content bg-coolgray-200 w-96"> class="border rounded shadow border-coolgray-400 card compact dropdown-content bg-coolgray-200 w-96">
<div class="card-body"> <div class="card-body">
{!! $helper !!} {!! $helper !!}
</div> </div>

View File

@ -65,7 +65,7 @@ class="{{ request()->is('settings') ? 'absolute bottom-0 pb-4 text-warning' : 'a
<div class="dropdown dropdown-left"> <div class="dropdown dropdown-left">
<label tabindex="0" class="btn btn-ghost no-animation hover:bg-transparent"> <label tabindex="0" class="btn btn-ghost no-animation hover:bg-transparent">
<div class="flex items-center justify-center gap-2 avatar placeholder"> <div class="flex items-center justify-center gap-2 avatar placeholder">
<div class="w-10 border border-dotted rounded-full border-neutral-600 text-warning"> <div class="w-10 border rounded-full border-neutral-600 text-warning">
<span class="text-xs">{{ Str::of(auth()->user()->name)->substr(0, 2)->upper() }}</span> <span class="text-xs">{{ Str::of(auth()->user()->name)->substr(0, 2)->upper() }}</span>
</div> </div>
<x-chevron-down /> <x-chevron-down />

View File

@ -2,7 +2,7 @@
@if ($this->activity) @if ($this->activity)
<div <div
class="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"> class="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.750ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity) }}</pre> <pre class="font-mono whitespace-pre-wrap" @if ($isPollingActive) wire:poll.2000ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity) }}</pre>
{{-- @else {{-- @else
<pre class="whitespace-pre-wrap">Output will be here...</pre> --}} <pre class="whitespace-pre-wrap">Output will be here...</pre> --}}
</div> </div>

View File

@ -1,6 +1,18 @@
<div> <a @class([
<a @if ($status === 'in_progress' || $status === 'queued') wire:poll='polling' @endif href="{{ url()->current() }}/{{ $deployment_uuid }}"> 'bg-coolgray-200 p-2 border-l border-dashed border-transparent transition-colors hover:no-underline',
{{ $created_at }} 'border-warning hover:bg-warning hover:text-black' =>
{{ $deployment_uuid }}</a> $status == 'in_progress' || $status == 'queued',
{{ $status }} 'border-error hover:bg-error' => $status == 'error',
</div> 'border-success hover:bg-success' => $status == 'finished',
]) @if ($status === 'in_progress' || $status === 'queued')
wire:poll.5000ms='polling'
@endif href="{{ url()->current() }}/{{ $deployment_uuid }}" class="hover:no-underline">
<div class="flex flex-col justify-start">
<div>
{{ $status }}
</div>
<div>
{{ $created_at }}
</div>
</div>
</a>

View File

@ -1,4 +1,4 @@
<div <div
class="flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 mt-4 text-xs text-white"> class="flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 mt-4 text-xs text-white">
<pre class="font-mono whitespace-pre-wrap" @if ($isKeepAliveOn) wire:poll.1000ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($activity) }}</pre> <pre class="font-mono whitespace-pre-wrap" @if ($isKeepAliveOn) wire:poll.2000ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($activity) }}</pre>
</div> </div>

View File

@ -10,7 +10,7 @@
</x-inputs.button> </x-inputs.button>
<x-inputs.button x-on:click.prevent="stopProxy = true">Stop <x-inputs.button x-on:click.prevent="stopProxy = true">Stop
</x-inputs.button> </x-inputs.button>
<div wire:poll="proxyStatus"> <div wire:poll.5000ms="proxyStatus">
@if ( @if (
$server->extra_attributes->last_applied_proxy_settings && $server->extra_attributes->last_applied_proxy_settings &&
$server->extra_attributes->last_saved_proxy_settings !== $server->extra_attributes->last_applied_proxy_settings) $server->extra_attributes->last_saved_proxy_settings !== $server->extra_attributes->last_applied_proxy_settings)

View File

@ -2,8 +2,8 @@
<h1 class="pb-0">Configuration</h1> <h1 class="pb-0">Configuration</h1>
<div class="pb-10 text-sm breadcrumbs"> <div class="pb-10 text-sm breadcrumbs">
<ul> <ul>
<li><a <li><a href="{{ route('project.show', ['project_uuid' => request()->route('project_uuid')]) }}">
href="{{ route('project.show', ['project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('project_uuid') }}</a> {{ $application->environment->project->name }}</a>
</li> </li>
<li><a <li><a
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a> href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>

View File

@ -12,7 +12,7 @@
</ul> </ul>
</div> </div>
<x-applications.navbar :application="$application" /> <x-applications.navbar :application="$application" />
<div class="pt-2"> <div class="flex flex-col gap-2 pt-2">
@forelse ($deployments as $deployment) @forelse ($deployments as $deployment)
<livewire:project.application.get-deployments :deployment_uuid="data_get($deployment->properties, 'type_uuid')" :created_at="data_get($deployment, 'created_at')" :status="data_get($deployment->properties, 'status')" /> <livewire:project.application.get-deployments :deployment_uuid="data_get($deployment->properties, 'type_uuid')" :created_at="data_get($deployment, 'created_at')" :status="data_get($deployment->properties, 'status')" />
@empty @empty

View File

@ -6,18 +6,21 @@
</div> </div>
<div class="pb-10 text-sm breadcrumbs"> <div class="pb-10 text-sm breadcrumbs">
<ul> <ul>
<li><a <li>
href="{{ route('project.show', ['project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('project_uuid') }}</a> <a href="{{ route('project.show', ['project_uuid' => request()->route('project_uuid')]) }}">
{{ $project->name }}
</a>
</li> </li>
<li> <li>
{{ request()->route('environment_name') }} </li> {{ request()->route('environment_name') }}
</li>
</ul> </ul>
</div> </div>
</div> </div>
@if ($environment->applications->count() === 0) @if ($environment->applications->count() === 0)
<p>No resources yet.</p> <p>No resources yet.</p>
@endif @endif
<div class="flex gap-2"> <div class="flex flex-col gap-2">
@foreach ($environment->applications->sortBy('name') as $application) @foreach ($environment->applications->sortBy('name') as $application)
<a class="box" <a class="box"
href="{{ route('project.application.configuration', [$project->uuid, $environment->name, $application->uuid]) }}"> href="{{ route('project.application.configuration', [$project->uuid, $environment->name, $application->uuid]) }}">

View File

@ -1,5 +1,10 @@
<x-layout> <x-layout>
<h1>Environments</h1> <h1 class="pb-0">Environments</h1>
<div class="pb-10 text-sm breadcrumbs">
<ul>
<li>{{ $project->name }} </li>
</ul>
</div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@foreach ($project->environments as $environment) @foreach ($project->environments as $environment)
<a class="box" href="{{ route('project.resources', [$project->uuid, $environment->name]) }}"> <a class="box" href="{{ route('project.resources', [$project->uuid, $environment->name]) }}">

View File

@ -1,7 +1,11 @@
<x-layout> <x-layout>
<h1 class="border-b-2 border-solid border-coolgray-200">Server <span <h1 class="pb-0">Server</h1>
class="text-xs text-neutral-400">{{ $server->name }}</span></h1> <div class="text-sm border-b-2 border-solid breadcrumbs border-coolgray-200">
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex pt-6"> <ul>
<li>{{ data_get($server, 'name') }}</li>
</ul>
</div>
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex pt-10">
<div class="flex flex-col gap-4 min-w-fit"> <div class="flex flex-col gap-4 min-w-fit">
<a :class="activeTab === 'general' && 'text-white'" <a :class="activeTab === 'general' && 'text-white'"
@click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General</a> @click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General</a>