@@ -218,7 +218,7 @@ class Kernel extends ConsoleKernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($service) {
|
if ($service) {
|
||||||
if (str($service->status())->contains('running') === false) {
|
if (str($service->status)->contains('running') === false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,11 +53,7 @@ class ResourcesController extends Controller
|
|||||||
$resources = $resources->flatten();
|
$resources = $resources->flatten();
|
||||||
$resources = $resources->map(function ($resource) {
|
$resources = $resources->map(function ($resource) {
|
||||||
$payload = $resource->toArray();
|
$payload = $resource->toArray();
|
||||||
if ($resource->getMorphClass() === \App\Models\Service::class) {
|
$payload['status'] = $resource->status;
|
||||||
$payload['status'] = $resource->status();
|
|
||||||
} else {
|
|
||||||
$payload['status'] = $resource->status;
|
|
||||||
}
|
|
||||||
$payload['type'] = $resource->type();
|
$payload['type'] = $resource->type();
|
||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
|
|||||||
@@ -154,11 +154,7 @@ class ServersController extends Controller
|
|||||||
'created_at' => $resource->created_at,
|
'created_at' => $resource->created_at,
|
||||||
'updated_at' => $resource->updated_at,
|
'updated_at' => $resource->updated_at,
|
||||||
];
|
];
|
||||||
if ($resource->type() === 'service') {
|
$payload['status'] = $resource->status;
|
||||||
$payload['status'] = $resource->status();
|
|
||||||
} else {
|
|
||||||
$payload['status'] = $resource->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
});
|
});
|
||||||
@@ -237,11 +233,7 @@ class ServersController extends Controller
|
|||||||
'created_at' => $resource->created_at,
|
'created_at' => $resource->created_at,
|
||||||
'updated_at' => $resource->updated_at,
|
'updated_at' => $resource->updated_at,
|
||||||
];
|
];
|
||||||
if ($resource->type() === 'service') {
|
$payload['status'] = $resource->status;
|
||||||
$payload['status'] = $resource->status();
|
|
||||||
} else {
|
|
||||||
$payload['status'] = $resource->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1072,7 +1072,7 @@ class ServicesController extends Controller
|
|||||||
if (! $service) {
|
if (! $service) {
|
||||||
return response()->json(['message' => 'Service not found.'], 404);
|
return response()->json(['message' => 'Service not found.'], 404);
|
||||||
}
|
}
|
||||||
if (str($service->status())->contains('running')) {
|
if (str($service->status)->contains('running')) {
|
||||||
return response()->json(['message' => 'Service is already running.'], 400);
|
return response()->json(['message' => 'Service is already running.'], 400);
|
||||||
}
|
}
|
||||||
StartService::dispatch($service);
|
StartService::dispatch($service);
|
||||||
@@ -1150,7 +1150,7 @@ class ServicesController extends Controller
|
|||||||
if (! $service) {
|
if (! $service) {
|
||||||
return response()->json(['message' => 'Service not found.'], 404);
|
return response()->json(['message' => 'Service not found.'], 404);
|
||||||
}
|
}
|
||||||
if (str($service->status())->contains('stopped') || str($service->status())->contains('exited')) {
|
if (str($service->status)->contains('stopped') || str($service->status)->contains('exited')) {
|
||||||
return response()->json(['message' => 'Service is already stopped.'], 400);
|
return response()->json(['message' => 'Service is already stopped.'], 400);
|
||||||
}
|
}
|
||||||
StopService::dispatch($service);
|
StopService::dispatch($service);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Navbar extends Component
|
|||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
if (str($this->service->status())->contains('running') && is_null($this->service->config_hash)) {
|
if (str($this->service->status)->contains('running') && is_null($this->service->config_hash)) {
|
||||||
$this->service->isConfigurationChanged(true);
|
$this->service->isConfigurationChanged(true);
|
||||||
$this->dispatch('configurationChanged');
|
$this->dispatch('configurationChanged');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,16 +35,26 @@ class SettingsOauth extends Component
|
|||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateOauthSettings()
|
private function updateOauthSettings(?string $provider = null)
|
||||||
{
|
{
|
||||||
foreach (array_values($this->oauth_settings_map) as &$setting) {
|
if ($provider) {
|
||||||
$setting->save();
|
$oauth = $this->oauth_settings_map[$provider];
|
||||||
|
if (! $oauth->couldBeEnabled()) {
|
||||||
|
$oauth->update(['enabled' => false]);
|
||||||
|
throw new \Exception('OAuth settings are not complete for '.$oauth->provider.'.<br/>Please fill in all required fields.');
|
||||||
|
}
|
||||||
|
$oauth->save();
|
||||||
|
$this->dispatch('success', 'OAuth settings for '.$oauth->provider.' updated successfully!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function instantSave()
|
public function instantSave(string $provider)
|
||||||
{
|
{
|
||||||
$this->updateOauthSettings();
|
try {
|
||||||
|
$this->updateOauthSettings($provider);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function submit()
|
public function submit()
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ class OauthSetting extends Model
|
|||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = ['provider', 'client_id', 'client_secret', 'redirect_uri', 'tenant', 'base_url', 'enabled'];
|
||||||
|
|
||||||
protected function clientSecret(): Attribute
|
protected function clientSecret(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
@@ -18,4 +20,16 @@ class OauthSetting extends Model
|
|||||||
set: fn (?string $value) => empty($value) ? null : Crypt::encryptString($value),
|
set: fn (?string $value) => empty($value) ? null : Crypt::encryptString($value),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function couldBeEnabled(): bool
|
||||||
|
{
|
||||||
|
switch ($this->provider) {
|
||||||
|
case 'azure':
|
||||||
|
return filled($this->client_id) && filled($this->client_secret) && filled($this->redirect_uri) && filled($this->tenant);
|
||||||
|
case 'authentik':
|
||||||
|
return filled($this->client_id) && filled($this->client_secret) && filled($this->redirect_uri) && filled($this->base_url);
|
||||||
|
default:
|
||||||
|
return filled($this->client_id) && filled($this->client_secret) && filled($this->redirect_uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Service extends BaseModel
|
|||||||
|
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
protected $appends = ['server_status'];
|
protected $appends = ['server_status', 'status'];
|
||||||
|
|
||||||
protected static function booted()
|
protected static function booted()
|
||||||
{
|
{
|
||||||
@@ -105,12 +105,12 @@ class Service extends BaseModel
|
|||||||
|
|
||||||
public function isRunning()
|
public function isRunning()
|
||||||
{
|
{
|
||||||
return (bool) str($this->status())->contains('running');
|
return (bool) str($this->status)->contains('running');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isExited()
|
public function isExited()
|
||||||
{
|
{
|
||||||
return (bool) str($this->status())->contains('exited');
|
return (bool) str($this->status)->contains('exited');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function type()
|
public function type()
|
||||||
@@ -213,7 +213,7 @@ class Service extends BaseModel
|
|||||||
instant_remote_process(["docker network rm {$uuid}"], $server, false);
|
instant_remote_process(["docker network rm {$uuid}"], $server, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function status()
|
public function getStatusAttribute()
|
||||||
{
|
{
|
||||||
$applications = $this->applications;
|
$applications = $this->applications;
|
||||||
$databases = $this->databases;
|
$databases = $this->databases;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Models\PersonalAccessToken;
|
use App\Models\PersonalAccessToken;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Validation\Rules\Password;
|
use Illuminate\Validation\Rules\Password;
|
||||||
@@ -19,6 +20,9 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
|
Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
|
||||||
|
$event->extendSocialite('authentik', \SocialiteProviders\Authentik\Provider::class);
|
||||||
|
});
|
||||||
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
|
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
|
||||||
|
|
||||||
Password::defaults(function () {
|
Password::defaults(function () {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Services extends Component
|
|||||||
public string $complexStatus = 'exited',
|
public string $complexStatus = 'exited',
|
||||||
public bool $showRefreshButton = true
|
public bool $showRefreshButton = true
|
||||||
) {
|
) {
|
||||||
$this->complexStatus = $service->status();
|
$this->complexStatus = $service->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'coolify' => [
|
'coolify' => [
|
||||||
'version' => '4.0.0-beta.377',
|
'version' => '4.0.0-beta.378',
|
||||||
'self_hosted' => env('SELF_HOSTED', true),
|
'self_hosted' => env('SELF_HOSTED', true),
|
||||||
'autoupdate' => env('AUTOUPDATE'),
|
'autoupdate' => env('AUTOUPDATE'),
|
||||||
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
|
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
|
||||||
|
|||||||
@@ -30,4 +30,19 @@ return [
|
|||||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'azure' => [
|
||||||
|
'client_id' => env('AZURE_CLIENT_ID'),
|
||||||
|
'client_secret' => env('AZURE_CLIENT_SECRET'),
|
||||||
|
'redirect' => env('AZURE_REDIRECT_URI'),
|
||||||
|
'tenant' => env('AZURE_TENANT_ID'),
|
||||||
|
'proxy' => env('AZURE_PROXY'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'authentik' => [
|
||||||
|
'base_url' => env('AUTHENTIK_BASE_URL'),
|
||||||
|
'client_id' => env('AUTHENTIK_CLIENT_ID'),
|
||||||
|
'client_secret' => env('AUTHENTIK_CLIENT_SECRET'),
|
||||||
|
'redirect' => env('AUTHENTIK_REDIRECT_URI'),
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
if (DB::table('instance_settings')->exists()) {
|
||||||
|
$settings = DB::table('instance_settings')->get();
|
||||||
|
foreach ($settings as $setting) {
|
||||||
|
try {
|
||||||
|
DB::table('instance_settings')->where('id', $setting->id)->update([
|
||||||
|
'resend_api_key' => $setting->resend_api_key ? Crypt::encryptString($setting->resend_api_key) : null,
|
||||||
|
]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
\Log::error('Error encrypting resend_api_key: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
if (DB::table('instance_settings')->exists()) {
|
||||||
|
$settings = DB::table('instance_settings')->get();
|
||||||
|
foreach ($settings as $setting) {
|
||||||
|
try {
|
||||||
|
DB::table('instance_settings')->where('id', $setting->id)->update([
|
||||||
|
'resend_api_key' => $setting->resend_api_key ? Crypt::decryptString($setting->resend_api_key) : null,
|
||||||
|
]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
\Log::error('Error decrypting resend_api_key: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.376"
|
"version": "4.0.0-beta.378"
|
||||||
},
|
},
|
||||||
"nightly": {
|
"nightly": {
|
||||||
"version": "4.0.0-beta.377"
|
"version": "4.0.0-beta.379"
|
||||||
},
|
},
|
||||||
"helper": {
|
"helper": {
|
||||||
"version": "1.0.4"
|
"version": "1.0.4"
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
monacoLoader: true,
|
monacoLoader: true,
|
||||||
monacoFontSize: '15px',
|
monacoFontSize: '15px',
|
||||||
monacoId: $id('monaco-editor'),
|
monacoId: $id('monaco-editor'),
|
||||||
|
isDarkMode() {
|
||||||
|
return document.documentElement.classList.contains('dark') || localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||||
|
},
|
||||||
monacoEditor(editor) {
|
monacoEditor(editor) {
|
||||||
editor.onDidChangeModelContent((e) => {
|
editor.onDidChangeModelContent((e) => {
|
||||||
this.monacoContent = editor.getValue();
|
this.monacoContent = editor.getValue();
|
||||||
@@ -41,357 +44,9 @@
|
|||||||
let proxy = URL.createObjectURL(new Blob([` self.MonacoEnvironment = { baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min' }; importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min/vs/base/worker/workerMain.min.js');`], { type: 'text/javascript' }));
|
let proxy = URL.createObjectURL(new Blob([` self.MonacoEnvironment = { baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min' }; importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min/vs/base/worker/workerMain.min.js');`], { type: 'text/javascript' }));
|
||||||
window.MonacoEnvironment = { getWorkerUrl: () => proxy };
|
window.MonacoEnvironment = { getWorkerUrl: () => proxy };
|
||||||
require(['vs/editor/editor.main'], () => {
|
require(['vs/editor/editor.main'], () => {
|
||||||
monaco.editor.defineTheme('blackboard', {
|
|
||||||
'base': 'vs-dark',
|
|
||||||
'inherit': true,
|
|
||||||
'rules': [{
|
|
||||||
'background': editorBackground,
|
|
||||||
'token': ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '959da5',
|
|
||||||
'token': 'comment'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '959da5',
|
|
||||||
'token': 'punctuation.definition.comment'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '959da5',
|
|
||||||
'token': 'string.comment'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'constant'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'entity.name.constant'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'variable.other.constant'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'variable.language'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b392f0',
|
|
||||||
'token': 'entity'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b392f0',
|
|
||||||
'token': 'entity.name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'token': 'variable.parameter.function'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '7bcc72',
|
|
||||||
'token': 'entity.name.tag'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ea4a5a',
|
|
||||||
'token': 'keyword'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ea4a5a',
|
|
||||||
'token': 'storage'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ea4a5a',
|
|
||||||
'token': 'storage.type'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'token': 'storage.modifier.package'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'token': 'storage.modifier.import'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'token': 'storage.type.java'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'punctuation.definition.string'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string punctuation.section.embedded source'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'support'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'meta.property-name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'fb8532',
|
|
||||||
'token': 'variable'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'token': 'variable.other'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'd73a49',
|
|
||||||
'fontStyle': 'bold italic underline',
|
|
||||||
'token': 'invalid.broken'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'd73a49',
|
|
||||||
'fontStyle': 'bold italic underline',
|
|
||||||
'token': 'invalid.deprecated'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'fafbfc',
|
|
||||||
'background': 'd73a49',
|
|
||||||
'fontStyle': 'italic underline',
|
|
||||||
'token': 'invalid.illegal'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'fafbfc',
|
|
||||||
'background': 'd73a49',
|
|
||||||
'fontStyle': 'italic underline',
|
|
||||||
'token': 'carriage-return'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'd73a49',
|
|
||||||
'fontStyle': 'bold italic underline',
|
|
||||||
'token': 'invalid.unimplemented'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'd73a49',
|
|
||||||
'token': 'message.error'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'token': 'string source'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'string variable'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'source.regexp'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string.regexp'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string.regexp.character-class'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string.regexp constant.character.escape'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string.regexp source.ruby.embedded'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'token': 'string.regexp string.regexp.arbitrary-repitition'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '7bcc72',
|
|
||||||
'fontStyle': 'bold',
|
|
||||||
'token': 'string.regexp constant.character.escape'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'support.constant'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'support.variable'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'meta.module-reference'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'fb8532',
|
|
||||||
'token': 'markup.list'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '0366d6',
|
|
||||||
'fontStyle': 'bold',
|
|
||||||
'token': 'markup.heading'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '0366d6',
|
|
||||||
'fontStyle': 'bold',
|
|
||||||
'token': 'markup.heading entity.name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'markup.quote'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'fontStyle': 'italic',
|
|
||||||
'token': 'markup.italic'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'f6f8fa',
|
|
||||||
'fontStyle': 'bold',
|
|
||||||
'token': 'markup.bold'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'markup.raw'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b31d28',
|
|
||||||
'background': 'ffeef0',
|
|
||||||
'token': 'markup.deleted'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b31d28',
|
|
||||||
'background': 'ffeef0',
|
|
||||||
'token': 'meta.diff.header.from-file'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b31d28',
|
|
||||||
'background': 'ffeef0',
|
|
||||||
'token': 'punctuation.definition.deleted'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '176f2c',
|
|
||||||
'background': 'f0fff4',
|
|
||||||
'token': 'markup.inserted'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '176f2c',
|
|
||||||
'background': 'f0fff4',
|
|
||||||
'token': 'meta.diff.header.to-file'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '176f2c',
|
|
||||||
'background': 'f0fff4',
|
|
||||||
'token': 'punctuation.definition.inserted'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b08800',
|
|
||||||
'background': 'fffdef',
|
|
||||||
'token': 'markup.changed'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b08800',
|
|
||||||
'background': 'fffdef',
|
|
||||||
'token': 'punctuation.definition.changed'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '2f363d',
|
|
||||||
'background': '959da5',
|
|
||||||
'token': 'markup.ignored'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '2f363d',
|
|
||||||
'background': '959da5',
|
|
||||||
'token': 'markup.untracked'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'b392f0',
|
|
||||||
'fontStyle': 'bold',
|
|
||||||
'token': 'meta.diff.range'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'c8e1ff',
|
|
||||||
'token': 'meta.diff.header'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '0366d6',
|
|
||||||
'fontStyle': 'bold',
|
|
||||||
'token': 'meta.separator'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '0366d6',
|
|
||||||
'token': 'meta.output'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ffeef0',
|
|
||||||
'token': 'brackethighlighter.tag'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ffeef0',
|
|
||||||
'token': 'brackethighlighter.curly'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ffeef0',
|
|
||||||
'token': 'brackethighlighter.round'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ffeef0',
|
|
||||||
'token': 'brackethighlighter.square'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ffeef0',
|
|
||||||
'token': 'brackethighlighter.angle'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'ffeef0',
|
|
||||||
'token': 'brackethighlighter.quote'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'd73a49',
|
|
||||||
'token': 'brackethighlighter.unmatched'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'd73a49',
|
|
||||||
'token': 'sublimelinter.mark.error'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': 'fb8532',
|
|
||||||
'token': 'sublimelinter.mark.warning'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '6a737d',
|
|
||||||
'token': 'sublimelinter.gutter-mark'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'fontStyle': 'underline',
|
|
||||||
'token': 'constant.other.reference.link'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'foreground': '79b8ff',
|
|
||||||
'fontStyle': 'underline',
|
|
||||||
'token': 'string.other.link'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'colors': {
|
|
||||||
'editor.foreground': '#f6f8fa',
|
|
||||||
'editor.background': editorBackground,
|
|
||||||
'editor.selectionBackground': '#4c2889',
|
|
||||||
'editor.inactiveSelectionBackground': '#444d56',
|
|
||||||
'editor.lineHighlightBackground': '#444d56',
|
|
||||||
'editorCursor.foreground': '#ffffff',
|
|
||||||
'editorWhitespace.foreground': '#6a737d',
|
|
||||||
'editorIndentGuide.background': '#6a737d',
|
|
||||||
'editorIndentGuide.activeBackground': '#f6f8fa',
|
|
||||||
'editor.selectionHighlightBorder': '#444d56'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const editor = monaco.editor.create($refs.monacoEditorElement, {
|
const editor = monaco.editor.create($refs.monacoEditorElement, {
|
||||||
value: monacoContent,
|
value: monacoContent,
|
||||||
theme: editorTheme,
|
theme: document.documentElement.classList.contains('dark') ? 'vs-dark' : 'vs',
|
||||||
wordWrap: 'on',
|
wordWrap: 'on',
|
||||||
readOnly: '{{ $readonly ?? false }}',
|
readOnly: '{{ $readonly ?? false }}',
|
||||||
minimap: { enabled: false },
|
minimap: { enabled: false },
|
||||||
@@ -399,7 +54,20 @@
|
|||||||
lineNumbersMinChars: 3,
|
lineNumbersMinChars: 3,
|
||||||
automaticLayout: true,
|
automaticLayout: true,
|
||||||
language: '{{ $language }}'
|
language: '{{ $language }}'
|
||||||
|
});
|
||||||
|
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
if (mutation.attributeName === 'class') {
|
||||||
|
const isDark = document.documentElement.classList.contains('dark');
|
||||||
|
monaco.editor.setTheme(isDark ? 'vs-dark' : 'vs');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.documentElement, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['class']
|
||||||
});
|
});
|
||||||
|
|
||||||
monacoEditor(editor);
|
monacoEditor(editor);
|
||||||
@@ -411,7 +79,6 @@
|
|||||||
|
|
||||||
updatePlaceholder(editor.getValue());
|
updatePlaceholder(editor.getValue());
|
||||||
|
|
||||||
// Watch for changes in monacoContent from Livewire
|
|
||||||
$watch('monacoContent', value => {
|
$watch('monacoContent', value => {
|
||||||
if (editor.getValue() !== value) {
|
if (editor.getValue() !== value) {
|
||||||
editor.setValue(value);
|
editor.setValue(value);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
@if ($service->isDeployable)
|
@if ($service->isDeployable)
|
||||||
<div class="flex flex-wrap order-first gap-2 items-center sm:order-last">
|
<div class="flex flex-wrap order-first gap-2 items-center sm:order-last">
|
||||||
@if (str($service->status())->contains('running'))
|
@if (str($service->status)->contains('running'))
|
||||||
<x-dropdown>
|
<x-dropdown>
|
||||||
<x-slot:title>
|
<x-slot:title>
|
||||||
Advanced
|
Advanced
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
Stop
|
Stop
|
||||||
</x-slot:button-title>
|
</x-slot:button-title>
|
||||||
</x-modal-confirmation>
|
</x-modal-confirmation>
|
||||||
@elseif (str($service->status())->contains('degraded'))
|
@elseif (str($service->status)->contains('degraded'))
|
||||||
<button @click="$wire.dispatch('startEvent')" class="gap-2 button">
|
<button @click="$wire.dispatch('startEvent')" class="gap-2 button">
|
||||||
<svg class="w-5 h-5 dark:text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-5 h-5 dark:text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
Stop
|
Stop
|
||||||
</x-slot:button-title>
|
</x-slot:button-title>
|
||||||
</x-modal-confirmation>
|
</x-modal-confirmation>
|
||||||
@elseif (str($service->status())->contains('exited'))
|
@elseif (str($service->status)->contains('exited'))
|
||||||
<button wire:click='stop(true)' class="gap-2 button">
|
<button wire:click='stop(true)' class="gap-2 button">
|
||||||
<svg class="w-5 h-5" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-5 h-5" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill="red" d="M26 20h-6v-2h6zm4 8h-6v-2h6zm-2-4h-6v-2h6z" />
|
<path fill="red" d="M26 20h-6v-2h6zm4 8h-6v-2h6zm-2-4h-6v-2h6z" />
|
||||||
@@ -150,8 +150,7 @@
|
|||||||
@else
|
@else
|
||||||
<div class="flex flex-wrap order-first gap-2 items-center sm:order-last">
|
<div class="flex flex-wrap order-first gap-2 items-center sm:order-last">
|
||||||
<div class="text-error">
|
<div class="text-error">
|
||||||
Unable to deploy. <a
|
Unable to deploy. <a class="underline font-bold cursor-pointer"
|
||||||
class="underline font-bold cursor-pointer"
|
|
||||||
@click.prevent="activeTab = 'environment-variables'; window.location.hash = 'environment-variables'">
|
@click.prevent="activeTab = 'environment-variables'; window.location.hash = 'environment-variables'">
|
||||||
Required environment variables missing.</a>
|
Required environment variables missing.</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
<div class="p-4 border dark:border-coolgray-300">
|
<div class="p-4 border dark:border-coolgray-300">
|
||||||
<h3>{{ ucfirst($oauth_setting->provider) }}</h3>
|
<h3>{{ ucfirst($oauth_setting->provider) }}</h3>
|
||||||
<div class="w-32">
|
<div class="w-32">
|
||||||
<x-forms.checkbox instantSave id="oauth_settings_map.{{ $oauth_setting->provider }}.enabled"
|
<x-forms.checkbox instantSave="instantSave('{{ $oauth_setting->provider }}')"
|
||||||
label="Enabled" />
|
id="oauth_settings_map.{{ $oauth_setting->provider }}.enabled" label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||||
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.client_id"
|
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.client_id"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.377"
|
"version": "4.0.0-beta.378"
|
||||||
},
|
},
|
||||||
"nightly": {
|
"nightly": {
|
||||||
"version": "4.0.0-beta.378"
|
"version": "4.0.0-beta.379"
|
||||||
},
|
},
|
||||||
"helper": {
|
"helper": {
|
||||||
"version": "1.0.4"
|
"version": "1.0.4"
|
||||||
|
|||||||
Reference in New Issue
Block a user