admin widget zu dokploy geswitched, viele übersetzungen im Frontend vervollständigt und Anlässe-Seiten mit ChatGPT ausgebaut
This commit is contained in:
@@ -34,16 +34,17 @@ class InfrastructureActionLogResource extends Resource
|
||||
->sortable()
|
||||
->searchable(),
|
||||
Tables\Columns\TextColumn::make('service_id')
|
||||
->label('Service')
|
||||
->label('Target')
|
||||
->searchable()
|
||||
->copyable()
|
||||
->limit(30),
|
||||
Tables\Columns\BadgeColumn::make('action')
|
||||
->label('Action')
|
||||
->colors([
|
||||
'warning' => 'restart',
|
||||
'info' => 'redeploy',
|
||||
'gray' => 'logs',
|
||||
'warning' => fn ($state) => in_array($state, ['compose.redeploy', 'redeploy'], true),
|
||||
'success' => fn ($state) => in_array($state, ['compose.deploy', 'deploy'], true),
|
||||
'danger' => fn ($state) => in_array($state, ['compose.stop', 'stop'], true),
|
||||
'gray' => fn ($state) => $state === 'logs',
|
||||
])
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('status_code')
|
||||
|
||||
@@ -19,7 +19,7 @@ class DokployDeployments extends Page
|
||||
|
||||
protected string $view = 'filament.super-admin.pages.dokploy-deployments';
|
||||
|
||||
public array $applications = [];
|
||||
public array $composes = [];
|
||||
|
||||
public array $recentLogs = [];
|
||||
|
||||
@@ -28,43 +28,45 @@ class DokployDeployments extends Page
|
||||
public function mount(DokployClient $client): void
|
||||
{
|
||||
$this->dokployWebUrl = config('dokploy.web_url');
|
||||
$this->refreshApplications($client);
|
||||
$this->refreshComposes($client);
|
||||
$this->refreshLogs();
|
||||
}
|
||||
|
||||
public function reload(string $applicationId): void
|
||||
public function redeploy(string $composeId): void
|
||||
{
|
||||
$this->performAction($applicationId, 'reload');
|
||||
$this->performAction($composeId, 'redeploy');
|
||||
}
|
||||
|
||||
public function redeploy(string $applicationId): void
|
||||
public function stop(string $composeId): void
|
||||
{
|
||||
$this->performAction($applicationId, 'redeploy');
|
||||
$this->performAction($composeId, 'stop');
|
||||
}
|
||||
|
||||
protected function performAction(string $applicationId, string $action): void
|
||||
protected function performAction(string $composeId, string $action): void
|
||||
{
|
||||
$client = app(DokployClient::class);
|
||||
|
||||
if (! $this->isKnownApplication($applicationId)) {
|
||||
if (! $this->isKnownCompose($composeId)) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title('Unknown service')
|
||||
->body("The application ID {$applicationId} is not configured.")
|
||||
->body("The compose ID {$composeId} is not configured.")
|
||||
->send();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$action === 'reload'
|
||||
? $client->reloadApplication($applicationId, auth()->user())
|
||||
: $client->redeployApplication($applicationId, auth()->user());
|
||||
match ($action) {
|
||||
'redeploy' => $client->redeployCompose($composeId, auth()->user()),
|
||||
'stop' => $client->stopCompose($composeId, auth()->user()),
|
||||
default => throw new \RuntimeException("Unsupported action [{$action}]"),
|
||||
};
|
||||
|
||||
Notification::make()
|
||||
->success()
|
||||
->title(ucfirst($action).' requested')
|
||||
->body("Dokploy accepted the {$action} action for {$applicationId}.")
|
||||
->body("Dokploy accepted the {$action} action for {$composeId}.")
|
||||
->send();
|
||||
} catch (\Throwable $exception) {
|
||||
Notification::make()
|
||||
@@ -74,35 +76,35 @@ class DokployDeployments extends Page
|
||||
->send();
|
||||
}
|
||||
|
||||
$this->refreshApplications($client);
|
||||
$this->refreshComposes($client);
|
||||
$this->refreshLogs();
|
||||
}
|
||||
|
||||
protected function refreshApplications(DokployClient $client): void
|
||||
protected function refreshComposes(DokployClient $client): void
|
||||
{
|
||||
$applicationMap = config('dokploy.applications', []);
|
||||
$composeMap = config('dokploy.composes', []);
|
||||
$results = [];
|
||||
|
||||
foreach ($applicationMap as $label => $id) {
|
||||
foreach ($composeMap as $label => $id) {
|
||||
try {
|
||||
$status = $client->applicationStatus($id);
|
||||
$application = Arr::get($status, 'application', []);
|
||||
$status = $client->composeStatus($id);
|
||||
$compose = Arr::get($status, 'compose', []);
|
||||
|
||||
$results[] = [
|
||||
'label' => ucfirst($label),
|
||||
'application_id' => $id,
|
||||
'status' => Arr::get($application, 'applicationStatus', 'unknown'),
|
||||
'compose_id' => $id,
|
||||
'status' => Arr::get($compose, 'composeStatus', 'unknown'),
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
$results[] = [
|
||||
'label' => ucfirst($label),
|
||||
'application_id' => $id,
|
||||
'compose_id' => $id,
|
||||
'status' => 'error',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->applications = $results;
|
||||
$this->composes = $results;
|
||||
}
|
||||
|
||||
protected function refreshLogs(): void
|
||||
@@ -122,8 +124,8 @@ class DokployDeployments extends Page
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function isKnownApplication(string $applicationId): bool
|
||||
protected function isKnownCompose(string $composeId): bool
|
||||
{
|
||||
return in_array($applicationId, array_values(config('dokploy.applications', [])), true);
|
||||
return in_array($composeId, array_values(config('dokploy.composes', [])), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,49 +15,38 @@ class DokployPlatformHealth extends Widget
|
||||
protected function getViewData(): array
|
||||
{
|
||||
return [
|
||||
'applications' => $this->loadApplications(),
|
||||
'composes' => $this->loadComposes(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function loadApplications(): array
|
||||
protected function loadComposes(): array
|
||||
{
|
||||
$client = app(DokployClient::class);
|
||||
$applicationMap = config('dokploy.applications', []);
|
||||
$composeMap = config('dokploy.composes', []);
|
||||
$results = [];
|
||||
|
||||
foreach ($applicationMap as $label => $applicationId) {
|
||||
foreach ($composeMap as $label => $composeId) {
|
||||
try {
|
||||
$status = $client->applicationStatus($applicationId);
|
||||
$deployments = $client->recentDeployments($applicationId, 1);
|
||||
$application = Arr::get($status, 'application', []);
|
||||
$monitoring = Arr::get($status, 'monitoring', []);
|
||||
$status = $client->composeStatus($composeId);
|
||||
$deployments = $client->composeDeployments($composeId, 1);
|
||||
$compose = Arr::get($status, 'compose', []);
|
||||
$services = $this->formatServices(Arr::get($status, 'services', []));
|
||||
|
||||
$results[] = [
|
||||
'label' => ucfirst($label),
|
||||
'application_id' => $applicationId,
|
||||
'app_name' => Arr::get($application, 'appName') ?? Arr::get($application, 'name'),
|
||||
'status' => Arr::get($application, 'applicationStatus', 'unknown'),
|
||||
'cpu' => $this->extractMetric($monitoring, [
|
||||
'metrics.cpuPercent',
|
||||
'metrics.cpu_percent',
|
||||
'cpuPercent',
|
||||
'cpu_percent',
|
||||
]),
|
||||
'memory' => $this->extractMetric($monitoring, [
|
||||
'metrics.memoryPercent',
|
||||
'metrics.memory_percent',
|
||||
'memoryPercent',
|
||||
'memory_percent',
|
||||
]),
|
||||
'compose_id' => $composeId,
|
||||
'name' => Arr::get($compose, 'name') ?? Arr::get($compose, 'appName') ?? $composeId,
|
||||
'status' => Arr::get($compose, 'composeStatus', 'unknown'),
|
||||
'services' => $services,
|
||||
'last_deploy' => Arr::get($deployments, '0.createdAt')
|
||||
?? Arr::get($deployments, '0.created_at')
|
||||
?? Arr::get($application, 'updatedAt')
|
||||
?? Arr::get($application, 'lastDeploymentAt'),
|
||||
?? Arr::get($compose, 'updatedAt')
|
||||
?? Arr::get($compose, 'lastDeploymentAt'),
|
||||
];
|
||||
} catch (\Throwable $exception) {
|
||||
$results[] = [
|
||||
'label' => ucfirst($label),
|
||||
'application_id' => $applicationId,
|
||||
'compose_id' => $composeId,
|
||||
'status' => 'unreachable',
|
||||
'error' => $exception->getMessage(),
|
||||
];
|
||||
@@ -68,9 +57,9 @@ class DokployPlatformHealth extends Widget
|
||||
return [
|
||||
[
|
||||
'label' => 'Dokploy',
|
||||
'application_id' => '-',
|
||||
'compose_id' => '-',
|
||||
'status' => 'unconfigured',
|
||||
'error' => 'Set DOKPLOY_APPLICATION_IDS in .env to enable monitoring.',
|
||||
'error' => 'Set DOKPLOY_COMPOSE_IDS in .env to enable monitoring.',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -78,14 +67,17 @@ class DokployPlatformHealth extends Widget
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function extractMetric(array $source, array $candidates): mixed
|
||||
protected function formatServices(array $services): array
|
||||
{
|
||||
foreach ($candidates as $key) {
|
||||
if (Arr::has($source, $key)) {
|
||||
return Arr::get($source, $key);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return collect($services)
|
||||
->map(function ($service) {
|
||||
return [
|
||||
'name' => Arr::get($service, 'serviceName') ?? Arr::get($service, 'name') ?? Arr::get($service, 'containerName'),
|
||||
'status' => Arr::get($service, 'status') ?? Arr::get($service, 'state') ?? Arr::get($service, 'composeStatus', 'unknown'),
|
||||
];
|
||||
})
|
||||
->filter(fn ($service) => filled($service['name']))
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Mail\ContactConfirmation;
|
||||
use App\Models\BlogPost;
|
||||
use App\Models\Event;
|
||||
use App\Models\CheckoutSession;
|
||||
use App\Models\Event;
|
||||
use App\Models\Package;
|
||||
use App\Models\PackagePurchase;
|
||||
use App\Models\TenantPackage;
|
||||
@@ -33,6 +33,8 @@ class MarketingController extends Controller
|
||||
{
|
||||
use PresentsPackages;
|
||||
|
||||
private ?MarkdownConverter $markdownConverter = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly CheckoutSessionService $checkoutSessions,
|
||||
private readonly PaddleCheckoutService $paddleCheckout,
|
||||
@@ -292,11 +294,14 @@ class MarketingController extends Controller
|
||||
$posts = $query->orderBy('published_at', 'desc')
|
||||
->paginate(4)
|
||||
->through(function (BlogPost $post) use ($locale) {
|
||||
$excerpt = $post->getTranslation('excerpt', $locale) ?? $post->getTranslation('excerpt', 'de') ?? '';
|
||||
|
||||
return [
|
||||
'id' => $post->id,
|
||||
'slug' => $post->slug,
|
||||
'title' => $post->getTranslation('title', $locale) ?? $post->getTranslation('title', 'de') ?? '',
|
||||
'excerpt' => $post->getTranslation('excerpt', $locale) ?? $post->getTranslation('excerpt', 'de') ?? '',
|
||||
'excerpt' => $excerpt,
|
||||
'excerpt_html' => $this->convertMarkdownToHtml($excerpt),
|
||||
'featured_image' => $post->featured_image ?? $post->banner_url ?? null,
|
||||
'published_at' => optional($post->published_at)->toDateString(),
|
||||
'author' => $post->author ? ['name' => $post->author->name] : null,
|
||||
@@ -310,7 +315,18 @@ class MarketingController extends Controller
|
||||
'first_post_title' => $posts->count() > 0 ? ($posts->first()['title'] ?? 'No title') : 'No posts',
|
||||
]);
|
||||
|
||||
return Inertia::render('marketing/Blog', compact('posts'));
|
||||
$postsArray = $posts->toArray();
|
||||
$postsArray['links'] = array_map(function (array $link) use ($locale) {
|
||||
return [
|
||||
'url' => $link['url'],
|
||||
'label' => $this->localizePaginationLabel($link['label'] ?? '', $locale),
|
||||
'active' => (bool) ($link['active'] ?? false),
|
||||
];
|
||||
}, $postsArray['links'] ?? []);
|
||||
|
||||
return Inertia::render('marketing/Blog', [
|
||||
'posts' => $postsArray,
|
||||
]);
|
||||
}
|
||||
|
||||
public function blogShow(string $locale, string $slug)
|
||||
@@ -330,29 +346,27 @@ class MarketingController extends Controller
|
||||
|
||||
// Transform to array with translated strings for the current locale
|
||||
$markdown = $postModel->getTranslation('content', $locale) ?? $postModel->getTranslation('content', 'de') ?? '';
|
||||
|
||||
$environment = new Environment;
|
||||
$environment->addExtension(new CommonMarkCoreExtension);
|
||||
$environment->addExtension(new TableExtension);
|
||||
$environment->addExtension(new AutolinkExtension);
|
||||
$environment->addExtension(new StrikethroughExtension);
|
||||
$environment->addExtension(new TaskListExtension);
|
||||
|
||||
$converter = new MarkdownConverter($environment);
|
||||
$contentHtml = (string) $converter->convert($markdown);
|
||||
$excerpt = $postModel->getTranslation('excerpt', $locale) ?? $postModel->getTranslation('excerpt', 'de') ?? '';
|
||||
$contentHtml = $this->convertMarkdownToHtml($markdown);
|
||||
[$contentHtmlWithIds, $headings] = $this->decorateHeadings($contentHtml);
|
||||
|
||||
$post = [
|
||||
'id' => $postModel->id,
|
||||
'title' => $postModel->getTranslation('title', $locale) ?? $postModel->getTranslation('title', 'de') ?? '',
|
||||
'excerpt' => $postModel->getTranslation('excerpt', $locale) ?? $postModel->getTranslation('excerpt', 'de') ?? '',
|
||||
'excerpt' => $excerpt,
|
||||
'excerpt_html' => $this->convertMarkdownToHtml($excerpt),
|
||||
'content' => $markdown,
|
||||
'content_html' => $contentHtml,
|
||||
'content_html' => $contentHtmlWithIds,
|
||||
'headings' => $headings,
|
||||
'featured_image' => $postModel->featured_image ?? $postModel->banner_url ?? null,
|
||||
'published_at' => $postModel->published_at->toDateString(),
|
||||
'slug' => $postModel->slug,
|
||||
'url' => route('blog.show', ['locale' => $locale, 'slug' => $postModel->slug], absolute: true),
|
||||
'author' => $postModel->author ? [
|
||||
'name' => $postModel->author->name,
|
||||
] : null,
|
||||
'previous_post' => $this->presentAdjacentPost($postModel, $locale, direction: 'previous'),
|
||||
'next_post' => $this->presentAdjacentPost($postModel, $locale, direction: 'next'),
|
||||
];
|
||||
|
||||
return Inertia::render('marketing/BlogShow', compact('post'));
|
||||
@@ -481,4 +495,119 @@ class MarketingController extends Controller
|
||||
'requestedType' => $normalized,
|
||||
]);
|
||||
}
|
||||
|
||||
private function localizePaginationLabel(?string $label, string $locale): string
|
||||
{
|
||||
$decoded = trim(html_entity_decode(strip_tags($label ?? '')));
|
||||
|
||||
if ($decoded === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($decoded === '...') {
|
||||
return '…';
|
||||
}
|
||||
|
||||
$normalized = Str::lower($decoded);
|
||||
|
||||
if (Str::contains($normalized, ['previous', 'vorherige', 'zurück'])) {
|
||||
return __('marketing.blog.pagination.previous', [], $locale);
|
||||
}
|
||||
|
||||
if (Str::contains($normalized, ['next', 'weiter', 'nächste'])) {
|
||||
return __('marketing.blog.pagination.next', [], $locale);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
private function markdownConverter(): MarkdownConverter
|
||||
{
|
||||
if (! $this->markdownConverter instanceof MarkdownConverter) {
|
||||
$environment = new Environment;
|
||||
$environment->addExtension(new CommonMarkCoreExtension);
|
||||
$environment->addExtension(new TableExtension);
|
||||
$environment->addExtension(new AutolinkExtension);
|
||||
$environment->addExtension(new StrikethroughExtension);
|
||||
$environment->addExtension(new TaskListExtension);
|
||||
|
||||
$this->markdownConverter = new MarkdownConverter($environment);
|
||||
}
|
||||
|
||||
return $this->markdownConverter;
|
||||
}
|
||||
|
||||
private function convertMarkdownToHtml(?string $markdown): string
|
||||
{
|
||||
if ($markdown === null || trim((string) $markdown) === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) $this->markdownConverter()->convert($markdown);
|
||||
}
|
||||
|
||||
private function decorateHeadings(string $html): array
|
||||
{
|
||||
$headings = [];
|
||||
$usedSlugs = [];
|
||||
|
||||
$updatedHtml = preg_replace_callback('/<h([2-3])>(.*?)<\/h\1>/', function ($matches) use (&$headings, &$usedSlugs) {
|
||||
$level = (int) $matches[1];
|
||||
$text = trim(strip_tags($matches[2]));
|
||||
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5);
|
||||
|
||||
if ($text === '') {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$baseSlug = Str::slug($text) ?: 'section';
|
||||
$slug = $baseSlug;
|
||||
$iterator = 1;
|
||||
|
||||
while (in_array($slug, $usedSlugs, true)) {
|
||||
$slug = $baseSlug.'-'.(++$iterator);
|
||||
}
|
||||
|
||||
$usedSlugs[] = $slug;
|
||||
$headings[] = [
|
||||
'text' => $text,
|
||||
'slug' => $slug,
|
||||
'level' => $level,
|
||||
];
|
||||
|
||||
return sprintf('<h%s id="%s">%s</h%s>', $level, $slug, $matches[2], $level);
|
||||
}, $html) ?: $html;
|
||||
|
||||
return [$updatedHtml, $headings];
|
||||
}
|
||||
|
||||
private function presentAdjacentPost(BlogPost $current, string $locale, string $direction): ?array
|
||||
{
|
||||
$operator = $direction === 'previous' ? '<' : '>';
|
||||
$orderDirection = $direction === 'previous' ? 'desc' : 'asc';
|
||||
|
||||
$neighbor = BlogPost::query()
|
||||
->with('author')
|
||||
->whereHas('category', function ($query) {
|
||||
$query->where('slug', 'blog');
|
||||
})
|
||||
->where('is_published', true)
|
||||
->whereNotNull('published_at')
|
||||
->where('published_at', $operator, $current->published_at)
|
||||
->orderBy('published_at', $orderDirection)
|
||||
->first();
|
||||
|
||||
if (! $neighbor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$excerpt = $neighbor->getTranslation('excerpt', $locale) ?? $neighbor->getTranslation('excerpt', 'de') ?? '';
|
||||
|
||||
return [
|
||||
'slug' => $neighbor->slug,
|
||||
'title' => $neighbor->getTranslation('title', $locale) ?? $neighbor->getTranslation('title', 'de') ?? '',
|
||||
'excerpt' => $excerpt,
|
||||
'excerpt_html' => $this->convertMarkdownToHtml($excerpt),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ class DokployClient
|
||||
throw new \RuntimeException('Dokploy application name is required to reload the service.');
|
||||
}
|
||||
|
||||
return $this->dispatchAction(
|
||||
$response = $this->dispatchAction(
|
||||
$applicationId,
|
||||
'reload',
|
||||
[
|
||||
@@ -74,11 +74,15 @@ class DokployClient
|
||||
fn (array $payload) => $this->post('/application.reload', $payload),
|
||||
$actor,
|
||||
);
|
||||
|
||||
$this->forgetApplicationCaches($applicationId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function redeployApplication(string $applicationId, ?Authenticatable $actor = null): array
|
||||
{
|
||||
return $this->dispatchAction(
|
||||
$response = $this->dispatchAction(
|
||||
$applicationId,
|
||||
'redeploy',
|
||||
[
|
||||
@@ -87,6 +91,95 @@ class DokployClient
|
||||
fn (array $payload) => $this->post('/application.redeploy', $payload),
|
||||
$actor,
|
||||
);
|
||||
|
||||
$this->forgetApplicationCaches($applicationId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function composeStatus(string $composeId): array
|
||||
{
|
||||
return $this->cached($this->composeCacheKey($composeId), function () use ($composeId) {
|
||||
$compose = $this->get('/compose.one', [
|
||||
'composeId' => $composeId,
|
||||
]);
|
||||
|
||||
$services = $this->optionalGet('/compose.loadServices', [
|
||||
'composeId' => $composeId,
|
||||
'type' => 'cache',
|
||||
]);
|
||||
|
||||
return [
|
||||
'compose' => $compose,
|
||||
'services' => $services,
|
||||
];
|
||||
}, 30);
|
||||
}
|
||||
|
||||
public function composeDeployments(string $composeId, int $limit = 5): array
|
||||
{
|
||||
return $this->cached($this->composeDeploymentsCacheKey($composeId), function () use ($composeId, $limit) {
|
||||
$deployments = $this->get('/deployment.allByCompose', [
|
||||
'composeId' => $composeId,
|
||||
]);
|
||||
|
||||
if (! is_array($deployments)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_slice($deployments, 0, $limit);
|
||||
}, 60);
|
||||
}
|
||||
|
||||
public function redeployCompose(string $composeId, ?Authenticatable $actor = null): array
|
||||
{
|
||||
$response = $this->dispatchAction(
|
||||
$composeId,
|
||||
'compose.redeploy',
|
||||
[
|
||||
'composeId' => $composeId,
|
||||
],
|
||||
fn (array $payload) => $this->post('/compose.redeploy', $payload),
|
||||
$actor,
|
||||
);
|
||||
|
||||
$this->forgetComposeCaches($composeId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function deployCompose(string $composeId, ?Authenticatable $actor = null): array
|
||||
{
|
||||
$response = $this->dispatchAction(
|
||||
$composeId,
|
||||
'compose.deploy',
|
||||
[
|
||||
'composeId' => $composeId,
|
||||
],
|
||||
fn (array $payload) => $this->post('/compose.deploy', $payload),
|
||||
$actor,
|
||||
);
|
||||
|
||||
$this->forgetComposeCaches($composeId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function stopCompose(string $composeId, ?Authenticatable $actor = null): array
|
||||
{
|
||||
$response = $this->dispatchAction(
|
||||
$composeId,
|
||||
'compose.stop',
|
||||
[
|
||||
'composeId' => $composeId,
|
||||
],
|
||||
fn (array $payload) => $this->post('/compose.stop', $payload),
|
||||
$actor,
|
||||
);
|
||||
|
||||
$this->forgetComposeCaches($composeId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function cached(string $key, callable $callback, int $seconds): mixed
|
||||
@@ -167,7 +260,7 @@ class DokployClient
|
||||
}
|
||||
|
||||
protected function dispatchAction(
|
||||
string $applicationId,
|
||||
string $targetId,
|
||||
string $action,
|
||||
array $payload,
|
||||
callable $callback,
|
||||
@@ -178,22 +271,20 @@ class DokployClient
|
||||
$body = $response->json() ?? [];
|
||||
$status = $response->status();
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logAction($applicationId, $action, $payload, [
|
||||
$this->logAction($targetId, $action, $payload, [
|
||||
'error' => $exception->getMessage(),
|
||||
], null, $actor);
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->logAction($applicationId, $action, $payload, $body, $status, $actor);
|
||||
Cache::forget($this->applicationCacheKey($applicationId));
|
||||
Cache::forget($this->deploymentCacheKey($applicationId));
|
||||
$this->logAction($targetId, $action, $payload, $body, $status, $actor);
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
protected function logAction(
|
||||
string $applicationId,
|
||||
string $targetId,
|
||||
string $action,
|
||||
array $payload,
|
||||
array $response,
|
||||
@@ -202,7 +293,7 @@ class DokployClient
|
||||
): void {
|
||||
InfrastructureActionLog::create([
|
||||
'user_id' => $actor?->getAuthIdentifier() ?? auth()->id(),
|
||||
'service_id' => $applicationId,
|
||||
'service_id' => $targetId,
|
||||
'action' => $action,
|
||||
'payload' => $payload,
|
||||
'response' => $response,
|
||||
@@ -219,4 +310,26 @@ class DokployClient
|
||||
{
|
||||
return "dokploy.deployments.{$applicationId}";
|
||||
}
|
||||
|
||||
protected function composeCacheKey(string $composeId): string
|
||||
{
|
||||
return "dokploy.compose.{$composeId}";
|
||||
}
|
||||
|
||||
protected function composeDeploymentsCacheKey(string $composeId): string
|
||||
{
|
||||
return "dokploy.compose.deployments.{$composeId}";
|
||||
}
|
||||
|
||||
protected function forgetApplicationCaches(string $applicationId): void
|
||||
{
|
||||
Cache::forget($this->applicationCacheKey($applicationId));
|
||||
Cache::forget($this->deploymentCacheKey($applicationId));
|
||||
}
|
||||
|
||||
protected function forgetComposeCaches(string $composeId): void
|
||||
{
|
||||
Cache::forget($this->composeCacheKey($composeId));
|
||||
Cache::forget($this->composeDeploymentsCacheKey($composeId));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user