mirror of
https://github.com/vitodeploy/vito.git
synced 2025-04-19 09:51:37 +00:00
Feature/add remote server logs (#159)
This commit is contained in:
parent
75aed62d75
commit
4517ca7d2a
35
app/Actions/Server/CreateServerLog.php
Executable file
35
app/Actions/Server/CreateServerLog.php
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Server;
|
||||||
|
|
||||||
|
use App\Models\Server;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class CreateServerLog
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function create(Server $server, array $input): void
|
||||||
|
{
|
||||||
|
$this->validate($input);
|
||||||
|
|
||||||
|
$server->logs()->create([
|
||||||
|
'is_remote' => true,
|
||||||
|
'name' => $input['path'],
|
||||||
|
'type' => 'remote',
|
||||||
|
'disk' => 'ssh',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function validate(array $input): void
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'path' => 'required',
|
||||||
|
])->validate();
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,6 @@ public function show(Server $server): View
|
|||||||
{
|
{
|
||||||
return view('servers.show', [
|
return view('servers.show', [
|
||||||
'server' => $server,
|
'server' => $server,
|
||||||
'logs' => $server->logs()->latest()->limit(10)->get(),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Actions\Server\CreateServerLog;
|
||||||
|
use App\Facades\Toast;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ServerLogController extends Controller
|
class ServerLogController extends Controller
|
||||||
{
|
{
|
||||||
@ -13,6 +16,7 @@ public function index(Server $server): View
|
|||||||
{
|
{
|
||||||
return view('server-logs.index', [
|
return view('server-logs.index', [
|
||||||
'server' => $server,
|
'server' => $server,
|
||||||
|
'pageTitle' => __('Vito Logs'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,4 +30,31 @@ public function show(Server $server, ServerLog $serverLog): RedirectResponse
|
|||||||
'content' => $serverLog->getContent(),
|
'content' => $serverLog->getContent(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function remote(Server $server): View
|
||||||
|
{
|
||||||
|
return view('server-logs.remote-logs', [
|
||||||
|
'server' => $server,
|
||||||
|
'remote' => true,
|
||||||
|
'pageTitle' => __('Remote Logs'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Server $server, Request $request): \App\Helpers\HtmxResponse
|
||||||
|
{
|
||||||
|
app(CreateServerLog::class)->create($server, $request->input());
|
||||||
|
|
||||||
|
Toast::success('Log added successfully.');
|
||||||
|
|
||||||
|
return htmx()->redirect(route('servers.logs.remote', ['server' => $server]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Server $server, ServerLog $serverLog): RedirectResponse
|
||||||
|
{
|
||||||
|
$serverLog->delete();
|
||||||
|
|
||||||
|
Toast::success('Remote log deleted successfully.');
|
||||||
|
|
||||||
|
return redirect()->route('servers.logs.remote', ['server' => $server]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ public function index(Server $server, Site $site): View
|
|||||||
return view('site-logs.index', [
|
return view('site-logs.index', [
|
||||||
'server' => $server,
|
'server' => $server,
|
||||||
'site' => $site,
|
'site' => $site,
|
||||||
|
'pageTitle' => __('Vito Logs'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,13 @@ class ServerLog extends AbstractModel
|
|||||||
'type',
|
'type',
|
||||||
'name',
|
'name',
|
||||||
'disk',
|
'disk',
|
||||||
|
'is_remote',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'server_id' => 'integer',
|
'server_id' => 'integer',
|
||||||
'site_id' => 'integer',
|
'site_id' => 'integer',
|
||||||
|
'is_remote' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function boot(): void
|
public static function boot(): void
|
||||||
@ -64,6 +66,17 @@ public function site(): BelongsTo
|
|||||||
return $this->belongsTo(Site::class);
|
return $this->belongsTo(Site::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getRemote($query, bool $active = true, ?Site $site = null)
|
||||||
|
{
|
||||||
|
$query->where('is_remote', $active);
|
||||||
|
|
||||||
|
if ($site) {
|
||||||
|
$query->where('name', 'like', $site->path.'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
public function write($buf): void
|
public function write($buf): void
|
||||||
{
|
{
|
||||||
if (Str::contains($buf, 'VITO_SSH_ERROR')) {
|
if (Str::contains($buf, 'VITO_SSH_ERROR')) {
|
||||||
@ -78,6 +91,10 @@ public function write($buf): void
|
|||||||
|
|
||||||
public function getContent(): ?string
|
public function getContent(): ?string
|
||||||
{
|
{
|
||||||
|
if ($this->is_remote) {
|
||||||
|
return $this->server->os()->readFile($this->name, 150);
|
||||||
|
}
|
||||||
|
|
||||||
if (Storage::disk($this->disk)->exists($this->name)) {
|
if (Storage::disk($this->disk)->exists($this->name)) {
|
||||||
return Storage::disk($this->disk)->get($this->name);
|
return Storage::disk($this->disk)->get($this->name);
|
||||||
}
|
}
|
||||||
|
@ -108,12 +108,18 @@ public function editFile(string $path, ?string $content = null): void
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readFile(string $path): string
|
public function readFile(string $path, ?int $lastLines = null): string
|
||||||
{
|
{
|
||||||
|
$params = [
|
||||||
|
'path' => $path,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($lastLines !== null) {
|
||||||
|
$params['lines'] = $lastLines;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->server->ssh()->exec(
|
return $this->server->ssh()->exec(
|
||||||
$this->getScript('read-file.sh', [
|
$this->getScript('read-file.sh', $params)
|
||||||
'path' => $path,
|
|
||||||
])
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1,7 @@
|
|||||||
[ -f __path__ ] && cat __path__
|
if [ -f __path__ ]; then
|
||||||
|
if [ -n __lines__ ]; then
|
||||||
|
sudo tail -n __lines__ __path__
|
||||||
|
else
|
||||||
|
sudo cat __path__
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('server_logs', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_remote')->default(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('server_logs', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('is_remote');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -6,8 +6,9 @@
|
|||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-select="#deploy"
|
hx-select="#deploy"
|
||||||
>
|
>
|
||||||
<x-primary-button hx-disable>
|
<x-primary-button class="flex items-center justify-between" :active="true" hx-disable>
|
||||||
{{ __("Deploy") }}
|
{{ __("Deploy") }}
|
||||||
|
<x-heroicon name="o-play-circle" class="ml-1 h-5 w-5" />
|
||||||
</x-primary-button>
|
</x-primary-button>
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
{{ $attributes }}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Zm3.75 11.625a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 599 B |
15
resources/views/components/heroicons/o-play-circle.blade.php
Normal file
15
resources/views/components/heroicons/o-play-circle.blade.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
{{ $attributes }}
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15.91 11.672a.375.375 0 0 1 0 .656l-5.603 3.113a.375.375 0 0 1-.557-.328V8.887c0-.286.307-.466.557-.327l5.603 3.112Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 476 B |
@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="text-lg font-semibold">{{ $server->name }}</h2>
|
<h2 class="text-lg font-semibold">{{ $server->name }}</h2>
|
||||||
|
|
||||||
|
@if (isset($header))
|
||||||
|
<header class="flex-grow border-b border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800">
|
||||||
|
<div class="mx-auto flex h-20 w-full max-w-full items-center justify-between px-5">
|
||||||
|
{{ $header }}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="flex flex-col items-end">
|
<div class="flex flex-col items-end">
|
||||||
@include("servers.partials.server-status")
|
@include("servers.partials.server-status")
|
||||||
<x-input-label class="mt-1 cursor-pointer" x-data="{ copied: false }">
|
<x-input-label class="mt-1 cursor-pointer" x-data="{ copied: false }">
|
||||||
|
@ -155,7 +155,7 @@ class="fixed left-0 top-0 z-40 h-screen w-64 -translate-x-full border-r border-g
|
|||||||
<li>
|
<li>
|
||||||
<x-sidebar-link
|
<x-sidebar-link
|
||||||
:href="route('servers.logs', ['server' => $server])"
|
:href="route('servers.logs', ['server' => $server])"
|
||||||
:active="request()->routeIs('servers.logs')"
|
:active="request()->routeIs('servers.logs*')"
|
||||||
>
|
>
|
||||||
<x-heroicon name="o-square-3-stack-3d" class="h-6 w-6" />
|
<x-heroicon name="o-square-3-stack-3d" class="h-6 w-6" />
|
||||||
<span class="ml-2">
|
<span class="ml-2">
|
||||||
|
@ -50,7 +50,7 @@ class="mr-1"
|
|||||||
<x-tab-item
|
<x-tab-item
|
||||||
class="mr-1"
|
class="mr-1"
|
||||||
:href="route('servers.sites.logs', ['server' => $site->server, 'site' => $site])"
|
:href="route('servers.sites.logs', ['server' => $site->server, 'site' => $site])"
|
||||||
:active="request()->routeIs('servers.sites.logs')"
|
:active="request()->routeIs('servers.sites.logs*')"
|
||||||
>
|
>
|
||||||
<x-heroicon name="o-square-3-stack-3d" class="h-5 w-5" />
|
<x-heroicon name="o-square-3-stack-3d" class="h-5 w-5" />
|
||||||
<span class="ml-2 hidden xl:block">Logs</span>
|
<span class="ml-2 hidden xl:block">Logs</span>
|
||||||
@ -105,7 +105,7 @@ class="flex w-full cursor-pointer items-center rounded-md border border-gray-300
|
|||||||
</x-dropdown-link>
|
</x-dropdown-link>
|
||||||
<x-dropdown-link
|
<x-dropdown-link
|
||||||
:href="route('servers.sites.logs', ['server' => $site->server, 'site' => $site])"
|
:href="route('servers.sites.logs', ['server' => $site->server, 'site' => $site])"
|
||||||
:active="request()->routeIs('servers.sites.logs')"
|
:active="request()->routeIs('servers.sites.logs*')"
|
||||||
>
|
>
|
||||||
<x-heroicon name="o-square-3-stack-3d" class="h-5 w-5" />
|
<x-heroicon name="o-square-3-stack-3d" class="h-5 w-5" />
|
||||||
<span class="ml-2">Logs</span>
|
<span class="ml-2">Logs</span>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<x-server-layout :server="$server">
|
<x-server-layout :server="$server">
|
||||||
<x-slot name="pageTitle">{{ $server->name }} Logs</x-slot>
|
@if (isset($pageTitle))
|
||||||
|
<x-slot name="pageTitle">{{ $server->name }} - {{ $pageTitle }}</x-slot>
|
||||||
|
@endif
|
||||||
|
|
||||||
@include("server-logs.partials.logs-list")
|
@include("server-logs.partials.header")
|
||||||
|
@include("server-logs.partials.logs-list-live")
|
||||||
</x-server-layout>
|
</x-server-layout>
|
||||||
|
59
resources/views/server-logs/partials/add-log.blade.php
Normal file
59
resources/views/server-logs/partials/add-log.blade.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<div x-data="">
|
||||||
|
<x-card-header>
|
||||||
|
<x-slot name="title">{{ __("Manage your remote logs") }}</x-slot>
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __("Here you can add new logs") }}
|
||||||
|
</x-slot>
|
||||||
|
<x-slot name="aside">
|
||||||
|
<div class="flex flex-col items-end lg:flex-row lg:items-center">
|
||||||
|
<x-primary-button class="cursor-pointer" x-on:click="$dispatch('open-modal', 'add-log')">
|
||||||
|
{{ __("Add Remote Log") }}
|
||||||
|
</x-primary-button>
|
||||||
|
|
||||||
|
<x-modal name="add-log">
|
||||||
|
<form
|
||||||
|
id="add-log-form"
|
||||||
|
hx-post="{{ route("servers.logs.remote.store", ["server" => $server]) }}"
|
||||||
|
hx-select="#add-log-form"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
class="p-6"
|
||||||
|
>
|
||||||
|
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||||
|
{{ __("Add Remote Log") }}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
<x-input-label for="path" :value="__('Please introduce the full path to the log file.')" />
|
||||||
|
<x-text-input
|
||||||
|
list="sites"
|
||||||
|
value="{{ old('path') }}"
|
||||||
|
id="path"
|
||||||
|
name="path"
|
||||||
|
type="text"
|
||||||
|
class="mt-1 w-full"
|
||||||
|
/>
|
||||||
|
<datalist id="sites">
|
||||||
|
@foreach ($server->sites as $site)
|
||||||
|
<option>{{ str($site->path)->append("/") }}</option>
|
||||||
|
@endforeach
|
||||||
|
</datalist>
|
||||||
|
@error("path")
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 flex items-center justify-end">
|
||||||
|
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||||
|
{{ __("Cancel") }}
|
||||||
|
</x-secondary-button>
|
||||||
|
|
||||||
|
<x-primary-button class="ml-3" hx-disable>
|
||||||
|
{{ __("Save") }}
|
||||||
|
</x-primary-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</x-modal>
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
</x-card-header>
|
||||||
|
</div>
|
54
resources/views/server-logs/partials/header.blade.php
Normal file
54
resources/views/server-logs/partials/header.blade.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@if (isset($pageTitle))
|
||||||
|
<x-slot name="pageTitle">{{ $pageTitle }} - {{ $server->name }}</x-slot>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-slot name="header">
|
||||||
|
<div class="hidden md:flex md:items-center md:justify-start">
|
||||||
|
<x-tab-item
|
||||||
|
class="mr-1"
|
||||||
|
:href="route('servers.logs', ['server' => $server])"
|
||||||
|
:active="request()->routeIs('servers.logs')"
|
||||||
|
>
|
||||||
|
<x-heroicon name="o-square-3-stack-3d" class="h-5 w-5" />
|
||||||
|
<span class="ml-2 hidden xl:block">{{ __("Vito Logs") }}</span>
|
||||||
|
</x-tab-item>
|
||||||
|
<x-tab-item
|
||||||
|
class="mr-1"
|
||||||
|
:href="route('servers.logs.remote', ['server' => $server])"
|
||||||
|
:active="request()->routeIs('servers.logs.remote')"
|
||||||
|
>
|
||||||
|
<x-heroicon name="o-document-magnifying-glass" class="h-5 w-5" />
|
||||||
|
<span class="ml-2 hidden xl:block">{{ __("Remote Logs") }}</span>
|
||||||
|
</x-tab-item>
|
||||||
|
</div>
|
||||||
|
<div class="md:hidden">
|
||||||
|
<x-dropdown align="left">
|
||||||
|
<x-slot name="trigger">
|
||||||
|
<div
|
||||||
|
class="flex w-full cursor-pointer items-center rounded-md border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-primary-500 focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-primary-500 dark:focus:ring-primary-500"
|
||||||
|
>
|
||||||
|
Select
|
||||||
|
<button type="button" class="ml-2">
|
||||||
|
<x-heroicon name="o-chevron-down" class="h-4 w-4 text-gray-400" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
<x-slot name="content">
|
||||||
|
<x-dropdown-link
|
||||||
|
:href="route('servers.logs', ['server' => $server])"
|
||||||
|
:active="request()->routeIs('servers.logs')"
|
||||||
|
>
|
||||||
|
<x-heroicon name="o-cog-6-tooth" class="h-5 w-5" />
|
||||||
|
<span class="ml-2">{{ __("Vito Logs") }}</span>
|
||||||
|
</x-dropdown-link>
|
||||||
|
<x-dropdown-link
|
||||||
|
:href="route('servers.logs.remote', ['server' => $server])"
|
||||||
|
:active="request()->routeIs('servers.logs.remote')"
|
||||||
|
>
|
||||||
|
<x-heroicon name="o-document-magnifying-glass" class="h-5 w-5" />
|
||||||
|
<span class="ml-2">{{ __("Remote Logs") }}</span>
|
||||||
|
</x-dropdown-link>
|
||||||
|
</x-slot>
|
||||||
|
</x-dropdown>
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
@ -1,31 +1,54 @@
|
|||||||
@php
|
@php
|
||||||
if (isset($site)) {
|
if (isset($site) && ! isset($remote)) {
|
||||||
$logs = $site
|
$logs = \App\Models\ServerLog::getRemote($site->logs(), false)
|
||||||
->logs()
|
->latest()
|
||||||
|
->paginate(10);
|
||||||
|
} elseif (isset($remote)) {
|
||||||
|
$logs = \App\Models\ServerLog::getRemote($server->logs())
|
||||||
->latest()
|
->latest()
|
||||||
->paginate(10);
|
->paginate(10);
|
||||||
} else {
|
} else {
|
||||||
$logs = $server
|
$logs = \App\Models\ServerLog::getRemote($server->logs(), false)
|
||||||
->logs()
|
|
||||||
->latest()
|
->latest()
|
||||||
->paginate(10);
|
->paginate(10);
|
||||||
}
|
}
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div x-data="">
|
<div x-data="{
|
||||||
|
deleteAction: '',
|
||||||
|
}">
|
||||||
<x-card-header>
|
<x-card-header>
|
||||||
<x-slot name="title">{{ __("Logs") }}</x-slot>
|
<x-slot name="title">
|
||||||
|
{{ $pageTitle ?? "Logs" }}
|
||||||
|
</x-slot>
|
||||||
</x-card-header>
|
</x-card-header>
|
||||||
<x-live id="live-server-logs">
|
<x-live id="live-server-logs">
|
||||||
<x-table>
|
<x-table>
|
||||||
<x-tr>
|
<x-tr>
|
||||||
<x-th>{{ __("Event") }}</x-th>
|
<x-th>
|
||||||
|
@isset($remote)
|
||||||
|
{{ __("Path") }}
|
||||||
|
@else
|
||||||
|
{{ __("Event") }}
|
||||||
|
@endisset
|
||||||
|
</x-th>
|
||||||
<x-th>{{ __("Date") }}</x-th>
|
<x-th>{{ __("Date") }}</x-th>
|
||||||
<x-th></x-th>
|
<x-th></x-th>
|
||||||
</x-tr>
|
</x-tr>
|
||||||
@foreach ($logs as $log)
|
@foreach ($logs as $log)
|
||||||
<x-tr>
|
<x-tr>
|
||||||
<x-td>{{ $log->type }}</x-td>
|
<x-td class="flex flex-col">
|
||||||
|
@isset($remote)
|
||||||
|
{{ $log->name }}
|
||||||
|
@else
|
||||||
|
{{ $log->type }}
|
||||||
|
@if (data_get($log, "type") === "remote")
|
||||||
|
<span class="text-sm text-gray-400">
|
||||||
|
{{ $log->name }}
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
</x-td>
|
||||||
<x-td>
|
<x-td>
|
||||||
<x-datetime :value="$log->created_at" />
|
<x-datetime :value="$log->created_at" />
|
||||||
</x-td>
|
</x-td>
|
||||||
@ -38,6 +61,14 @@
|
|||||||
>
|
>
|
||||||
<x-heroicon name="o-eye" class="h-5 w-5" />
|
<x-heroicon name="o-eye" class="h-5 w-5" />
|
||||||
</x-icon-button>
|
</x-icon-button>
|
||||||
|
|
||||||
|
@if (isset($remote) && ! isset($site))
|
||||||
|
<x-icon-button
|
||||||
|
x-on:click="deleteAction = '{{ route('servers.logs.remote.destroy', ['server' => $server, 'serverLog' => $log->id]) }}'; $dispatch('open-modal', 'delete-remote-log')"
|
||||||
|
>
|
||||||
|
<x-heroicon name="o-trash" class="h-5 w-5" />
|
||||||
|
</x-icon-button>
|
||||||
|
@endif
|
||||||
</x-td>
|
</x-td>
|
||||||
</x-tr>
|
</x-tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -48,6 +79,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</x-live>
|
</x-live>
|
||||||
|
<div id="delete"></div>
|
||||||
<x-modal name="show-log" max-width="4xl">
|
<x-modal name="show-log" max-width="4xl">
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<h2 class="mb-5 text-lg font-medium text-gray-900 dark:text-gray-100">
|
<h2 class="mb-5 text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||||
@ -67,4 +99,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-modal>
|
</x-modal>
|
||||||
|
<x-confirmation-modal
|
||||||
|
name="delete-remote-log"
|
||||||
|
title="Confirm"
|
||||||
|
description="Are you sure that you want to delete this log?"
|
||||||
|
method="delete"
|
||||||
|
x-bind:action="deleteAction"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
6
resources/views/server-logs/remote-logs.blade.php
Normal file
6
resources/views/server-logs/remote-logs.blade.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<x-server-layout :server="$server">
|
||||||
|
@include("server-logs.partials.header")
|
||||||
|
|
||||||
|
@include("server-logs.partials.add-log")
|
||||||
|
@include("server-logs.partials.logs-list-live")
|
||||||
|
</x-server-layout>
|
@ -15,5 +15,5 @@
|
|||||||
@endif
|
@endif
|
||||||
</x-live>
|
</x-live>
|
||||||
|
|
||||||
@include("server-logs.partials.logs-list")
|
@include("server-logs.partials.logs-list-live", ["pageTitle" => "Logs"])
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<x-site-layout :site="$site">
|
<x-site-layout :site="$site">
|
||||||
<x-slot name="pageTitle">{{ __("Logs") }}</x-slot>
|
<x-slot name="pageTitle">{{ $pageTitle }}</x-slot>
|
||||||
|
|
||||||
@include("server-logs.partials.logs-list", ["server" => $site->server, "site" => $site])
|
@include("server-logs.partials.logs-list-live", ["server" => $site->server, "site" => $site])
|
||||||
</x-site-layout>
|
</x-site-layout>
|
||||||
|
@ -11,5 +11,5 @@
|
|||||||
@endif
|
@endif
|
||||||
</x-live>
|
</x-live>
|
||||||
|
|
||||||
@include("server-logs.partials.logs-list", ["server" => $site->server, "site" => $site])
|
@include("server-logs.partials.logs-list-live", ["server" => $site->server, "site" => $site])
|
||||||
</x-site-layout>
|
</x-site-layout>
|
||||||
|
@ -150,6 +150,9 @@
|
|||||||
// logs
|
// logs
|
||||||
Route::prefix('/{server}/logs')->group(function () {
|
Route::prefix('/{server}/logs')->group(function () {
|
||||||
Route::get('/', [ServerLogController::class, 'index'])->name('servers.logs');
|
Route::get('/', [ServerLogController::class, 'index'])->name('servers.logs');
|
||||||
|
Route::get('/remote', [ServerLogController::class, 'remote'])->name('servers.logs.remote');
|
||||||
|
Route::post('/remote', [ServerLogController::class, 'store'])->name('servers.logs.remote.store');
|
||||||
|
Route::delete('/remote/{serverLog}', [ServerLogController::class, 'destroy'])->name('servers.logs.remote.destroy');
|
||||||
Route::get('/{serverLog}', [ServerLogController::class, 'show'])->name('servers.logs.show');
|
Route::get('/{serverLog}', [ServerLogController::class, 'show'])->name('servers.logs.show');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -23,4 +23,37 @@ public function test_see_logs()
|
|||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
->assertSeeText($log->type);
|
->assertSeeText($log->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_see_logs_remote()
|
||||||
|
{
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
|
/** @var ServerLog $log */
|
||||||
|
$log = ServerLog::factory()->create([
|
||||||
|
'server_id' => $this->server->id,
|
||||||
|
'is_remote' => true,
|
||||||
|
'type' => 'remote',
|
||||||
|
'name' => 'see-remote-log',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->get(route('servers.logs.remote', $this->server))
|
||||||
|
->assertSuccessful()
|
||||||
|
->assertSeeText('see-remote-log');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_create_remote_log()
|
||||||
|
{
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
|
$this->post(route('servers.logs.remote.store', [
|
||||||
|
'server' => $this->server->id,
|
||||||
|
]), [
|
||||||
|
'path' => 'test-path',
|
||||||
|
])->assertOk();
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('server_logs', [
|
||||||
|
'is_remote' => true,
|
||||||
|
'name' => 'test-path',
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,6 +282,6 @@ public function test_see_logs(): void
|
|||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
]))
|
]))
|
||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
->assertSee('Logs');
|
->assertSee('Vito Logs');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user