commit
d05ffe32a3
23
app/Actions/Server/CleanupDocker.php
Normal file
23
app/Actions/Server/CleanupDocker.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Server;
|
||||
|
||||
class CleanupDocker
|
||||
{
|
||||
use AsAction;
|
||||
public function handle(Server $server, bool $force = true)
|
||||
{
|
||||
if ($force) {
|
||||
instant_remote_process(['docker image prune -af'], $server, false);
|
||||
instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false);
|
||||
instant_remote_process(['docker builder prune -af'], $server, false);
|
||||
} else {
|
||||
instant_remote_process(['docker image prune -f'], $server, false);
|
||||
instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false);
|
||||
instant_remote_process(['docker builder prune -f'], $server, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ public function handle(bool $force)
|
||||
if (!$this->server) {
|
||||
return;
|
||||
}
|
||||
CleanupDocker::run($this->server, false);
|
||||
$this->latestVersion = get_latest_version_of_coolify();
|
||||
$this->currentVersion = config('version');
|
||||
ray('latest version:' . $this->latestVersion . " current version: " . $this->currentVersion . ' force: ' . $force);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\DeleteResourceJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
@ -91,7 +92,7 @@ private function deleteApplication()
|
||||
if (!$confirmed) {
|
||||
break;
|
||||
}
|
||||
$toDelete->delete();
|
||||
DeleteResourceJob::dispatch($toDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,7 +116,7 @@ private function deleteDatabase()
|
||||
if (!$confirmed) {
|
||||
return;
|
||||
}
|
||||
$toDelete->delete();
|
||||
DeleteResourceJob::dispatch($toDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,7 +140,7 @@ private function deleteService()
|
||||
if (!$confirmed) {
|
||||
return;
|
||||
}
|
||||
$toDelete->delete();
|
||||
DeleteResourceJob::dispatch($toDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ private function check_resources($schedule)
|
||||
}
|
||||
}
|
||||
foreach ($servers as $server) {
|
||||
$schedule->job(new ServerStatusJob($server))->everyTenMinutes()->onOneServer();
|
||||
$schedule->job(new ServerStatusJob($server))->everyFiveMinutes()->onOneServer();
|
||||
}
|
||||
}
|
||||
private function instance_auto_update($schedule)
|
||||
|
@ -203,7 +203,7 @@ public function handle(): void
|
||||
dispatch(new ContainerStatusJob($this->server));
|
||||
}
|
||||
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
||||
$this->application->isConfigurationChanged(true);
|
||||
$this->application->isConfigurationChanged(false);
|
||||
return;
|
||||
} else if ($this->application->dockerfile) {
|
||||
$this->deploy_simple_dockerfile();
|
||||
@ -738,13 +738,15 @@ private function deploy_pull_request()
|
||||
$this->generate_nixpacks_confs();
|
||||
}
|
||||
$this->generate_compose_file();
|
||||
|
||||
// Needs separate preview variables
|
||||
$this->generate_build_env_variables();
|
||||
$this->add_build_env_variables_to_dockerfile();
|
||||
if ($this->application->build_pack !== 'nixpacks') {
|
||||
$this->add_build_env_variables_to_dockerfile();
|
||||
}
|
||||
$this->build_image();
|
||||
$this->stop_running_container();
|
||||
if ($this->application->destination->server->isSwarm()) {
|
||||
ray("{$this->workdir}{$this->docker_compose_location}");
|
||||
$this->push_to_docker_registry();
|
||||
$this->execute_remote_command(
|
||||
[
|
||||
@ -911,10 +913,7 @@ private function generate_nixpacks_confs()
|
||||
if ($this->nixpacks_plan) {
|
||||
$parsed = Toml::Parse($this->nixpacks_plan);
|
||||
// Do any modifications here
|
||||
// $cmds = collect(data_get($parsed, 'phases.setup.cmds', []));
|
||||
$this->generate_env_variables();
|
||||
// data_set($parsed, 'phases.setup.cmds', $cmds);
|
||||
ray($this->env_args->toArray());
|
||||
$merged_envs = $this->env_args->merge(collect(data_get($parsed, 'variables', [])));
|
||||
data_set($parsed, 'variables', $merged_envs->toArray());
|
||||
$this->nixpacks_plan = json_encode($parsed, JSON_PRETTY_PRINT);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Actions\Server\CleanupDocker;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
@ -43,9 +44,7 @@ public function handle(): void
|
||||
ray('Usage before: ' . $this->usageBefore);
|
||||
if ($this->usageBefore >= $this->server->settings->cleanup_after_percentage) {
|
||||
ray('Cleaning up ' . $this->server->name);
|
||||
instant_remote_process(['docker image prune -af'], $this->server, false);
|
||||
instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $this->server, false);
|
||||
instant_remote_process(['docker builder prune -af'], $this->server, false);
|
||||
CleanupDocker::run($this->server);
|
||||
$usageAfter = $this->server->getDiskUsage();
|
||||
if ($usageAfter < $this->usageBefore) {
|
||||
ray('Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $this->server->name);
|
||||
|
@ -108,7 +108,7 @@ public function handle(): void
|
||||
'message' => $this->task_output ?? $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage());
|
||||
// send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,15 @@ class Index extends Component
|
||||
{
|
||||
public Project $project;
|
||||
public Environment $environment;
|
||||
public function mount () {
|
||||
public $applications = [];
|
||||
public $postgresqls = [];
|
||||
public $redis = [];
|
||||
public $mongodbs = [];
|
||||
public $mysqls = [];
|
||||
public $mariadbs = [];
|
||||
public $services = [];
|
||||
public function mount()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
@ -21,6 +29,84 @@ public function mount () {
|
||||
}
|
||||
$this->project = $project;
|
||||
$this->environment = $environment;
|
||||
$this->applications = $environment->applications->sortBy('name');
|
||||
$this->applications = $this->applications->map(function ($application) {
|
||||
if (data_get($application, 'environment.project.uuid')) {
|
||||
$application->hrefLink = route('project.application.configuration', [
|
||||
'project_uuid' => data_get($application, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($application, 'environment.name'),
|
||||
'application_uuid' => data_get($application, 'uuid')
|
||||
]);
|
||||
}
|
||||
return $application;
|
||||
});
|
||||
$this->postgresqls = $environment->postgresqls->sortBy('name');
|
||||
$this->postgresqls = $this->postgresqls->map(function ($postgresql) {
|
||||
if (data_get($postgresql, 'environment.project.uuid')) {
|
||||
$postgresql->hrefLink = route('project.database.configuration', [
|
||||
'project_uuid' => data_get($postgresql, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($postgresql, 'environment.name'),
|
||||
'database_uuid' => data_get($postgresql, 'uuid')
|
||||
]);
|
||||
}
|
||||
return $postgresql;
|
||||
});
|
||||
$this->redis = $environment->redis->sortBy('name');
|
||||
$this->redis = $this->redis->map(function ($redis) {
|
||||
if (data_get($redis, 'environment.project.uuid')) {
|
||||
$redis->hrefLink = route('project.database.configuration', [
|
||||
'project_uuid' => data_get($redis, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($redis, 'environment.name'),
|
||||
'database_uuid' => data_get($redis, 'uuid')
|
||||
]);
|
||||
}
|
||||
return $redis;
|
||||
});
|
||||
$this->mongodbs = $environment->mongodbs->sortBy('name');
|
||||
$this->mongodbs = $this->mongodbs->map(function ($mongodb) {
|
||||
if (data_get($mongodb, 'environment.project.uuid')) {
|
||||
$mongodb->hrefLink = route('project.database.configuration', [
|
||||
'project_uuid' => data_get($mongodb, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($mongodb, 'environment.name'),
|
||||
'database_uuid' => data_get($mongodb, 'uuid')
|
||||
]);
|
||||
}
|
||||
return $mongodb;
|
||||
});
|
||||
$this->mysqls = $environment->mysqls->sortBy('name');
|
||||
$this->mysqls = $this->mysqls->map(function ($mysql) {
|
||||
if (data_get($mysql, 'environment.project.uuid')) {
|
||||
$mysql->hrefLink = route('project.database.configuration', [
|
||||
'project_uuid' => data_get($mysql, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($mysql, 'environment.name'),
|
||||
'database_uuid' => data_get($mysql, 'uuid')
|
||||
]);
|
||||
}
|
||||
return $mysql;
|
||||
});
|
||||
$this->mariadbs = $environment->mariadbs->sortBy('name');
|
||||
$this->mariadbs = $this->mariadbs->map(function ($mariadb) {
|
||||
if (data_get($mariadb, 'environment.project.uuid')) {
|
||||
$mariadb->hrefLink = route('project.database.configuration', [
|
||||
'project_uuid' => data_get($mariadb, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($mariadb, 'environment.name'),
|
||||
'database_uuid' => data_get($mariadb, 'uuid')
|
||||
]);
|
||||
}
|
||||
return $mariadb;
|
||||
});
|
||||
$this->services = $environment->services->sortBy('name');
|
||||
$this->services = $this->services->map(function ($service) {
|
||||
if (data_get($service, 'environment.project.uuid')) {
|
||||
$service->hrefLink = route('project.service.configuration', [
|
||||
'project_uuid' => data_get($service, 'environment.project.uuid'),
|
||||
'environment_name' => data_get($service, 'environment.name'),
|
||||
'service_uuid' => data_get($service, 'uuid')
|
||||
]);
|
||||
$service->status = serviceStatus($service);
|
||||
}
|
||||
return $service;
|
||||
});
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
|
@ -108,8 +108,7 @@ public function runCommand()
|
||||
$this->validate();
|
||||
try {
|
||||
// Wrap command to prevent escaped execution in the host.
|
||||
$cmd = 'sh -c "' . str_replace('"', '\"', $this->command) . '"';
|
||||
|
||||
$cmd = 'sh -c "if [ -f ~/.profile ]; then . ~/.profile; fi; ' . str_replace('"', '\"', $this->command) . '"';
|
||||
if (!empty($this->workDir)) {
|
||||
$exec = "docker exec -w {$this->workDir} {$this->container} {$cmd}";
|
||||
} else {
|
||||
|
@ -126,7 +126,7 @@ function generateSshCommand(Server $server, string $command, bool $isMux = true)
|
||||
if (data_get($server, 'settings.is_cloudflare_tunnel')) {
|
||||
$ssh_command .= '-o ProxyCommand="/usr/local/bin/cloudflared access ssh --hostname %h" ';
|
||||
}
|
||||
$command = "PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin && $command";
|
||||
$command = "test -f ~/.profile && . ~/.profile; PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin && $command";
|
||||
$ssh_command .= "-i {$privateKeyLocation} "
|
||||
. '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '
|
||||
. '-o PasswordAuthentication=no '
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.188',
|
||||
'release' => '4.0.0-beta.189',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.188';
|
||||
return '4.0.0-beta.189';
|
||||
|
@ -80,7 +80,7 @@ .box-without-bg {
|
||||
}
|
||||
|
||||
.description {
|
||||
@apply pt-2 text-xs font-bold text-neutral-500 group-hover:text-white;
|
||||
@apply text-xs font-bold text-neutral-500 group-hover:text-white;
|
||||
}
|
||||
|
||||
.lds-heart {
|
||||
|
@ -1,12 +0,0 @@
|
||||
<x-layout>
|
||||
<h1>Command Center</h1>
|
||||
<div class="subtitle">Execute commands on your servers without leaving the browser.</div>
|
||||
@if ($servers->count() > 0)
|
||||
<livewire:run-command :servers="$servers" />
|
||||
@else
|
||||
<div>
|
||||
<div>No servers found. Without a server, you won't be able to do much.</div>
|
||||
<x-use-magic-bar link="/server/new" />
|
||||
</div>
|
||||
@endif
|
||||
</x-layout>
|
@ -44,54 +44,216 @@ class="font-normal text-white normal-case border-none rounded hover:no-underline
|
||||
<a href="{{ route('project.resource.create', ['project_uuid' => request()->route('project_uuid'), 'environment_name' => request()->route('environment_name')]) }} "
|
||||
class="items-center justify-center box">+ Add New Resource</a>
|
||||
@endif
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@foreach ($environment->applications->sortBy('name') as $application)
|
||||
<a class="relative box group"
|
||||
href="{{ route('project.application.configuration', [$project->uuid, $environment->name, $application->uuid]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">{{ $application->name }}</div>
|
||||
<div class="description">{{ $application->description }}</div>
|
||||
</div>
|
||||
@if (Str::of(data_get($application, 'status'))->startsWith('running'))
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
@elseif (Str::of(data_get($application, 'status'))->startsWith('exited'))
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
@elseif (Str::of(data_get($application, 'status'))->startsWith('restarting'))
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
@endif
|
||||
</a>
|
||||
@endforeach
|
||||
@foreach ($environment->databases()->sortBy('name') as $database)
|
||||
<a class="relative box group"
|
||||
href="{{ route('project.database.configuration', [$project->uuid, $environment->name, $database->uuid]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">{{ $database->name }}</div>
|
||||
<div class="description">{{ $database->description }}</div>
|
||||
</div>
|
||||
@if (Str::of(data_get($database, 'status'))->startsWith('running'))
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
@elseif (Str::of(data_get($database, 'status'))->startsWith('exited'))
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
@elseif (Str::of(data_get($database, 'status'))->startsWith('restaring'))
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
@endif
|
||||
</a>
|
||||
@endforeach
|
||||
@foreach ($environment->services->sortBy('name') as $service)
|
||||
<a class="relative box group"
|
||||
href="{{ route('project.service.configuration', [$project->uuid, $environment->name, $service->uuid]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">{{ $service->name }}</div>
|
||||
<div class="description">{{ $service->description }}</div>
|
||||
</div>
|
||||
@if (Str::of(serviceStatus($service))->startsWith('running'))
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
@elseif (Str::of(serviceStatus($service))->startsWith('degraded'))
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
@elseif (Str::of(serviceStatus($service))->startsWith('exited'))
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
@endif
|
||||
</a>
|
||||
@endforeach
|
||||
<div x-data="searchComponent()">
|
||||
<x-forms.input placeholder="Search for name, fqdn..." class="w-full" x-model="search" />
|
||||
<div class="grid gap-2 pt-4 lg:grid-cols-2">
|
||||
<template x-for="item in filteredApplications" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
<div class="description" x-text="item.fqdn"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
<template x-for="item in filteredPostgresqls" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
<template x-for="item in filteredRedis" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
<template x-for="item in filteredMongodbs" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
<template x-for="item in filteredMysqls" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
<template x-for="item in filteredMariadbs" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
<template x-for="item in filteredServices" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('degraded')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function searchComponent() {
|
||||
return {
|
||||
search: '',
|
||||
applications: @js($applications),
|
||||
postgresqls: @js($postgresqls),
|
||||
redis: @js($redis),
|
||||
mongodbs: @js($mongodbs),
|
||||
mysqls: @js($mysqls),
|
||||
mariadbs: @js($mariadbs),
|
||||
services: @js($services),
|
||||
get filteredApplications() {
|
||||
if (this.search === '') {
|
||||
return this.applications;
|
||||
}
|
||||
this.applications = Object.values(this.applications);
|
||||
return this.applications.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.fqdn?.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
get filteredPostgresqls() {
|
||||
if (this.search === '') {
|
||||
return this.postgresqls;
|
||||
}
|
||||
this.postgresqls = Object.values(this.postgresqls);
|
||||
return this.postgresqls.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
get filteredRedis() {
|
||||
if (this.search === '') {
|
||||
return this.redis;
|
||||
}
|
||||
this.redis = Object.values(this.redis);
|
||||
return this.redis.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
get filteredMongodbs() {
|
||||
if (this.search === '') {
|
||||
return this.mongodbs;
|
||||
}
|
||||
this.mongodbs = Object.values(this.mongodbs);
|
||||
return this.mongodbs.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
get filteredMysqls() {
|
||||
if (this.search === '') {
|
||||
return this.mysqls;
|
||||
}
|
||||
this.mysqls = Object.values(this.mysqls);
|
||||
return this.mysqls.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
get filteredMariadbs() {
|
||||
if (this.search === '') {
|
||||
return this.mariadbs;
|
||||
}
|
||||
this.mariadbs = Object.values(this.mariadbs);
|
||||
return this.mariadbs.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
get filteredServices() {
|
||||
if (this.search === '') {
|
||||
return this.services;
|
||||
}
|
||||
this.services = Object.values(this.services);
|
||||
return this.services.filter(item => {
|
||||
return item.name.toLowerCase().includes(this.search.toLowerCase()) ||
|
||||
item.description?.toLowerCase().includes(this.search.toLowerCase());
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
@ -1,83 +0,0 @@
|
||||
<x-layout>
|
||||
<h1>Profile</h1>
|
||||
<div class="subtitle ">Your user profile settings.</div>
|
||||
<livewire:profile.form :request="$request" />
|
||||
<h2 class="py-4">Subscription</h2>
|
||||
<a href="{{ route('team.index') }}">Check in Team Settings</a>
|
||||
<h2 class="py-4">Two-factor Authentication</h2>
|
||||
@if (session('status') == 'two-factor-authentication-enabled')
|
||||
<div class="mb-4 font-medium">
|
||||
Please finish configuring two factor authentication below. Read the QR code or enter the secret key
|
||||
manually.
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<form action="/user/confirmed-two-factor-authentication" method="POST" class="flex items-end gap-2">
|
||||
@csrf
|
||||
<x-forms.input type="number" id="code" label="One-time code" required />
|
||||
<x-forms.button type="submit">Validate 2FA</x-forms.button>
|
||||
</form>
|
||||
<div>
|
||||
<div>{!! $request->user()->twoFactorQrCodeSvg() !!}</div>
|
||||
<div x-data="{ showCode: false }" class="py-2">
|
||||
<template x-if="showCode">
|
||||
<div class="py-2 ">{!! decrypt($request->user()->two_factor_secret) !!}</div>
|
||||
</template>
|
||||
<x-forms.button x-on:click="showCode = !showCode">Show secret key to manually
|
||||
enter</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@elseif(session('status') == 'two-factor-authentication-confirmed')
|
||||
<div class="mb-4 ">
|
||||
Two factor authentication confirmed and enabled successfully.
|
||||
</div>
|
||||
<div>
|
||||
<div class="pb-6 ">Here are the recovery codes for your account. Please store them in a secure
|
||||
location.
|
||||
</div>
|
||||
<div class="text-white">
|
||||
@foreach ($request->user()->recoveryCodes() as $code)
|
||||
<div>{{ $code }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
@if ($request->user()->two_factor_confirmed_at)
|
||||
<div class="pb-4 "> Two factor authentication is <span class="text-helper">enabled</span>.</div>
|
||||
<div class="flex gap-2">
|
||||
<form action="/user/two-factor-authentication" method="POST">
|
||||
@csrf
|
||||
@method ('DELETE')
|
||||
<x-forms.button type="submit">Disable</x-forms.button>
|
||||
</form>
|
||||
<form action="/user/two-factor-recovery-codes" method="POST">
|
||||
@csrf
|
||||
<x-forms.button type="submit">Regenerate Recovery Codes</x-forms.button>
|
||||
</form>
|
||||
</div>
|
||||
@if (session('status') == 'recovery-codes-generated')
|
||||
<div>
|
||||
<div class="py-6 ">Here are the recovery codes for your account. Please store them in a
|
||||
secure
|
||||
location.
|
||||
</div>
|
||||
<div class="text-white">
|
||||
@foreach ($request->user()->recoveryCodes() as $code)
|
||||
<div>{{ $code }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<form action="/user/two-factor-authentication" method="POST">
|
||||
@csrf
|
||||
<x-forms.button type="submit">Configure 2FA</x-forms.button>
|
||||
</form>
|
||||
@endif
|
||||
@endif
|
||||
@if (session()->has('errors'))
|
||||
<div class="text-error">
|
||||
Something went wrong. Please try again.
|
||||
</div>
|
||||
@endif
|
||||
</x-layout>
|
@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.188"
|
||||
"version": "4.0.0-beta.189"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user