Compare commits

...

17 Commits

Author SHA1 Message Date
Andras Bacsai
3d87a88d3d Merge pull request #1790 from coollabsio/next
v4.0.0-beta.228
2024-03-01 09:32:19 +01:00
Andras Bacsai
10f9e22a8e fix: do not show n/a networsk 2024-03-01 09:28:14 +01:00
Andras Bacsai
8edda0cdda fix: load unmanaged async 2024-03-01 09:25:27 +01:00
Andras Bacsai
21047afc02 Add new sponsor image 2024-03-01 09:19:23 +01:00
Andras Bacsai
2e9793ffb2 Refactor code for improved performance and readability 2024-02-29 09:21:02 +01:00
Andras Bacsai
fcd100df39 Fix typos and grammatical errors in email templates and form view 2024-02-29 09:16:02 +01:00
Andras Bacsai
dfd564a3a4 Add Supabase logo and update environment variable in compose file 2024-02-29 09:15:06 +01:00
Andras Bacsai
a43c916009 Refactor code and add new fields for Kong service 2024-02-28 13:48:39 +01:00
Andras Bacsai
c8332ca9bf fix: resource tab not loading if server is not reachable 2024-02-28 09:51:45 +01:00
Andras Bacsai
e98170f921 Update Github Sponsors to $40+ 2024-02-28 09:38:59 +01:00
Andras Bacsai
b8f25406cd Refactor code to improve performance and readability 2024-02-27 15:44:19 +01:00
Andras Bacsai
76dcc12b13 Update version numbers to 4.0.0-beta.228 2024-02-27 15:13:30 +01:00
Andras Bacsai
baa2228c9b Merge pull request #1786 from coollabsio/next
v4.0.0-beta.226
2024-02-27 09:10:31 +01:00
Andras Bacsai
5275ae8e9c Refactor getLogs method and update view template 2024-02-27 09:08:15 +01:00
Andras Bacsai
c71e1e107e Refactor getLogs method and update get-logs.blade.php view 2024-02-27 09:05:28 +01:00
Andras Bacsai
8ab72c7e10 feat: preview deployment logs 2024-02-27 09:01:19 +01:00
Andras Bacsai
a8970df91b Update class names in controllers 2024-02-27 08:03:42 +01:00
31 changed files with 1463 additions and 84 deletions

View File

@@ -33,7 +33,9 @@ Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="cccareers logo" width="200"/></a>
<a href="https://appwrite.io" target="_blank"><img src="./other/logos/appwrite.svg" alt="appwrite logo" width="200"/></a>
## Github Sponsors ($15+)
## Github Sponsors ($40+)
<a href="https://cryptojobslist.com/?utm_source=coolify.io"><img src="https://github.com/cryptojobslist.png" width="60px" alt="CryptoJobsList" /></a>
<a href="https://typebot.io/?utm_source=coolify.io"><img src="https://pbs.twimg.com/profile_images/1509194008366657543/9I-C7uWT_400x400.jpg" width="60px" alt="typebot"/></a>
<a href="https://bc.direct"><img width="60px" alt="BC Direct" src="https://github.com/coollabsio/coolify/assets/5845193/a4063c41-95ed-4a32-8814-cd1475572e37"/></a>
<a href="https://github.com/automazeio"><img src="https://github.com/automazeio.png" width="60px" alt="Corentin Clichy" /></a>
<a href="https://github.com/corentinclichy"><img src="https://github.com/corentinclichy.png" width="60px" alt="Corentin Clichy" /></a>

View File

@@ -16,7 +16,7 @@ class StartService
$commands[] = "cd " . $service->workdir();
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
$commands[] = "echo 'Creating Docker network.'";
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid >/dev/null 2>&1 || true";
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
$commands[] = "echo Starting service.";
$commands[] = "echo 'Pulling images.'";
$commands[] = "docker compose pull";

View File

@@ -14,7 +14,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Visus\Cuid2\Cuid2;
class APIDeploy extends Controller
class Deploy extends Controller
{
public function deploy(Request $request)
{

View File

@@ -6,7 +6,7 @@ use App\Http\Controllers\Controller;
use App\Models\Project as ModelsProject;
use Illuminate\Http\Request;
class APIProject extends Controller
class Project extends Controller
{
public function projects(Request $request)
{

View File

@@ -6,7 +6,7 @@ use App\Http\Controllers\Controller;
use App\Models\Server as ModelsServer;
use Illuminate\Http\Request;
class APIServer extends Controller
class Server extends Controller
{
public function servers(Request $request)
{

View File

@@ -10,7 +10,8 @@ use Livewire\Component;
class Create extends Component
{
public $type;
public function mount() {
public function mount()
{
$services = getServiceTemplates();
$type = str(request()->query('type'));
$destination_uuid = request()->query('destination');
@@ -70,7 +71,7 @@ class Create extends Component
$generatedValue = $value;
if ($value->contains('SERVICE_')) {
$command = $value->after('SERVICE_')->beforeLast('_');
$generatedValue = generateEnvValue($command->value());
$generatedValue = generateEnvValue($command->value(), $service);
}
EnvironmentVariable::create([
'key' => $key,

View File

@@ -23,6 +23,7 @@ class GetLogs extends Component
public ServiceApplication|ServiceDatabase|null $servicesubtype = null;
public Server $server;
public ?string $container = null;
public ?string $pull_request = null;
public ?bool $streamLogs = false;
public ?bool $showTimeStamps = true;
public int $numberOfLines = 100;
@@ -70,7 +71,14 @@ class GetLogs extends Component
}
public function getLogs($refresh = false)
{
if (!$refresh && $this->resource?->getMorphClass() === 'App\Models\Service') return;
if ($this->resource?->getMorphClass() === 'App\Models\Application') {
if (str($this->container)->contains('-pr-')) {
$this->pull_request = "Pull Request: " . str($this->container)->afterLast('-pr-')->beforeLast('_')->value();
} else {
$this->pull_request = 'branch';
}
}
if (!$refresh && ($this->resource?->getMorphClass() === 'App\Models\Service' || str($this->container)->contains('-pr-'))) return;
if ($this->container) {
if ($this->showTimeStamps) {
if ($this->server->isSwarm()) {

View File

@@ -41,13 +41,19 @@ class Logs extends Component
]
]);
} else {
$containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id, 0);
$containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id, includePullrequests: true);
}
if ($containers->count() > 0) {
$containers->each(function ($container) {
$this->containers->push(str_replace('/', '', $container['Names']));
});
}
$this->containers = $this->containers->sortByDesc(function ($container) {
if (str_contains($container, '-pr-')) {
return explode('-pr-', $container)[1];
}
return $container;
});
} else if (data_get($this->parameters, 'database_uuid')) {
$this->type = 'database';
$resource = StandalonePostgresql::where('uuid', $this->parameters['database_uuid'])->first();
@@ -70,21 +76,15 @@ class Logs extends Component
$this->status = $this->resource->status;
$this->server = $this->resource->destination->server;
$this->container = $this->resource->uuid;
// if (str(data_get($this, 'resource.status'))->startsWith('running')) {
$this->containers->push($this->container);
// }
$this->containers->push($this->container);
} else if (data_get($this->parameters, 'service_uuid')) {
$this->type = 'service';
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
$this->resource->applications()->get()->each(function ($application) {
// if (str(data_get($application, 'status'))->contains('running')) {
$this->containers->push(data_get($application, 'name') . '-' . data_get($this->resource, 'uuid'));
// }
$this->containers->push(data_get($application, 'name') . '-' . data_get($this->resource, 'uuid'));
});
$this->resource->databases()->get()->each(function ($database) {
// if (str(data_get($database, 'status'))->contains('running')) {
$this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid'));
// }
$this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid'));
});
$this->server = $this->resource->server;

View File

@@ -55,7 +55,7 @@ class Resources extends Component
} catch (\Throwable $e) {
return handleError($e, $this);
}
$this->loadUnmanagedContainers();
// $this->loadUnmanagedContainers();
}
public function render()
{

View File

@@ -2,7 +2,7 @@
namespace App\Livewire\Tags;
use App\Http\Controllers\Api\APIDeploy as Deploy;
use App\Http\Controllers\Api\Deploy;
use App\Models\ApplicationDeploymentQueue;
use App\Models\Tag;
use Livewire\Component;

View File

@@ -263,17 +263,19 @@ class Server extends BaseModel
}
public function loadUnmanagedContainers()
{
$containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this);
$containers = format_docker_command_output_to_json($containers);
$containers = $containers->map(function ($container) {
$labels = data_get($container, 'Labels');
if (!str($labels)->contains("coolify.managed")) {
return $container;
}
return null;
});
$containers = $containers->filter();
return collect($containers);
if ($this->isFunctional()) {
$containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this);
$containers = format_docker_command_output_to_json($containers);
$containers = $containers->map(function ($container) {
$labels = data_get($container, 'Labels');
if (!str($labels)->contains("coolify.managed")) {
return $container;
}
return null;
});
$containers = $containers->filter();
return collect($containers);
}
}
public function hasDefinedResources()
{

View File

@@ -102,6 +102,30 @@ class Service extends BaseModel
foreach ($applications as $application) {
$image = str($application->image)->before(':')->value();
switch ($image) {
case str($image)?->contains('kong'):
$data = collect([]);
$dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first();
$dashboard_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
if ($dashboard_user) {
$data = $data->merge([
'Dashboard User' => [
'key' => data_get($dashboard_user, 'key'),
'value' => data_get($dashboard_user, 'value'),
'rules' => 'required',
],
]);
}
if ($dashboard_password) {
$data = $data->merge([
'Dashboard Password' => [
'key' => data_get($dashboard_password, 'key'),
'value' => data_get($dashboard_password, 'value'),
'rules' => 'required',
'isPassword' => true,
],
]);
}
$fields->put('Supabase', $data->toArray());
case str($image)?->contains('minio'):
$data = collect([]);
$console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first();

View File

@@ -8,18 +8,21 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Spatie\Url\Url;
function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null): Collection
function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null, ?bool $includePullrequests = false): Collection
{
$containers = collect([]);
if (!$server->isSwarm()) {
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}' "], $server);
$containers = format_docker_command_output_to_json($containers);
$containers = $containers->map(function ($container) use ($pullRequestId) {
$containers = $containers->map(function ($container) use ($pullRequestId, $includePullrequests) {
$labels = data_get($container, 'Labels');
if (!str($labels)->contains("coolify.pullRequestId=")) {
data_set($container, 'Labels', $labels . ",coolify.pullRequestId={$pullRequestId}");
return $container;
}
if ($includePullrequests) {
return $container;
}
if (str($labels)->contains("coolify.pullRequestId=$pullRequestId")) {
return $container;
}

View File

@@ -33,6 +33,11 @@ use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;
use Lcobucci\JWT\Encoding\ChainedFormatter;
use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Token\Builder;
use Poliander\Cron\CronExpression;
use Visus\Cuid2\Cuid2;
use phpseclib3\Crypt\RSA;
@@ -625,7 +630,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
}
$definedNetwork = collect([$resource->uuid]);
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource) {
$serviceVolumes = collect(data_get($service, 'volumes', []));
$servicePorts = collect(data_get($service, 'ports', []));
@@ -927,6 +931,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$savedService->fqdn = $fqdn;
$savedService->save();
}
EnvironmentVariable::create([
'key' => $key,
'value' => $fqdn,
'is_build_time' => false,
'service_id' => $resource->id,
'is_preview' => false,
]);
}
// data_forget($service, "environment.$variableName");
// $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName");
@@ -978,7 +989,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
}
} else {
$generatedValue = generateEnvValue($command);
$generatedValue = generateEnvValue($command, $resource);
if (!$foundEnv) {
EnvironmentVariable::create([
'key' => $key,
@@ -1394,7 +1405,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
]);
}
} else {
$generatedValue = generateEnvValue($command);
$generatedValue = generateEnvValue($command, $service);
if (!$foundEnv) {
EnvironmentVariable::create([
'key' => $key,
@@ -1570,7 +1581,7 @@ function parseEnvVariable(Str|string $value)
'port' => $port,
];
}
function generateEnvValue(string $command)
function generateEnvValue(string $command, Service $service)
{
switch ($command) {
case 'PASSWORD':
@@ -1591,6 +1602,46 @@ function generateEnvValue(string $command)
case 'USER':
$generatedValue = Str::random(16);
break;
case 'SUPABASEANON':
$signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first();
if (is_null($signingKey)) {
return;
} else {
$signingKey = $signingKey->value;
}
$key = InMemory::plainText($signingKey);
$algorithm = new Sha256();
$tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default()));
$now = new DateTimeImmutable();
$now = $now->setTime($now->format('H'), $now->format('i'));
$token = $tokenBuilder
->issuedBy('supabase')
->issuedAt($now)
->expiresAt($now->modify('+100 year'))
->withClaim('role', 'anon')
->getToken($algorithm, $key);
$generatedValue = $token->toString();
break;
case 'SUPABASESERVICE':
$signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first();
if (is_null($signingKey)) {
return;
} else {
$signingKey = $signingKey->value;
}
$key = InMemory::plainText($signingKey);
$algorithm = new Sha256();
$tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default()));
$now = new DateTimeImmutable();
$now = $now->setTime($now->format('H'), $now->format('i'));
$token = $tokenBuilder
->issuedBy('supabase')
->issuedAt($now)
->expiresAt($now->modify('+100 year'))
->withClaim('role', 'service_role')
->getToken($algorithm, $key);
$generatedValue = $token->toString();
break;
default:
$generatedValue = Str::random(16);
break;

View File

@@ -7,7 +7,7 @@ return [
// 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.226',
'release' => '4.0.0-beta.228',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),

View File

@@ -1,3 +1,3 @@
<?php
return '4.0.0-beta.226';
return '4.0.0-beta.228';

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="white" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14m-6 6l6-6m-6-6l6 6"/>
</svg>

After

Width:  |  Height:  |  Size: 203 B

15
public/svgs/supabase.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg width="109" height="113" viewBox="0 0 109 113" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M63.7076 110.284C60.8481 113.885 55.0502 111.912 54.9813 107.314L53.9738 40.0627L99.1935 40.0627C107.384 40.0627 111.952 49.5228 106.859 55.9374L63.7076 110.284Z" fill="url(#paint0_linear)"/>
<path d="M63.7076 110.284C60.8481 113.885 55.0502 111.912 54.9813 107.314L53.9738 40.0627L99.1935 40.0627C107.384 40.0627 111.952 49.5228 106.859 55.9374L63.7076 110.284Z" fill="url(#paint1_linear)" fill-opacity="0.2"/>
<path d="M45.317 2.07103C48.1765 -1.53037 53.9745 0.442937 54.0434 5.041L54.4849 72.2922H9.83113C1.64038 72.2922 -2.92775 62.8321 2.1655 56.4175L45.317 2.07103Z" fill="#3ECF8E"/>
<defs>
<linearGradient id="paint0_linear" x1="53.9738" y1="54.974" x2="94.1635" y2="71.8295" gradientUnits="userSpaceOnUse">
<stop stop-color="#249361"/>
<stop offset="1" stop-color="#3ECF8E"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="36.1558" y1="30.578" x2="54.4844" y2="65.0806" gradientUnits="userSpaceOnUse">
<stop/>
<stop offset="1" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<img class="inline-flex w-4 h-4" src="{{ asset('svgs/internal-link.svg') }}">

View File

@@ -1,5 +1,5 @@
<x-emails.layout>
Your trial ends soon. Please update payment details [here]({{ $stripeCustomerPortal }}),
Your servers & deployed resources will be untouched, but you won't be able to deploy new resources and lost all automations and integrations.
Your servers & deployed resources will be untouched, but you won't be able to deploy new resources and lose all automations and integrations.
</x-emails.layout>

View File

@@ -16,7 +16,6 @@
<button class="text-white btn-link">{{ data_get($docker, 'network') }} </button>
</a>
@empty
<div class="">N/A</div>
@endforelse
@forelse ($server->swarmDockers as $docker)
<a
@@ -24,7 +23,6 @@
<button class="text-white btn-link">{{ data_get($docker, 'network') }} </button>
</a>
@empty
<div class="">N/A</div>
@endforelse
</div>
<div class="pt-2">

View File

@@ -86,15 +86,21 @@
Redeploy
@endif
</x-forms.button>
<x-forms.button class="bg-coolgray-500"
wire:click="stop({{ data_get($preview, 'pull_request_id') }})">Remove Preview
</x-forms.button>
<a
href="{{ route('project.application.deployment.index', [...$parameters, 'pull_request_id' => data_get($preview, 'pull_request_id')]) }}">
<x-forms.button class="bg-coolgray-500">
Get Deployment Logs
Deployment Logs
</x-forms.button>
</a>
<a
href="{{ route('project.application.logs', [...$parameters, 'pull_request_id' => data_get($preview, 'pull_request_id')]) }}">
<x-forms.button class="bg-coolgray-500">
Application Logs
</x-forms.button>
</a>
<x-forms.button isError class="bg-coolgray-500"
wire:click="stop({{ data_get($preview, 'pull_request_id') }})">Delete
</x-forms.button>
</div>
</div>
@endforeach

View File

@@ -50,7 +50,7 @@
<template x-for="item in filteredApplications" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col w-full px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -66,8 +66,8 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="description break-all" x-text="item.fqdn"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.fqdn"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
@@ -83,7 +83,7 @@
<template x-for="item in filteredPostgresqls" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -99,7 +99,7 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
@@ -115,7 +115,7 @@
<template x-for="item in filteredRedis" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -131,7 +131,7 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
@@ -147,7 +147,7 @@
<template x-for="item in filteredMongodbs" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -163,7 +163,7 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
@@ -179,7 +179,7 @@
<template x-for="item in filteredMysqls" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -195,7 +195,7 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
@@ -211,7 +211,7 @@
<template x-for="item in filteredMariadbs" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -227,7 +227,7 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
@@ -243,7 +243,7 @@
<template x-for="item in filteredServices" :key="item.id">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<div class="flex flex-col mx-6">
<div class="flex flex-col px-4 mx-2">
<div class="flex gap-2">
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
<template x-if="item.status.startsWith('running')">
@@ -259,7 +259,7 @@
<div title="degraded" class="mt-1 bg-warning badge badge-xs"></div>
</template>
</div>
<div class="description" x-text="item.description"></div>
<div class="max-w-full truncate description" x-text="item.description"></div>
</div>
</a>
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">

View File

@@ -1,23 +1,26 @@
<div>
<div x-init="$wire.getLogs">
<div class="flex gap-2">
<h4>Container: {{ $container }}</h4>
<div x-init="$wire.getLogs" id="screen" x-data="{ fullscreen: false, alwaysScroll: false, intervalId: null }">
<div class="flex items-center gap-2">
<h3>{{ str($container)->beforeLast('-')->headline() }}</h3>
@if ($pull_request)
<div>({{ $pull_request }})</div>
@endif
@if ($streamLogs)
<span wire:poll.2000ms='getLogs(true)' class="loading loading-xs text-warning loading-spinner"></span>
@endif
</div>
<div class="flex gap-2">
<form wire:submit='getLogs(true)' class="flex items-end gap-2 pt-2 ">
<div class="w-96">
<x-forms.input label="Only Show Number of Lines" placeholder="1000" required
id="numberOfLines"></x-forms.input>
</div>
<x-forms.button type="submit">Refresh</x-forms.button>
<x-forms.checkbox instantSave label="Stream Logs" id="streamLogs"></x-forms.checkbox>
<x-forms.checkbox instantSave label="Include Timestamps" id="showTimeStamps"></x-forms.checkbox>
</div>
<form wire:submit='getLogs(true)' class="flex items-end gap-2">
<x-forms.input label="Only Show Number of Lines" placeholder="1000" required
id="numberOfLines"></x-forms.input>
<x-forms.button type="submit">Refresh</x-forms.button>
</form>
<div id="screen" x-data="{ fullscreen: false, alwaysScroll: false, intervalId: null }" :class="fullscreen ? 'fullscreen' : 'w-full py-4 mx-auto'">
<div class="relative flex flex-col-reverse w-full p-4 pt-6 overflow-y-auto text-white bg-coolgray-100 scrollbar border-coolgray-300"
:class="fullscreen ? '' : 'max-h-[40rem] border border-solid rounded'">
<div :class="fullscreen ? 'fullscreen' : 'relative w-full py-4 mx-auto'">
<div class="flex flex-col-reverse w-full px-4 py-2 overflow-y-auto text-white bg-coolgray-100 scrollbar border-coolgray-300"
:class="fullscreen ? '' : 'max-h-96 border border-solid rounded'">
<button title="Minimize" x-show="fullscreen" class="fixed top-4 right-4"
x-on:click="makeFullscreen"><svg class="icon" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
@@ -36,8 +39,8 @@
stroke-width="2" d="M12 5v14m4-4l-4 4m-4-4l4 4" />
</svg></button>
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-2 right-2"
x-on:click="makeFullscreen"><svg class=" icon" viewBox="0 0 24 24"
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-6 right-4"
x-on:click="makeFullscreen"><svg class="icon" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<g fill="none">
<path
@@ -46,7 +49,11 @@
d="M9.793 12.793a1 1 0 0 1 1.497 1.32l-.083.094L6.414 19H9a1 1 0 0 1 .117 1.993L9 21H4a1 1 0 0 1-.993-.883L3 20v-5a1 1 0 0 1 1.993-.117L5 15v2.586l4.793-4.793ZM20 3a1 1 0 0 1 .993.883L21 4v5a1 1 0 0 1-1.993.117L19 9V6.414l-4.793 4.793a1 1 0 0 1-1.497-1.32l.083-.094L17.586 5H15a1 1 0 0 1-.117-1.993L15 3h5Z" />
</g>
</svg></button>
<pre id="logs" class="font-mono whitespace-pre-wrap">{{ $outputs }}</pre>
@if ($outputs)
<pre id="logs" class="font-mono whitespace-pre-wrap">{{ $outputs }}</pre>
@else
<pre id="logs" class="font-mono whitespace-pre-wrap">Refresh to get the logs...</pre>
@endif
</div>
</div>
<script>

View File

@@ -4,7 +4,7 @@
<h2>General</h2>
@if ($server->id === 0)
<x-new-modal buttonTitle="Save" title="Change Localhost" action="submit">
You could lost a lot of functionalities if you change the server details of the server where Coolify
You could lose a lot of functionalities if you change the server details of the server where Coolify
is
running on.<br>Please think again.
</x-new-modal>

View File

@@ -45,7 +45,7 @@
{{ data_get($resource, 'environment.name') }}
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap"><a class=""
href="{{ $resource->link() }}">{{ $resource->name }} </a>
href="{{ $resource->link() }}">{{ $resource->name }} <x-internal-link/></a>
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">
{{ str($resource->type())->headline() }}</td>
@@ -68,7 +68,7 @@
</div>
</div>
<div x-cloak x-show="activeTab === 'unmanaged'" class="h-full">
<div class="flex flex-col">
<div class="flex flex-col" x-init="$wire.loadUnmanagedContainers()">
<div class="flex gap-2">
<h2>Resources</h2>
<x-forms.button wire:click="refreshStatus">Refresh</x-forms.button>

View File

@@ -1,8 +1,8 @@
<?php
use App\Http\Controllers\Api\APIDeploy as Deploy;
use App\Http\Controllers\Api\APIProject as Project;
use App\Http\Controllers\Api\APIServer as Server;
use App\Http\Controllers\Api\Deploy;
use App\Http\Controllers\Api\Project;
use App\Http\Controllers\Api\Server;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;

View File

@@ -1,5 +1,5 @@
#!/bin/bash
## Do not modify this file. You will lost the ability to autoupdate!
## Do not modify this file. You will lose the ability to autoupdate!
VERSION="1.0.4"
CDN="https://cdn.coollabs.io/coolify"

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
"version": "3.12.36"
},
"v4": {
"version": "4.0.0-beta.226"
"version": "4.0.0-beta.228"
}
}
}