Merge branch 'next' into feat/deployment-token
This commit is contained in:
@@ -4,11 +4,9 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
|
||||
|
||||
html,
|
||||
body {
|
||||
@apply h-full bg-neutral-50 text-neutral-800 dark:bg-base dark:text-neutral-400;
|
||||
@apply h-full bg-neutral-50 text-neutral-800 dark:bg-base dark:text-neutral-400 w-full;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -32,6 +30,14 @@ body {
|
||||
@apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300;
|
||||
}
|
||||
|
||||
.input-sticky {
|
||||
@apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 dark:focus:ring-coolgray-300 focus:ring-neutral-400 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset;
|
||||
}
|
||||
|
||||
.input-sticky-active {
|
||||
@apply border-2 border-coollabs text-black dark:text-white focus:bg-neutral-200 dark:focus:bg-coolgray-400 focus:border-coollabs;
|
||||
}
|
||||
|
||||
/* Readonly */
|
||||
.input {
|
||||
@apply dark:read-only:text-neutral-500 dark:read-only:ring-0 dark:read-only:bg-coolgray-100/40 placeholder:text-neutral-300 dark:placeholder:text-neutral-700 read-only:text-neutral-500 read-only:bg-neutral-200;
|
||||
@@ -172,10 +178,6 @@ section {
|
||||
@apply bg-error;
|
||||
}
|
||||
|
||||
/* [type='checkbox']:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
} */
|
||||
|
||||
.menu {
|
||||
@apply flex items-center gap-1;
|
||||
}
|
||||
@@ -197,7 +199,7 @@ section {
|
||||
}
|
||||
|
||||
.scrollbar {
|
||||
@apply scrollbar-thumb-coollabs-100 dark:scrollbar-track-coolgray-200 scrollbar-track-neutral-200 scrollbar-w-2;
|
||||
@apply scrollbar-thumb-coollabs-100 dark:scrollbar-track-coolgray-200 scrollbar-track-neutral-200 scrollbar-thin;
|
||||
}
|
||||
|
||||
.main {
|
||||
@@ -320,4 +322,4 @@ section {
|
||||
|
||||
.dz-button {
|
||||
@apply w-full p-4 py-10 my-4 font-bold bg-white border dark:border-coolgray-400 dark:text-white dark:bg-transparent hover:dark:bg-coolgray-400;
|
||||
}
|
||||
}
|
||||
32
resources/js/bootstrap.js
vendored
32
resources/js/bootstrap.js
vendored
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
|
||||
// import axios from 'axios';
|
||||
// window.axios = axios;
|
||||
|
||||
// window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo';
|
||||
|
||||
// import Pusher from 'pusher-js';
|
||||
// window.Pusher = Pusher;
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: import.meta.env.VITE_PUSHER_APP_KEY,
|
||||
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
|
||||
// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
|
||||
// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
|
||||
// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
|
||||
// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
|
||||
// enabledTransports: ['ws', 'wss'],
|
||||
// });
|
||||
@@ -60,7 +60,22 @@ export function initializeTerminalComponent() {
|
||||
};
|
||||
|
||||
},
|
||||
resetTerminal() {
|
||||
if (this.term) {
|
||||
this.$wire.dispatch('error', 'Terminal websocket connection lost.');
|
||||
this.term.reset();
|
||||
this.term.clear();
|
||||
this.pendingWrites = 0;
|
||||
this.paused = false;
|
||||
this.commandBuffer = '';
|
||||
|
||||
// Force a refresh
|
||||
this.$nextTick(() => {
|
||||
this.resizeTerminal();
|
||||
this.term.focus();
|
||||
});
|
||||
}
|
||||
},
|
||||
setupTerminal() {
|
||||
const terminalElement = document.getElementById('terminal');
|
||||
if (terminalElement) {
|
||||
@@ -69,9 +84,15 @@ export function initializeTerminalComponent() {
|
||||
rows: 30,
|
||||
fontFamily: '"Fira Code", courier-new, courier, monospace, "Powerline Extra Symbols"',
|
||||
cursorBlink: true,
|
||||
rendererType: 'canvas',
|
||||
convertEol: true,
|
||||
disableStdin: false
|
||||
});
|
||||
this.fitAddon = new FitAddon();
|
||||
this.term.loadAddon(this.fitAddon);
|
||||
this.$nextTick(() => {
|
||||
this.resizeTerminal();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -101,12 +122,19 @@ export function initializeTerminalComponent() {
|
||||
`${connectionString.protocol}://${connectionString.host}${connectionString.port}${connectionString.path}`
|
||||
this.socket = new WebSocket(url);
|
||||
|
||||
this.socket.onopen = () => {
|
||||
console.log('[Terminal] WebSocket connection established. Cool cool cool cool cool cool.');
|
||||
};
|
||||
|
||||
this.socket.onmessage = this.handleSocketMessage.bind(this);
|
||||
this.socket.onerror = (e) => {
|
||||
console.error('WebSocket error:', e);
|
||||
console.error('[Terminal] WebSocket error.');
|
||||
};
|
||||
this.socket.onclose = () => {
|
||||
console.log('WebSocket connection closed');
|
||||
console.warn('[Terminal] WebSocket connection closed.');
|
||||
this.resetTerminal();
|
||||
this.message = '(connection closed)';
|
||||
this.terminalActive = false;
|
||||
this.reconnect();
|
||||
};
|
||||
}
|
||||
@@ -117,19 +145,18 @@ export function initializeTerminalComponent() {
|
||||
clearInterval(this.reconnectInterval);
|
||||
}
|
||||
this.reconnectInterval = setInterval(() => {
|
||||
console.log('Attempting to reconnect...');
|
||||
console.warn('[Terminal] Attempting to reconnect...');
|
||||
this.initializeWebSocket();
|
||||
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
||||
console.log('Reconnected successfully');
|
||||
console.log('[Terminal] Reconnected successfully');
|
||||
clearInterval(this.reconnectInterval);
|
||||
this.reconnectInterval = null;
|
||||
window.location.reload();
|
||||
|
||||
}
|
||||
}, 2000);
|
||||
},
|
||||
|
||||
handleSocketMessage(event) {
|
||||
this.message = '(connection closed)';
|
||||
if (event.data === 'pty-ready') {
|
||||
if (!this.term._initialized) {
|
||||
this.term.open(document.getElementById('terminal'));
|
||||
@@ -150,8 +177,17 @@ export function initializeTerminalComponent() {
|
||||
this.term.reset();
|
||||
this.commandBuffer = '';
|
||||
} else {
|
||||
this.pendingWrites++;
|
||||
this.term.write(event.data, this.flowControlCallback.bind(this));
|
||||
try {
|
||||
this.pendingWrites++;
|
||||
this.term.write(event.data, (err) => {
|
||||
if (err) {
|
||||
console.error('[Terminal] Write error:', err);
|
||||
}
|
||||
this.flowControlCallback();
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Terminal] Write operation failed:', error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -173,11 +209,15 @@ export function initializeTerminalComponent() {
|
||||
if (!this.term) return;
|
||||
|
||||
this.term.onData((data) => {
|
||||
this.socket.send(JSON.stringify({ message: data }));
|
||||
if (data === '\r') {
|
||||
this.commandBuffer = '';
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
this.socket.send(JSON.stringify({ message: data }));
|
||||
if (data === '\r') {
|
||||
this.commandBuffer = '';
|
||||
} else {
|
||||
this.commandBuffer += data;
|
||||
}
|
||||
} else {
|
||||
this.commandBuffer += data;
|
||||
console.warn('[Terminal] WebSocket not ready, data not sent');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
@else
|
||||
<div>Transactional emails are not active on this instance.</div>
|
||||
<div>See how to set it in our <a class="dark:text-white" target="_blank"
|
||||
href="{{ config('constants.docs.base_url') }}">docs</a>, or how to
|
||||
href="{{ config('constants.urls.docs') }}">docs</a>, or how to
|
||||
manually reset password.
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -5,18 +5,20 @@
|
||||
'disabled' => false,
|
||||
'instantSave' => false,
|
||||
'value' => null,
|
||||
'domValue' => null,
|
||||
'checked' => false,
|
||||
'hideLabel' => false,
|
||||
'fullWidth' => false,
|
||||
])
|
||||
|
||||
<div @class([
|
||||
'flex flex-row items-center gap-4 px-2 py-1 form-control min-w-fit dark:hover:bg-coolgray-100',
|
||||
'flex flex-row items-center gap-4 pr-2 py-1 form-control min-w-fit dark:hover:bg-coolgray-100',
|
||||
'w-full' => $fullWidth,
|
||||
])>
|
||||
@if (!$hideLabel)
|
||||
<label @class(['flex gap-4 px-0 min-w-fit label', 'opacity-40' => $disabled])>
|
||||
<span class="flex gap-2">
|
||||
<label @class([
|
||||
'flex gap-4 items-center px-0 min-w-fit label w-full cursor-pointer',
|
||||
])>
|
||||
<span class="flex flex-grow gap-2">
|
||||
@if ($label)
|
||||
{!! $label !!}
|
||||
@else
|
||||
@@ -26,12 +28,12 @@
|
||||
<x-helper :helper="$helper" />
|
||||
@endif
|
||||
</span>
|
||||
</label>
|
||||
@endif
|
||||
<span class="flex-grow"></span>
|
||||
<input @disabled($disabled) type="checkbox" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@if ($instantSave) wire:loading.attr="disabled" wire:click='{{ $instantSave === 'instantSave' || $instantSave == '1' ? 'instantSave' : $instantSave }}'
|
||||
wire:model="{{ $id }}" @else wire:model="{{ $value ?? $id }}" @endif
|
||||
@if ($domValue) value="{{ $domValue }}" @endif
|
||||
/>
|
||||
@if ($checked) checked @endif
|
||||
wire:model={{ $id }} @else wire:model={{ $value ?? $id }} @endif />
|
||||
@if (!$hideLabel)
|
||||
</label>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
$disableTwoStepConfirmation = data_get(InstanceSettings::get(), 'disable_two_step_confirmation');
|
||||
@endphp
|
||||
|
||||
<div x-data="{
|
||||
<div wire:ignore x-data="{
|
||||
modalOpen: false,
|
||||
step: {{ empty($checkboxes) ? 2 : 1 }},
|
||||
initialStep: {{ empty($checkboxes) ? 2 : 1 }},
|
||||
@@ -106,8 +106,8 @@
|
||||
this.selectedActions.push(id);
|
||||
}
|
||||
}
|
||||
}" @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }"
|
||||
class="relative w-auto h-auto">
|
||||
}" @keydown.escape.window="modalOpen = false; resetModal()"
|
||||
:class="{ 'z-40': modalOpen }" class="relative w-auto h-auto">
|
||||
@if ($customButton)
|
||||
@if ($buttonFullWidth)
|
||||
<x-forms.button @click="modalOpen=true" class="w-full">
|
||||
@@ -302,7 +302,8 @@
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<x-forms.button
|
||||
x-bind:disabled="!disableTwoStepConfirmation && confirmWithText && userConfirmationText !== confirmationText"
|
||||
x-bind:disabled="!disableTwoStepConfirmation && confirmWithText && userConfirmationText !==
|
||||
confirmationText"
|
||||
class="w-auto" isError
|
||||
@click="
|
||||
if (dispatchEvent) {
|
||||
@@ -337,11 +338,14 @@
|
||||
Your Password
|
||||
</label>
|
||||
<form @submit.prevent="false" @keydown.enter.prevent>
|
||||
<input type="text" name="username" autocomplete="username" value="{{ auth()->user()->email }}" style="display: none;">
|
||||
<input type="password" id="password-confirm-{{ $passwordConfirm }}" x-model="password"
|
||||
class="w-full input" placeholder="Enter your password" autocomplete="current-password">
|
||||
<input type="text" name="username" autocomplete="username"
|
||||
value="{{ auth()->user()->email }}" style="display: none;">
|
||||
<input type="password" id="password-confirm-{{ $passwordConfirm }}"
|
||||
x-model="password" class="w-full input" placeholder="Enter your password"
|
||||
autocomplete="current-password">
|
||||
</form>
|
||||
<p x-show="passwordError" x-text="passwordError" class="mt-1 text-sm text-red-500"></p>
|
||||
<p x-show="passwordError" x-text="passwordError" class="mt-1 text-sm text-red-500">
|
||||
</p>
|
||||
@error('password')
|
||||
<p class="mt-1 text-sm text-red-500">{{ $message }}</p>
|
||||
@enderror
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
'action' => 'delete',
|
||||
'content' => null,
|
||||
'closeOutside' => true,
|
||||
'minWidth' => '36rem',
|
||||
])
|
||||
<div x-data="{ modalOpen: false }" :class="{ 'z-40': modalOpen }" @keydown.window.escape="modalOpen=false"
|
||||
class="relative w-auto h-auto">
|
||||
class="relative w-auto h-auto" wire:ignore>
|
||||
@if ($content)
|
||||
<div @click="modalOpen=true">
|
||||
{{ $content }}
|
||||
@@ -27,7 +28,7 @@
|
||||
@endif
|
||||
<template x-teleport="body">
|
||||
<div x-show="modalOpen"
|
||||
class="fixed top-0 left-0 lg:px-0 px-4 z-[99] flex items-center justify-center w-screen h-screen" x-cloak>
|
||||
class="fixed top-0 left-0 lg:px-0 px-4 z-[99] flex items-center justify-center w-screen h-screen">
|
||||
<div x-show="modalOpen" x-transition:enter="ease-out duration-100" x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-100"
|
||||
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
|
||||
@@ -40,7 +41,7 @@
|
||||
x-transition:leave="ease-in duration-100"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="relative w-full py-6 border rounded drop-shadow min-w-full lg:min-w-[36rem] max-w-fit bg-white border-neutral-200 dark:bg-base px-6 dark:border-coolgray-300">
|
||||
class="relative w-full py-6 border rounded drop-shadow min-w-full lg:min-w-[{{ $minWidth }}] max-w-fit bg-white border-neutral-200 dark:bg-base px-6 dark:border-coolgray-300">
|
||||
<div class="flex items-center justify-between pb-3">
|
||||
<h3 class="text-2xl font-bold">{{ $title }}</h3>
|
||||
<button @click="modalOpen=false"
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
}
|
||||
window.location.reload();
|
||||
},
|
||||
setZoom(zoom) {
|
||||
localStorage.setItem('zoom', zoom);
|
||||
window.location.reload();
|
||||
},
|
||||
init() {
|
||||
this.full = localStorage.getItem('pageWidth');
|
||||
this.zoom = localStorage.getItem('zoom');
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
|
||||
const userSettings = localStorage.getItem('theme');
|
||||
if (userSettings !== 'system') {
|
||||
@@ -21,6 +26,7 @@
|
||||
}
|
||||
});
|
||||
this.queryTheme();
|
||||
this.checkZoom();
|
||||
},
|
||||
setTheme(type) {
|
||||
this.theme = type;
|
||||
@@ -44,6 +50,30 @@
|
||||
this.theme = 'system';
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
},
|
||||
checkZoom() {
|
||||
if (this.zoom === null) {
|
||||
this.setZoom(100);
|
||||
}
|
||||
if (this.zoom === '90') {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
html {
|
||||
font-size: 93.75%;
|
||||
}
|
||||
|
||||
:root {
|
||||
--vh: 1vh;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
html {
|
||||
font-size: 87.5%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
}">
|
||||
<div class="flex pt-6 pb-4 pl-2">
|
||||
@@ -69,7 +99,7 @@
|
||||
</div>
|
||||
</x-slot:title>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="mb-1 font-bold border-b dark:border-coolgray-500 dark:text-white text-md">Color</div>
|
||||
<div class="font-bold border-b dark:border-coolgray-500 dark:text-white text-md">Color</div>
|
||||
<button @click="setTheme('dark')" class="px-1 dropdown-item-no-padding">Dark</button>
|
||||
<button @click="setTheme('light')" class="px-1 dropdown-item-no-padding">Light</button>
|
||||
<button @click="setTheme('system')" class="px-1 dropdown-item-no-padding">System</button>
|
||||
@@ -78,6 +108,9 @@
|
||||
x-show="full === 'full'">Center</button>
|
||||
<button @click="switchWidth()" class="px-1 dropdown-item-no-padding"
|
||||
x-show="full === 'center'">Full</button>
|
||||
<div class="my-1 font-bold border-b dark:border-coolgray-500 dark:text-white text-md">Zoom</div>
|
||||
<button @click="setZoom(100)" class="px-1 dropdown-item-no-padding">100%</button>
|
||||
<button @click="setZoom(90)" class="px-1 dropdown-item-no-padding">90%</button>
|
||||
</div>
|
||||
</x-dropdown>
|
||||
</div>
|
||||
@@ -148,7 +181,7 @@
|
||||
<li>
|
||||
<a title="Destinations"
|
||||
class="{{ request()->is('destination*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('destination.index') }}" wire:navigate>
|
||||
href="{{ route('destination.index') }}">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
@@ -163,8 +196,8 @@
|
||||
class="{{ request()->is('storages*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('storage.index') }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2">
|
||||
<path d="M4 6a8 3 0 1 0 16 0A8 3 0 1 0 4 6" />
|
||||
<path d="M4 6v6a8 3 0 0 0 16 0V6" />
|
||||
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
|
||||
@@ -215,7 +248,7 @@
|
||||
<li>
|
||||
<a title="Tags"
|
||||
class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||
href="{{ route('tags.index') }}">
|
||||
href="{{ route('tags.show') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2">
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
href="{{ route('notifications.discord') }}">
|
||||
<button>Discord</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('notifications.slack') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('notifications.slack') }}">
|
||||
<button>Slack</button>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -262,7 +262,7 @@
|
||||
your self-hosted instance?
|
||||
<x-forms.button>
|
||||
<a class="font-bold dark:text-white hover:no-underline"
|
||||
href="{{ config('coolify.contact') }}">Contact
|
||||
href="{{ config('constants.urls.contact') }}">Contact
|
||||
Us</a>
|
||||
</x-forms.button>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<li class="inline-flex items-center">
|
||||
<div class="flex items-center">
|
||||
<a class="text-xs truncate lg:text-sm"
|
||||
href="{{ route('project.show', ['project_uuid' => $this->parameters['project_uuid']]) }}">
|
||||
href="{{ route('project.show', ['project_uuid' => data_get($resource, 'environment.project.uuid')]) }}">
|
||||
{{ data_get($resource, 'environment.project.name', 'Undefined Name') }}</a>
|
||||
<svg aria-hidden="true" class="w-4 h-4 mx-1 font-bold dark:text-warning" fill="currentColor"
|
||||
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -21,7 +21,7 @@
|
||||
<li>
|
||||
<div class="flex items-center">
|
||||
<a class="text-xs truncate lg:text-sm"
|
||||
href="{{ route('project.resource.index', ['environment_name' => $this->parameters['environment_name'], 'project_uuid' => $this->parameters['project_uuid']]) }}">{{ $this->parameters['environment_name'] }}</a>
|
||||
href="{{ route('project.resource.index', ['environment_name' => data_get($resource, 'environment.name'), 'project_uuid' => data_get($resource, 'environment.project.uuid')]) }}">{{ data_get($resource, 'environment.name') }}</a>
|
||||
<svg aria-hidden="true" class="w-4 h-4 mx-1 font-bold dark:text-warning" fill="currentColor"
|
||||
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd"
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||
<a class="menu-item {{ $activeMenu === 'general' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}" wire:navigate>General</a>
|
||||
href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}">General</a>
|
||||
@if ($server->isFunctional())
|
||||
<a class="menu-item {{ $activeMenu === 'advanced' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.advanced', ['server_uuid' => $server->uuid]) }}" wire:navigate>Advanced
|
||||
href="{{ route('server.advanced', ['server_uuid' => $server->uuid]) }}">Advanced
|
||||
</a>
|
||||
@endif
|
||||
<a class="menu-item {{ $activeMenu === 'private-key' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}" wire:navigate>Private Key
|
||||
href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">Private Key
|
||||
</a>
|
||||
@if ($server->isFunctional())
|
||||
@if (!$server->isLocalhost())
|
||||
<a class="menu-item {{ $activeMenu === 'cloudflare-tunnels' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.cloudflare-tunnels', ['server_uuid' => $server->uuid]) }}" wire:navigate>Cloudflare
|
||||
href="{{ route('server.cloudflare-tunnels', ['server_uuid' => $server->uuid]) }}">Cloudflare
|
||||
Tunnels</a>
|
||||
@endif
|
||||
@if ($server->isFunctional())
|
||||
<a class="menu-item {{ $activeMenu === 'destinations' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.destinations', ['server_uuid' => $server->uuid]) }}" wire:navigate>Destinations
|
||||
href="{{ route('server.destinations', ['server_uuid' => $server->uuid]) }}">Destinations
|
||||
</a>
|
||||
<a class="menu-item {{ $activeMenu === 'log-drains' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.log-drains', ['server_uuid' => $server->uuid]) }}" wire:navigate>Log
|
||||
href="{{ route('server.log-drains', ['server_uuid' => $server->uuid]) }}">Log
|
||||
Drains</a>
|
||||
<a class="menu-item {{ $activeMenu === 'metrics' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.charts', ['server_uuid' => $server->uuid]) }}">Metrics</a>
|
||||
@endif
|
||||
@if (!$server->isLocalhost())
|
||||
<a class="menu-item {{ $activeMenu === 'danger' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.delete', ['server_uuid' => $server->uuid]) }}" wire:navigate>Danger</a>
|
||||
href="{{ route('server.delete', ['server_uuid' => $server->uuid]) }}">Danger</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
href="{{ route('settings.index') }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
@if (isCloud())
|
||||
<a class="{{ request()->routeIs('settings.license') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('settings.license') }}">
|
||||
<button>Resale License</button>
|
||||
</a>
|
||||
@endif
|
||||
<a class="{{ request()->routeIs('settings.backup') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('settings.backup') }}">
|
||||
<button>Backup</button>
|
||||
|
||||
@@ -11,16 +11,20 @@
|
||||
toast(this.title, { description: this.description, type: this.type, position: this.position, html: html })
|
||||
}
|
||||
}" x-init="window.toast = function(message, options = {}) {
|
||||
let description = '';
|
||||
let type = 'default';
|
||||
let position = 'top-center';
|
||||
let html = '';
|
||||
if (typeof options.description != 'undefined') description = options.description;
|
||||
if (typeof options.type != 'undefined') type = options.type;
|
||||
if (typeof options.position != 'undefined') position = options.position;
|
||||
if (typeof options.html != 'undefined') html = options.html;
|
||||
try {
|
||||
let description = '';
|
||||
let type = 'default';
|
||||
let position = 'top-center';
|
||||
let html = '';
|
||||
if (typeof options.description != 'undefined') description = options.description;
|
||||
if (typeof options.type != 'undefined') type = options.type;
|
||||
if (typeof options.position != 'undefined') position = options.position;
|
||||
if (typeof options.html != 'undefined') html = options.html;
|
||||
|
||||
window.dispatchEvent(new CustomEvent('toast-show', { detail: { type: type, message: message, description: description, position: position, html: html } }));
|
||||
window.dispatchEvent(new CustomEvent('toast-show', { detail: { type: type, message: message, description: description, position: position, html: html } }));
|
||||
} catch (error) {
|
||||
console.error('Error showing toast:', error);
|
||||
}
|
||||
}" class="relative space-y-5">
|
||||
<template x-teleport="body">
|
||||
<ul x-data="{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<a {{ $attributes->merge(['class' => 'text-xs cursor-pointer opacity-90 hover:opacity-100 dark:hover:text-white hover:text-black']) }}
|
||||
href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('version') }}" target="_blank">
|
||||
v{{ config('version') }}
|
||||
</a>
|
||||
href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('constants.coolify.version') }}" target="_blank">
|
||||
v{{ config('constants.coolify.version') }}
|
||||
</a>
|
||||
|
||||
23
resources/views/errors/400.blade.php
Normal file
23
resources/views/errors/400.blade.php
Normal file
@@ -0,0 +1,23 @@
|
||||
@extends('layouts.base')
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div>
|
||||
<p class="font-mono font-semibold text-7xl dark:text-warning">400</p>
|
||||
<h1 class="mt-4 font-bold tracking-tight dark:text-white">Bad Request</h1>
|
||||
@if ($exception->getMessage())
|
||||
<p class="text-base leading-7 text-red-500">{{ $exception->getMessage() }}</p>
|
||||
@else
|
||||
<p class="text-base leading-7 text-neutral-300">The request could not be understood by the server due to
|
||||
malformed syntax.
|
||||
</p>
|
||||
@endif
|
||||
<div class="flex items-center mt-10 gap-x-6">
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -9,7 +9,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div>
|
||||
<p class="font-mono font-semibold text-red-500 text-7xl">500</p>
|
||||
<h1 class="mt-4 font-bold tracking-tight dark:text-white">Something is not okay, are you okay?</h1>
|
||||
<h1 class="mt-4 font-bold tracking-tight dark:text-white">Wait, this is not cool...</h1>
|
||||
<p class="text-base leading-7 text-neutral-300">There has been an error, we are working on it.
|
||||
</p>
|
||||
@if ($exception->getMessage() !== '')
|
||||
@@ -13,7 +13,7 @@
|
||||
<a href="/">
|
||||
<x-forms.button>Go back home</x-forms.button>
|
||||
</a>
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
patience.
|
||||
</p>
|
||||
<div class="flex items-center mt-10 gap-x-6">
|
||||
<a target="_blank" class="text-xs" href="{{ config('coolify.contact') }}">Contact
|
||||
<a target="_blank" class="text-xs" href="{{ config('constants.urls.contact') }}">Contact
|
||||
support
|
||||
<x-external-link />
|
||||
</a>
|
||||
|
||||
@@ -34,11 +34,13 @@
|
||||
</style>
|
||||
@if (config('app.name') == 'Coolify Cloud')
|
||||
<script defer data-domain="app.coolify.io" src="https://analytics.coollabs.io/js/plausible.js"></script>
|
||||
<script src="https://js.sentry-cdn.com/0f8593910512b5cdd48c6da78d4093be.min.js" crossorigin="anonymous"></script>
|
||||
@endif
|
||||
@auth
|
||||
<script type="text/javascript" src="{{ URL::asset('js/echo.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ URL::asset('js/pusher.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ URL::asset('js/apexcharts.js') }}"></script>
|
||||
|
||||
@endauth
|
||||
</head>
|
||||
@section('body')
|
||||
@@ -84,9 +86,9 @@
|
||||
window.Pusher = Pusher;
|
||||
window.Echo = new Echo({
|
||||
broadcaster: 'pusher',
|
||||
cluster: "{{ env('PUSHER_HOST') }}" || window.location.hostname,
|
||||
key: "{{ env('PUSHER_APP_KEY') }}" || 'coolify',
|
||||
wsHost: "{{ env('PUSHER_HOST') }}" || window.location.hostname,
|
||||
cluster: "{{ config('constants.pusher.host') }}" || window.location.hostname,
|
||||
key: "{{ config('constants.pusher.app_key') }}" || 'coolify',
|
||||
wsHost: "{{ config('constants.pusher.host') }}" || window.location.hostname,
|
||||
wsPort: "{{ getRealtime() }}",
|
||||
wssPort: "{{ getRealtime() }}",
|
||||
forceTLS: false,
|
||||
@@ -94,6 +96,20 @@
|
||||
enableStats: false,
|
||||
enableLogging: true,
|
||||
enabledTransports: ['ws', 'wss'],
|
||||
disableStats: true,
|
||||
// Add auto reconnection settings
|
||||
enabledTransports: ['ws', 'wss'],
|
||||
disabledTransports: ['sockjs', 'xhr_streaming', 'xhr_polling'],
|
||||
// Attempt to reconnect on connection lost
|
||||
autoReconnect: true,
|
||||
// Wait 1 second before first reconnect attempt
|
||||
reconnectionDelay: 1000,
|
||||
// Maximum delay between reconnection attempts
|
||||
maxReconnectionDelay: 1000,
|
||||
// Multiply delay by this number for each reconnection attempt
|
||||
reconnectionDelayGrowth: 1,
|
||||
// Maximum number of reconnection attempts
|
||||
maxAttempts: 15
|
||||
});
|
||||
@endauth
|
||||
let checkHealthInterval = null;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
@if ($foundUsers->count() > 0)
|
||||
<div class="flex flex-wrap gap-2 pt-4">
|
||||
@foreach ($foundUsers as $user)
|
||||
<div class="box w-64 group">
|
||||
<div class="box w-64 group" wire:click="switchUser({{ $user->id }})">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="box-title">{{ $user->name }}</div>
|
||||
<div class="box-description">{{ $user->email }}</div>
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
</x-slot:actions>
|
||||
<x-slot:explanation>
|
||||
<p>This will install the latest Docker Engine on your server, configure a few things to be able
|
||||
to run optimal.<br><br>Minimum Docker Engine version is: 22<br><br>To manually install
|
||||
to run optimal.<br><br>Minimum Docker Engine version is: {{ $minDockerVersion }}<br><br>To manually install
|
||||
Docker
|
||||
Engine, check <a target="_blank" class="underline dark:text-warning"
|
||||
href="https://docs.docker.com/engine/install/#server">this
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
@forelse ($server->destinations() as $destination)
|
||||
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
||||
<a class="box group"
|
||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}"
|
||||
wire:navigate>
|
||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="box-title">{{ $destination->name }}</div>
|
||||
<div class="box-description">Server: {{ $destination->server->name }}</div>
|
||||
@@ -26,8 +25,7 @@
|
||||
@endif
|
||||
@if ($destination->getMorphClass() === 'App\Models\SwarmDocker')
|
||||
<a class="box group"
|
||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}"
|
||||
wire:navigate>
|
||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="box-title">{{ $destination->name }}</div>
|
||||
<div class="box-description">server: {{ $destination->server->name }}</div>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<div class="pb-10" x-data>
|
||||
<h1>Compose</h1>
|
||||
<div>All kinds of compose files.</div>
|
||||
<h3 class="pt-4">Services</h3>
|
||||
@foreach ($services as $serviceName => $value)
|
||||
<x-forms.button wire:click="setService('{{ $serviceName }}')">{{ Str::headline($serviceName) }}</x-forms.button>
|
||||
@endforeach
|
||||
<h3 class="pt-4">Base64 En/Decode</h3>
|
||||
<x-forms.button x-on:click="copyToClipboard('{{ $base64 }}')">Copy Base64 Compose</x-forms.button>
|
||||
<div class="pt-4">
|
||||
<x-forms.textarea realtimeValidation rows="40" id="compose"></x-forms.textarea>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,15 +0,0 @@
|
||||
<div>
|
||||
<h2>S3 Test</h2>
|
||||
<form wire:submit="save">
|
||||
<input type="file" wire:model="file">
|
||||
@error('file')
|
||||
<span class="error">{{ $message }}</span>
|
||||
@enderror
|
||||
<div wire:loading wire:target="file">Uploading to server...</div>
|
||||
@if ($file)
|
||||
<x-forms.button type="submit">Upload file to s3:/files</x-forms.button>
|
||||
@endif
|
||||
</form>
|
||||
<h4>Functions</h4>
|
||||
<x-forms.button wire:click="get_files">Get s3:/files</x-forms.button>
|
||||
</div>
|
||||
@@ -11,16 +11,22 @@
|
||||
|
||||
let checkNumber = 1;
|
||||
let checkPusherInterval = null;
|
||||
let checkReconnectInterval = null;
|
||||
|
||||
if (!this.popups.realtime) {
|
||||
checkPusherInterval = setInterval(() => {
|
||||
if (window.Echo && window.Echo.connector.pusher.connection.state !== 'connected') {
|
||||
checkNumber++;
|
||||
if (checkNumber > 5) {
|
||||
this.popups.realtime = true;
|
||||
console.error(
|
||||
'Coolify could not connect to its real-time service. This will cause unusual problems on the UI if not fixed! Please check the related documentation (https://coolify.io/docs/knowledge-base/cloudflare/tunnels) or get help on Discord (https://coollabs.io/discord).)'
|
||||
);
|
||||
clearInterval(checkPusherInterval);
|
||||
if (window.Echo) {
|
||||
if (window.Echo.connector.pusher.connection.state === 'connected') {
|
||||
this.popups.realtime = false;
|
||||
} else {
|
||||
checkNumber++;
|
||||
if (checkNumber > 5) {
|
||||
this.popups.realtime = true;
|
||||
console.error(
|
||||
'Coolify could not connect to its real-time service. This will cause unusual problems on the UI if not fixed! Please check the related documentation (https://coolify.io/docs/knowledge-base/cloudflare/tunnels) or get help on Discord (https://coollabs.io/discord).)'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
@endif
|
||||
</div>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave id="discordEnabled" label="Enabled" />
|
||||
<x-forms.checkbox instantSave="instantSaveDiscordEnabled" id="discordEnabled" label="Enabled" />
|
||||
</div>
|
||||
<x-forms.input type="password"
|
||||
helper="Generate a webhook in Discord.<br>Example: https://discord.com/api/webhooks/...." required
|
||||
|
||||
@@ -9,115 +9,110 @@
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if (isInstanceAdmin() && !$team->use_instance_email_settings)
|
||||
@if (isInstanceAdmin() && !$useInstanceEmailSettings)
|
||||
<x-forms.button wire:click='copyFromInstanceSettings'>
|
||||
Copy from Instance Settings
|
||||
</x-forms.button>
|
||||
@endif
|
||||
@if (isEmailEnabled($team) && auth()->user()->isAdminFromSession() && isTestEmailEnabled($team))
|
||||
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
||||
<form wire:submit='submit' class="flex flex-col w-full gap-2">
|
||||
<x-forms.input placeholder="test@example.com" id="emails" label="Recipients" required />
|
||||
<x-forms.button wire:click="sendTestNotification" @click="modalOpen=false">
|
||||
<form wire:submit.prevent="sendTestEmail" class="flex flex-col w-full gap-2">
|
||||
<x-forms.input wire:model="testEmailAddress" placeholder="test@example.com" id="testEmailAddress"
|
||||
label="Recipients" required />
|
||||
<x-forms.button type="submit" @click="modalOpen=false">
|
||||
Send Email
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</x-modal-input>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
@if (isCloud())
|
||||
@if ($this->sharedEmailEnabled)
|
||||
<div class="w-64 py-4">
|
||||
<x-forms.checkbox instantSave="instantSaveInstance" id="team.use_instance_email_settings"
|
||||
label="Use Hosted Email Service" />
|
||||
</div>
|
||||
@else
|
||||
<div class="w-96 pb-4">
|
||||
<x-forms.checkbox disabled id="team.use_instance_email_settings"
|
||||
label="Use Hosted Email Service (Pro+ subscription required)" />
|
||||
@if (!isCloud())
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave="instantSaveInstance" id="useInstanceEmailSettings"
|
||||
label="Use system wide (transactional) email settings" />
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave="instantSaveInstance" id="team.use_instance_email_settings"
|
||||
label="Use system wide (transactional) email settings" />
|
||||
@if (!$useInstanceEmailSettings)
|
||||
<div class="flex gap-4">
|
||||
<x-forms.input required id="smtpFromName" helper="Name used in emails." label="From Name" />
|
||||
<x-forms.input required id="smtpFromAddress" helper="Email address used in emails."
|
||||
label="From Address" />
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
@if (isCloud())
|
||||
<div class="w-64 py-4">
|
||||
<x-forms.checkbox instantSave="instantSaveInstance" id="useInstanceEmailSettings"
|
||||
label="Use Hosted Email Service" />
|
||||
</div>
|
||||
@endif
|
||||
@if (!$team->use_instance_email_settings)
|
||||
<form class="flex flex-col items-end gap-2 pt-4 pb-4 xl:flex-row" wire:submit='submitFromFields'>
|
||||
<x-forms.input required id="team.smtp_from_name" helper="Name used in emails." label="From Name" />
|
||||
<x-forms.input required id="team.smtp_from_address" helper="Email address used in emails."
|
||||
label="From Address" />
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</form>
|
||||
@if (!$useInstanceEmailSettings)
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="p-4 border dark:border-coolgray-300">
|
||||
<h3>SMTP Server</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave id="team.smtp_enabled" label="Enabled" />
|
||||
<form wire:submit='submit' class="p-4 border dark:border-coolgray-300 flex flex-col gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3>SMTP Server</h3>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<form wire:submit='submit' class="flex flex-col">
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave="instantSaveSmtpEnabled" id="smtpEnabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input required id="team.smtp_host" placeholder="smtp.mailgun.org" label="Host" />
|
||||
<x-forms.input required id="team.smtp_port" placeholder="587" label="Port" />
|
||||
<x-forms.input id="team.smtp_encryption" helper="If SMTP uses SSL, set it to 'tls'."
|
||||
placeholder="tls" label="Encryption" />
|
||||
<x-forms.input required id="smtpHost" placeholder="smtp.mailgun.org" label="Host" />
|
||||
<x-forms.input required id="smtpPort" placeholder="587" label="Port" />
|
||||
<x-forms.select id="smtpEncryption" label="Encryption">
|
||||
<option value="tls">TLS</option>
|
||||
<option value="ssl">SSL</option>
|
||||
<option value="none">None</option>
|
||||
</x-forms.select>
|
||||
</div>
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input id="team.smtp_username" label="SMTP Username" />
|
||||
<x-forms.input id="team.smtp_password" type="password" label="SMTP Password" />
|
||||
<x-forms.input id="team.smtp_timeout" helper="Timeout value for sending emails."
|
||||
<x-forms.input id="smtpUsername" label="SMTP Username" />
|
||||
<x-forms.input id="smtpPassword" type="password" label="SMTP Password" />
|
||||
<x-forms.input id="smtpTimeout" helper="Timeout value for sending emails."
|
||||
label="Timeout" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="p-4 border dark:border-coolgray-300">
|
||||
<h3>Resend</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSaveResend' id="team.resend_enabled" label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submitResend' class="flex flex-col">
|
||||
</form>
|
||||
<form wire:submit='submit' class="p-4 border dark:border-coolgray-300 flex flex-col gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3>Resend</h3>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSaveResend' id="resendEnabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input required type="password" id="team.resend_api_key" placeholder="API key"
|
||||
<x-forms.input required type="password" id="resendApiKey" placeholder="API key"
|
||||
label="API Key" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
@if (isEmailEnabled($team) || data_get($team, 'use_instance_email_settings'))
|
||||
@if (isEmailEnabled($team) || $useInstanceEmailSettings)
|
||||
<h2 class="mt-4">Subscribe to events</h2>
|
||||
<div class="w-64">
|
||||
@if (isDev())
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_test" label="Test" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="smtpNotificationsTest" label="Test" />
|
||||
@endif
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_status_changes"
|
||||
<x-forms.checkbox instantSave="saveModel" id="smtpNotificationsStatusChanges"
|
||||
label="Container Status Changes" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_deployments"
|
||||
<x-forms.checkbox instantSave="saveModel" id="smtpNotificationsDeployments"
|
||||
label="Application Deployments" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_database_backups"
|
||||
label="Backup Status" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_scheduled_tasks"
|
||||
<x-forms.checkbox instantSave="saveModel" id="smtpNotificationsDatabaseBackups" label="Backup Status" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="smtpNotificationsScheduledTasks"
|
||||
label="Scheduled Tasks Status" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_server_disk_usage"
|
||||
label="Server Disk Usage" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="smtpNotificationsServerDiskUsage" label="Server Disk Usage" />
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
43
resources/views/livewire/notifications/slack.blade.php
Normal file
43
resources/views/livewire/notifications/slack.blade.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
Notifications | Coolify
|
||||
</x-slot>
|
||||
<x-notification.navbar />
|
||||
<form wire:submit='submit' class="flex flex-col gap-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Slack</h2>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if ($slackEnabled)
|
||||
<x-forms.button class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||
wire:click="sendTestNotification">
|
||||
Send Test Notifications
|
||||
</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave="instantSaveSlackEnabled" id="slackEnabled" label="Enabled" />
|
||||
</div>
|
||||
<x-forms.input type="password"
|
||||
helper="Generate a webhook in Slack.<br>Example: https://hooks.slack.com/services/...." required
|
||||
id="slackWebhookUrl" label="Webhook" />
|
||||
</form>
|
||||
@if ($slackEnabled)
|
||||
<h2 class="mt-4">Subscribe to events</h2>
|
||||
<div class="w-64">
|
||||
@if (isDev())
|
||||
<x-forms.checkbox instantSave="saveModel" id="slackNotificationsTest" label="Test" />
|
||||
@endif
|
||||
<x-forms.checkbox instantSave="saveModel" id="slackNotificationsStatusChanges"
|
||||
label="Container Status Changes" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="slackNotificationsDeployments"
|
||||
label="Application Deployments" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="slackNotificationsDatabaseBackups" label="Backup Status" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="slackNotificationsScheduledTasks"
|
||||
label="Scheduled Tasks Status" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="slackNotificationsServerDiskUsage"
|
||||
label="Server Disk Usage" />
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@@ -9,7 +9,7 @@
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if ($team->telegram_enabled)
|
||||
@if ($telegramEnabled)
|
||||
<x-forms.button class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||
wire:click="sendTestNotification">
|
||||
Send Test Notifications
|
||||
@@ -17,64 +17,61 @@
|
||||
@endif
|
||||
</div>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave id="team.telegram_enabled" label="Enabled" />
|
||||
<x-forms.checkbox instantSave="instantSaveTelegramEnabled" id="telegramEnabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
|
||||
<x-forms.input type="password" autocomplete="new-password"
|
||||
helper="Get it from the <a class='inline-block underline dark:text-white' href='https://t.me/botfather' target='_blank'>BotFather Bot</a> on Telegram."
|
||||
required id="team.telegram_token" label="Token" />
|
||||
<x-forms.input type="password" autocomplete="new-password"
|
||||
helper="Get it from the <a class='inline-block underline dark:text-white' href='https://t.me/botfather' target='_blank'>BotFather Bot</a> on Telegram."
|
||||
required id="telegramToken" label="Token" />
|
||||
<x-forms.input helper="Recommended to add your bot to a group chat and add its Chat ID here." required
|
||||
id="team.telegram_chat_id" label="Chat ID" />
|
||||
id="telegramChatId" label="Chat ID" />
|
||||
</div>
|
||||
@if (data_get($team, 'telegram_enabled'))
|
||||
@if ($telegramEnabled)
|
||||
<h2 class="mt-4">Subscribe to events</h2>
|
||||
<div class="flex flex-col gap-4 w-96">
|
||||
@if (isDev())
|
||||
<div class="flex flex-col">
|
||||
<h4>Test Notification</h4>
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_test"
|
||||
label="Enabled" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="telegramNotificationsTest" label="Enabled" />
|
||||
<x-forms.input
|
||||
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||
id="team.telegram_notifications_test_message_thread_id" label="Custom Topic ID" />
|
||||
id="telegramNotificationsTestMessageThreadId" label="Custom Topic ID" />
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex flex-col">
|
||||
<h4>Container Status Changes</h4>
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_status_changes"
|
||||
label="Enabled" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="telegramNotificationsStatusChanges" label="Enabled" />
|
||||
<x-forms.input
|
||||
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||
id="team.telegram_notifications_status_changes_message_thread_id" label="Custom Topic ID" />
|
||||
id="telegramNotificationsStatusChangesMessageThreadId" label="Custom Topic ID" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<h4>Application Deployments</h4>
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_deployments"
|
||||
label="Enabled" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="telegramNotificationsDeployments" label="Enabled" />
|
||||
<x-forms.input
|
||||
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||
id="team.telegram_notifications_deployments_message_thread_id" label="Custom Topic ID" />
|
||||
id="telegramNotificationsDeploymentsMessageThreadId" label="Custom Topic ID" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<h4>Database Backup Status</h4>
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_database_backups"
|
||||
<x-forms.checkbox instantSave="saveModel" id="telegramNotificationsDatabaseBackups"
|
||||
label="Enabled" />
|
||||
<x-forms.input
|
||||
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||
id="team.telegram_notifications_database_backups_message_thread_id" label="Custom Topic ID" />
|
||||
id="telegramNotificationsDatabaseBackupsMessageThreadId" label="Custom Topic ID" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<h4>Scheduled Tasks Status</h4>
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_scheduled_tasks"
|
||||
label="Enabled" />
|
||||
<x-forms.checkbox instantSave="saveModel" id="telegramNotificationsScheduledTasks"
|
||||
label="Enabled" />
|
||||
<x-forms.input
|
||||
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||
id="team.telegram_notifications_scheduled_tasks_thread_id" label="Custom Topic ID" />
|
||||
id="telegramNotificationsScheduledTasksMessageThreadId" label="Custom Topic ID" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<h4>Server Disk Usage</h4>
|
||||
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_server_disk_usage"
|
||||
<x-forms.checkbox instantSave="saveModel" id="telegramNotificationsServerDiskUsage"
|
||||
label="Enabled" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,90 +8,88 @@
|
||||
<h3>General</h3>
|
||||
@if ($application->git_based())
|
||||
<x-forms.checkbox helper="Automatically deploy new commits based on Git webhooks." instantSave
|
||||
id="application.settings.is_auto_deploy_enabled" label="Auto Deploy" />
|
||||
id="isAutoDeployEnabled" label="Auto Deploy" />
|
||||
<x-forms.checkbox
|
||||
helper="Allow to automatically deploy Preview Deployments for all opened PR's.<br><br>Closing a PR will delete Preview Deployments."
|
||||
instantSave id="application.settings.is_preview_deployments_enabled" label="Preview Deployments" />
|
||||
instantSave id="isPreviewDeploymentsEnabled" label="Preview Deployments" />
|
||||
@endif
|
||||
<x-forms.checkbox helper="Disable Docker build cache on every deployment." instantSave id="disableBuildCache"
|
||||
label="Disable Build Cache" />
|
||||
<x-forms.checkbox
|
||||
helper="Your application will be available only on https if your domain starts with https://..."
|
||||
instantSave id="is_force_https_enabled" label="Force Https" />
|
||||
instantSave id="isForceHttpsEnabled" label="Force Https" />
|
||||
<x-forms.checkbox label="Enable Gzip Compression"
|
||||
helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this."
|
||||
instantSave id="is_gzip_enabled" />
|
||||
instantSave id="isGzipEnabled" />
|
||||
<x-forms.checkbox helper="Strip Prefix is used to remove prefixes from paths. Like /api/ to /api."
|
||||
instantSave id="is_stripprefix_enabled" label="Strip Prefixes" />
|
||||
instantSave id="isStripprefixEnabled" label="Strip Prefixes" />
|
||||
@if ($application->build_pack === 'dockercompose')
|
||||
<h3>Docker Compose</h3>
|
||||
<x-forms.checkbox instantSave id="application.settings.is_raw_compose_deployment_enabled"
|
||||
label="Raw Compose Deployment"
|
||||
<x-forms.checkbox instantSave id="isRawComposeDeploymentEnabled" label="Raw Compose Deployment"
|
||||
helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/compose#raw-docker-compose-deployment'>documentation.</a>" />
|
||||
@endif
|
||||
<h3>Container Names</h3>
|
||||
<h3 class="pt-4">Container Names</h3>
|
||||
<x-forms.checkbox
|
||||
helper="The deployed container will have the same name ({{ $application->uuid }}). <span class='font-bold dark:text-warning'>You will lose the rolling update feature!</span>"
|
||||
instantSave id="application.settings.is_consistent_container_name_enabled"
|
||||
label="Consistent Container Names" />
|
||||
@if (!$application->settings->is_consistent_container_name_enabled)
|
||||
<form class="flex items-end gap-2 pl-2" wire:submit.prevent='saveCustomName'>
|
||||
instantSave id="isConsistentContainerNameEnabled" label="Consistent Container Names" />
|
||||
@if ($isConsistentContainerNameEnabled === false)
|
||||
<form class="flex items-end gap-2 " wire:submit.prevent='saveCustomName'>
|
||||
<x-forms.input
|
||||
helper="You can add a custom name for your container.<br><br>The name will be converted to slug format when you save it. <span class='font-bold dark:text-warning'>You will lose the rolling update feature!</span>"
|
||||
instantSave id="application.settings.custom_internal_name" label="Custom Container Name" />
|
||||
instantSave id="customInternalName" label="Custom Container Name" />
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
</form>
|
||||
@endif
|
||||
@if ($application->build_pack === 'dockercompose')
|
||||
<h3>Network</h3>
|
||||
<x-forms.checkbox instantSave id="application.settings.connect_to_docker_network"
|
||||
label="Connect To Predefined Network"
|
||||
<h3 class="pt-4">Network</h3>
|
||||
<x-forms.checkbox instantSave id="isConnectToDockerNetworkEnabled" label="Connect To Predefined Network"
|
||||
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='underline dark:text-white' target='_blank' href='https://coolify.io/docs/knowledge-base/docker/compose#connect-to-predefined-networks'>this</a>." />
|
||||
@endif
|
||||
@if (!$application->settings->is_raw_compose_deployment_enabled)
|
||||
<h3>Logs</h3>
|
||||
@if ($isLogDrainEnabled === false)
|
||||
<h3 class="pt-4">Logs</h3>
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave id="application.settings.is_log_drain_enabled" label="Drain Logs" />
|
||||
instantSave id="isLogDrainEnabled" label="Drain Logs" />
|
||||
@endif
|
||||
|
||||
@if ($application->git_based())
|
||||
<h3>Git</h3>
|
||||
<x-forms.checkbox instantSave id="application.settings.is_git_submodules_enabled" label="Submodules"
|
||||
<x-forms.checkbox instantSave id="isGitSubmodulesEnabled" label="Submodules"
|
||||
helper="Allow Git Submodules during build process." />
|
||||
<x-forms.checkbox instantSave id="application.settings.is_git_lfs_enabled" label="LFS"
|
||||
<x-forms.checkbox instantSave id="isGitLfsEnabled" label="LFS"
|
||||
helper="Allow Git LFS during build process." />
|
||||
@endif
|
||||
{{-- <x-forms.checkbox disabled instantSave id="is_dual_cert" label="Dual Certs?" />
|
||||
<x-forms.checkbox disabled instantSave id="is_custom_ssl" label="Is Custom SSL?" />
|
||||
<x-forms.checkbox disabled instantSave id="is_http2" label="Is Http2?" /> --}}
|
||||
</div>
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<h3>GPU</h3>
|
||||
@endif
|
||||
<form wire:submit="submit">
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<x-forms.checkbox
|
||||
helper="Enable GPU usage for this application. More info <a href='https://docs.docker.com/compose/gpu-support/' class='underline dark:text-white' target='_blank'>here</a>."
|
||||
instantSave id="application.settings.is_gpu_enabled" label="Attach GPU" />
|
||||
@if ($application->settings->is_gpu_enabled)
|
||||
<h5>GPU Settings</h5>
|
||||
|
||||
</div>
|
||||
<form wire:submit="submit" class="flex flex-col gap-2">
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<div class="flex gap-2 items-end pt-4">
|
||||
<h3>GPU</h3>
|
||||
@if ($isGpuEnabled)
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
@endif
|
||||
@endif
|
||||
@if ($application->settings->is_gpu_enabled)
|
||||
<div class="flex flex-col w-full gap-2 p-2 xl:flex-row">
|
||||
<x-forms.input label="GPU Driver" id="application.settings.gpu_driver"> </x-forms.input>
|
||||
<x-forms.input label="GPU Count" placeholder="empty means use all GPUs"
|
||||
id="application.settings.gpu_count"> </x-forms.input>
|
||||
<x-forms.input label="GPU Device Ids" placeholder="0,2"
|
||||
helper="Comma separated list of device ids. More info <a href='https://docs.docker.com/compose/gpu-support/#access-specific-devices' class='underline dark:text-white' target='_blank'>here</a>."
|
||||
id="application.settings.gpu_device_ids"> </x-forms.input>
|
||||
</div>
|
||||
@endif
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<div class="md:w-96 pb-4">
|
||||
<x-forms.checkbox
|
||||
helper="Enable GPU usage for this application. More info <a href='https://docs.docker.com/compose/gpu-support/' class='underline dark:text-white' target='_blank'>here</a>."
|
||||
instantSave id="isGpuEnabled" label="Enable GPU" />
|
||||
</div>
|
||||
@endif
|
||||
@if ($isGpuEnabled)
|
||||
<div class="flex flex-col w-full gap-2 ">
|
||||
<div class="flex gap-2 items-end">
|
||||
<x-forms.input label="GPU Driver" id="gpuDriver"> </x-forms.input>
|
||||
<x-forms.input label="GPU Count" placeholder="empty means use all GPUs" id="gpuCount">
|
||||
</x-forms.input>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="px-2">
|
||||
<x-forms.textarea label="GPU Options" id="application.settings.gpu_options">
|
||||
</x-forms.textarea>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
<x-forms.input label="GPU Device Ids" placeholder="0,2"
|
||||
helper="Comma separated list of device ids. More info <a href='https://docs.docker.com/compose/gpu-support/#access-specific-devices' class='underline dark:text-white' target='_blank'>here</a>."
|
||||
id="gpuDeviceIds"> </x-forms.input>
|
||||
<x-forms.textarea rows="10" label="GPU Options" id="gpuOptions"> </x-forms.textarea>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
@forelse ($deployments as $deployment)
|
||||
<div @class([
|
||||
'dark:bg-coolgray-100 p-2 border-l-2 transition-colors hover:no-underline box-without-bg-without-border bg-white flex-col cursor-pointer dark:hover:text-neutral-400 dark:hover:bg-coolgray-200',
|
||||
'border-warning border-dashed ' =>
|
||||
'border-white border-dashed ' =>
|
||||
data_get($deployment, 'status') === 'in_progress' ||
|
||||
data_get($deployment, 'status') === 'cancelled-by-user',
|
||||
'border-error border-dashed ' =>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
},
|
||||
toggleScroll() {
|
||||
this.alwaysScroll = !this.alwaysScroll;
|
||||
|
||||
|
||||
if (this.alwaysScroll) {
|
||||
this.intervalId = setInterval(() => {
|
||||
const screen = document.getElementById('screen');
|
||||
@@ -58,30 +58,34 @@
|
||||
<div @if ($isKeepAliveOn) wire:poll.2000ms="polling" @endif
|
||||
class="flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto bg-white dark:text-white dark:bg-coolgray-100 scrollbar dark:border-coolgray-300"
|
||||
:class="fullscreen ? '' : 'min-h-14 max-h-[40rem] border border-dotted rounded'">
|
||||
<div :class="fullscreen ? 'fixed' : 'absolute'" class="top-4 right-6">
|
||||
<div :class="fullscreen ? 'fixed' : 'absolute'" class="top-2 right-3">
|
||||
<div class="flex justify-end gap-4 fixed -translate-x-full">
|
||||
<button title="Toggle timestamps" x-on:click="showTimestamps = !showTimestamps">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
stroke="currentColor" stroke-width="2">
|
||||
<svg class="w-5 h-5 opacity-30 hover:opacity-100" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||
stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Go Top" x-show="fullscreen" x-on:click="goTop">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="w-5 h-5 opacity-30 hover:opacity-100" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" d="M12 5v14m4-10l-4-4M8 9l4-4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Follow Logs" x-show="fullscreen" :class="alwaysScroll ? 'dark:text-warning' : ''"
|
||||
x-on:click="toggleScroll">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="w-5 h-5 opacity-30 hover:opacity-100" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" d="M12 5v14m4-4l-4 4m-4-4l4 4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Fullscreen" x-show="!fullscreen" x-on:click="makeFullscreen">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="w-5 h-5 opacity-30 hover:opacity-100" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none">
|
||||
<path
|
||||
d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z" />
|
||||
@@ -91,7 +95,8 @@
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Minimize" x-show="fullscreen" x-on:click="makeFullscreen">
|
||||
<svg class="icon" viewBox="0 0 24 24"xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="w-5 h-5 opacity-30 hover:opacity-100"
|
||||
viewBox="0 0 24 24"xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"
|
||||
d="M6 14h4m0 0v4m0-4l-6 6m14-10h-4m0 0V6m0 4l6-6" />
|
||||
|
||||
@@ -61,8 +61,16 @@
|
||||
|
||||
</div>
|
||||
@endif
|
||||
@if ($application->settings->is_static || $application->build_pack === 'static')
|
||||
<x-forms.textarea id="application.custom_nginx_configuration"
|
||||
placeholder="Empty means default configuration will be used." label="Custom Nginx Configuration"
|
||||
helper="You can add custom Nginx configuration here." />
|
||||
<x-forms.button wire:click="generateNginxConfiguration">Generate Default Nginx
|
||||
Configuration</x-forms.button>
|
||||
@endif
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<div class="flex items-end gap-2">
|
||||
|
||||
<x-forms.input placeholder="https://coolify.io" wire:model.blur="application.fqdn" label="Domains"
|
||||
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. " />
|
||||
<x-forms.button wire:click="getWildcardDomain">Generate Domain
|
||||
@@ -70,7 +78,7 @@
|
||||
</div>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.select label="Direction" id="application.redirect" required
|
||||
helper="You need to add both the www and non-www A DNS records pointing to your server.">
|
||||
helper="You must need to add www and non-www as an A DNS record. Make sure the www domain is added under Domains.">
|
||||
<option value="both">Allow www & non-www.</option>
|
||||
<option value="www">Redirect to www.</option>
|
||||
<option value="non-www">Redirect to non-www.</option>
|
||||
@@ -154,7 +162,7 @@
|
||||
<div class="pt-1 text-xs">Nixpacks will detect the required configuration
|
||||
automatically.
|
||||
<a class="underline"
|
||||
href="https://coolify.io/docs/resources/applications/index">Framework
|
||||
href="https://coolify.io/docs/applications">Framework
|
||||
Specific Docs</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Preview Deployments</h2>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-forms.button wire:click="resetToDefault">Reset template to default</x-forms.button>
|
||||
<x-forms.button isHighlighted wire:click="resetToDefault">Reset template to default</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4 ">Preview Deployments based on pull requests are here.</div>
|
||||
<div class="flex flex-col gap-2 pb-4">
|
||||
<x-forms.input id="application.preview_url_template" label="Preview URL Template"
|
||||
<x-forms.input id="previewUrlTemplate" label="Preview URL Template"
|
||||
helper="Templates:<span class='text-helper'>@@{{ random }}</span> to generate random sub-domain each time a PR is deployed, <span class='text-helper'>@@{{ pr_id }}</span> to use pull request ID as sub-domain or <span class='text-helper'>@@{{ domain }}</span> to replace the domain name with the application's domain name." />
|
||||
@if ($preview_url_template)
|
||||
<div class="">Domain Preview: {{ $preview_url_template }}</div>
|
||||
@if ($previewUrlTemplate)
|
||||
<div class="">Domain Preview: {{ $previewUrlTemplate }}</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<h4 class="py-2 ">Select another Private Key</h4>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@foreach ($privateKeys as $key)
|
||||
<x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
|
||||
<x-forms.button wire:click="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
|
||||
</x-forms.button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@@ -6,15 +6,13 @@
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
{{-- <div>Advanced Swarm Configuration</div> --}}
|
||||
<div class="flex flex-col gap-2 py-4">
|
||||
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
||||
<x-forms.input id="application.swarm_replicas" label="Replicas" required />
|
||||
<x-forms.input id="swarmReplicas" label="Replicas" required />
|
||||
<x-forms.checkbox instantSave helper="If turned off, this resource will start on manager nodes too."
|
||||
id="application.settings.is_swarm_only_worker_nodes" label="Only Start on Worker nodes" />
|
||||
id="isSwarmOnlyWorkerNodes" label="Only Start on Worker nodes" />
|
||||
</div>
|
||||
<x-forms.textarea id="swarm_placement_constraints" rows="7"
|
||||
label="Custom Placement Constraints"
|
||||
<x-forms.textarea id="swarmPlacementConstraints" rows="7" label="Custom Placement Constraints"
|
||||
placeholder="placement:
|
||||
constraints:
|
||||
- 'node.role == worker'" />
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
@endif
|
||||
</div>
|
||||
<div class="w-48 pb-2">
|
||||
<x-forms.checkbox instantSave label="Backup Enabled" id="backup.enabled" />
|
||||
<x-forms.checkbox instantSave label="S3 Enabled" id="backup.save_s3" />
|
||||
<x-forms.checkbox instantSave label="Backup Enabled" id="backupEnabled" />
|
||||
<x-forms.checkbox instantSave label="S3 Enabled" id="saveS3" />
|
||||
</div>
|
||||
@if ($backup->save_s3)
|
||||
<div class="pb-6">
|
||||
<x-forms.select id="backup.s3_storage_id" label="S3 Storage" required>
|
||||
<x-forms.select id="s3StorageId" label="S3 Storage" required>
|
||||
<option value="default">Select a S3 storage</option>
|
||||
@foreach ($s3s as $s3)
|
||||
<option value="{{ $s3->id }}">{{ $s3->name }}</option>
|
||||
@@ -37,40 +37,40 @@
|
||||
<div class="flex gap-2 flex-col ">
|
||||
@if ($backup->database_type === 'App\Models\StandalonePostgresql' && $backup->database_id !== 0)
|
||||
<div class="w-48">
|
||||
<x-forms.checkbox label="Backup All Databases" id="backup.dump_all" instantSave />
|
||||
<x-forms.checkbox label="Backup All Databases" id="dumpAll" instantSave />
|
||||
</div>
|
||||
@if (!$backup->dump_all)
|
||||
<x-forms.input label="Databases To Backup"
|
||||
helper="Comma separated list of databases to backup. Empty will include the default one."
|
||||
id="backup.databases_to_backup" />
|
||||
id="databasesToBackup" />
|
||||
@endif
|
||||
@elseif($backup->database_type === 'App\Models\StandaloneMongodb')
|
||||
<x-forms.input label="Databases To Include"
|
||||
helper="A list of databases to backup. You can specify which collection(s) per database to exclude from the backup. Empty will include all databases and collections.<br><br>Example:<br><br>database1:collection1,collection2|database2:collection3,collection4<br><br> database1 will include all collections except collection1 and collection2. <br>database2 will include all collections except collection3 and collection4.<br><br>Another Example:<br><br>database1:collection1|database2<br><br> database1 will include all collections except collection1.<br>database2 will include ALL collections."
|
||||
id="backup.databases_to_backup" />
|
||||
id="databasesToBackup" />
|
||||
@elseif($backup->database_type === 'App\Models\StandaloneMysql')
|
||||
<div class="w-48">
|
||||
<x-forms.checkbox label="Backup All Databases" id="backup.dump_all" instantSave />
|
||||
<x-forms.checkbox label="Backup All Databases" id="dumpAll" instantSave />
|
||||
</div>
|
||||
@if (!$backup->dump_all)
|
||||
<x-forms.input label="Databases To Backup"
|
||||
helper="Comma separated list of databases to backup. Empty will include the default one."
|
||||
id="backup.databases_to_backup" />
|
||||
id="databasesToBackup" />
|
||||
@endif
|
||||
@elseif($backup->database_type === 'App\Models\StandaloneMariadb')
|
||||
<div class="w-48">
|
||||
<x-forms.checkbox label="Backup All Databases" id="backup.dump_all" instantSave />
|
||||
<x-forms.checkbox label="Backup All Databases" id="dumpAll" instantSave />
|
||||
</div>
|
||||
@if (!$backup->dump_all)
|
||||
<x-forms.input label="Databases To Backup"
|
||||
helper="Comma separated list of databases to backup. Empty will include the default one."
|
||||
id="backup.databases_to_backup" />
|
||||
id="databasesToBackup" />
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Frequency" id="backup.frequency" />
|
||||
<x-forms.input label="Number of backups to keep (locally)" id="backup.number_of_backups_locally" />
|
||||
<x-forms.input label="Frequency" id="frequency" />
|
||||
<x-forms.input label="Number of backups to keep (locally)" id="numberOfBackupsLocally" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -7,68 +7,78 @@
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Name" id="database.name" />
|
||||
<x-forms.input label="Description" id="database.description" />
|
||||
<x-forms.input label="Image" id="database.image" required
|
||||
<x-forms.input label="Name" id="name" />
|
||||
<x-forms.input label="Description" id="description" />
|
||||
<x-forms.input label="Image" id="image" required
|
||||
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/r/clickhouse/clickhouse-server/'>https://hub.docker.com/r/clickhouse/clickhouse-server/</a>" />
|
||||
</div>
|
||||
|
||||
@if ($database->started_at)
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Initial Username" id="database.clickhouse_admin_user"
|
||||
placeholder="If empty: clickhouse" readonly helper="You can only change this in the database." />
|
||||
<x-forms.input label="Initial Password" id="database.clickhouse_admin_password" type="password" required
|
||||
<x-forms.input label="Initial Username" id="clickhouseAdminUser" placeholder="If empty: clickhouse"
|
||||
readonly helper="You can only change this in the database." />
|
||||
<x-forms.input label="Initial Password" id="clickhouseAdminPassword" type="password" required readonly
|
||||
helper="You can only change this in the database." />
|
||||
</div>
|
||||
@else
|
||||
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
||||
start. After that, you need to modify it in the database.
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Username" id="database.clickhouse_admin_user" required />
|
||||
<x-forms.input label="Password" id="database.clickhouse_admin_password" type="password" required />
|
||||
<x-forms.input label="Username" id="clickhouseAdminUser" required />
|
||||
<x-forms.input label="Password" id="clickhouseAdminPassword" type="password" required />
|
||||
</div>
|
||||
@endif
|
||||
<x-forms.input
|
||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||
id="database.custom_docker_run_options" label="Custom Docker Options" />
|
||||
id="customDockerRunOptions" label="Custom Docker Options" />
|
||||
<div class="flex flex-col gap-2">
|
||||
<h3 class="py-2">Network</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
||||
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
||||
</div>
|
||||
<x-forms.input label="Clickhouse URL (internal)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url" />
|
||||
@if ($db_url_public)
|
||||
type="password" readonly wire:model="dbUrl" />
|
||||
@if ($dbUrlPublic)
|
||||
<x-forms.input label="Clickhouse URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url_public" />
|
||||
type="password" readonly wire:model="dbUrlPublic" />
|
||||
@else
|
||||
<x-forms.input label="Clickhouse URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
readonly value="Starting the database will generate this." />
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if ($isPublic)
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !$isPublic }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
|
||||
</div>
|
||||
</form>
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
<div class="flex flex-col">
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
||||
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
<x-forms.input placeholder="0 0 * * * or daily" id="frequency"
|
||||
helper="You can use every_minute, hourly, daily, weekly, monthly, yearly or a cron expression." label="Frequency"
|
||||
required />
|
||||
@if ($s3s->count() === 0)
|
||||
<h2>S3</h2>
|
||||
@if ($definedS3s->count() === 0)
|
||||
<div class="text-red-500">No validated S3 Storages found.</div>
|
||||
@else
|
||||
<x-forms.checkbox wire:model.live="save_s3" label="Save to S3" />
|
||||
@if ($save_s3)
|
||||
<x-forms.select id="selected_storage_id" label="Select a validated S3 storage">
|
||||
@foreach ($s3s as $s3)
|
||||
<x-forms.checkbox wire:model.live="saveToS3" label="Save to S3" />
|
||||
@if ($saveToS3)
|
||||
<x-forms.select id="s3StorageId" label="Select a S3 Storage">
|
||||
@foreach ($definedS3s as $s3)
|
||||
<option value="{{ $s3->id }}">{{ $s3->name }}</option>
|
||||
@endforeach
|
||||
</x-forms.select>
|
||||
|
||||
@@ -7,53 +7,75 @@
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Name" id="database.name" />
|
||||
<x-forms.input label="Description" id="database.description" />
|
||||
<x-forms.input label="Image" id="database.image" required />
|
||||
<x-forms.input label="Name" id="name" />
|
||||
<x-forms.input label="Description" id="description" />
|
||||
<x-forms.input label="Image" id="image" required />
|
||||
</div>
|
||||
<x-forms.input
|
||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||
id="database.custom_docker_run_options" label="Custom Docker Options" />
|
||||
id="customDockerRunOptions" label="Custom Docker Options" />
|
||||
|
||||
@if ($database->started_at)
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Initial Password" id="dragonflyPassword" type="password" required readonly
|
||||
helper="You can only change this in the database." />
|
||||
</div>
|
||||
@else
|
||||
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
||||
start. After that, you need to modify it in the database.
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Password" id="dragonflyPassword" type="password" required />
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex flex-col gap-2">
|
||||
<h3 class="py-2">Network</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
||||
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
||||
</div>
|
||||
<x-forms.input label="Dragonfly URL (internal)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url" />
|
||||
@if ($db_url_public)
|
||||
type="password" readonly wire:model="dbUrl" />
|
||||
|
||||
@if ($dbUrlPublic)
|
||||
<x-forms.input label="Dragonfly URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url_public" />
|
||||
type="password" readonly wire:model="dbUrlPublic" />
|
||||
@else
|
||||
<x-forms.input label="Dragonfly URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
readonly value="Starting the database will generate this." />
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if ($isPublic)
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !$isPublic }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
|
||||
</div>
|
||||
</div>
|
||||
{{-- <x-forms.textarea
|
||||
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/Snapchat/KeyDB/unstable/keydb.conf'>KeyDB Default Configuration</a>"
|
||||
label="Custom Dragonfly Configuration" rows="10" id="database.keydb_conf" /> --}}
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
<div class="flex flex-col">
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
|
||||
</div>
|
||||
</form>
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,54 +7,78 @@
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Name" id="database.name" />
|
||||
<x-forms.input label="Description" id="database.description" />
|
||||
<x-forms.input label="Image" id="database.image" required
|
||||
<x-forms.input label="Name" id="name" />
|
||||
<x-forms.input label="Description" id="description" />
|
||||
<x-forms.input label="Image" id="image" required
|
||||
helper="For all available images, check here:<br><br><a target='_blank' href=https://hub.docker.com/r/eqalpha/keydb'>https://hub.docker.com/r/eqalpha/keydb</a>" />
|
||||
</div>
|
||||
|
||||
@if ($database->started_at)
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Initial Password" id="keydbPassword" type="password" required readonly
|
||||
helper="You can only change this in the database." />
|
||||
</div>
|
||||
@else
|
||||
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
||||
start. After that, you need to modify it in the database.
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Password" id="keydbPassword" type="password" required />
|
||||
</div>
|
||||
@endif
|
||||
<x-forms.input
|
||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||
id="database.custom_docker_run_options" label="Custom Docker Options" />
|
||||
id="customDockerRunOptions" label="Custom Docker Options" />
|
||||
<div class="flex flex-col gap-2">
|
||||
<h3 class="py-2">Network</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
||||
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
||||
</div>
|
||||
<x-forms.input label="KeyDB URL (internal)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url" />
|
||||
@if ($db_url_public)
|
||||
type="password" readonly wire:model="dbUrl" />
|
||||
@if ($dbUrlPublic)
|
||||
<x-forms.input label="KeyDB URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url_public" />
|
||||
type="password" readonly wire:model="dbUrlPublic" />
|
||||
@else
|
||||
<x-forms.input label="KeyDB URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
readonly value="Starting the database will generate this." />
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if ($isPublic)
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !$isPublic }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
|
||||
</div>
|
||||
<x-forms.textarea
|
||||
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/Snapchat/KeyDB/unstable/keydb.conf'>KeyDB Default Configuration</a>"
|
||||
label="Custom KeyDB Configuration" rows="10" id="database.keydb_conf" />
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
<div class="flex flex-col">
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
||||
</div>
|
||||
label="Custom KeyDB Configuration" rows="10" id="keydbConf" />
|
||||
</form>
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -66,21 +66,28 @@
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if (data_get($database, 'is_public'))
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom MariaDB Configuration" rows="10" id="database.mariadb_conf" />
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
|
||||
@@ -56,21 +56,28 @@
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if (data_get($database, 'is_public'))
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom MongoDB Configuration" rows="10" id="database.mongo_conf" />
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
|
||||
@@ -66,21 +66,28 @@
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if (data_get($database, 'is_public'))
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom Mysql Configuration" rows="10" id="database.mysql_conf" />
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
|
||||
@@ -74,21 +74,28 @@
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true"
|
||||
class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if (data_get($database, 'is_public'))
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom PostgreSQL Configuration" rows="10" id="database.postgres_conf" />
|
||||
</form>
|
||||
@@ -102,8 +109,7 @@
|
||||
<h3>Initialization scripts</h3>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Init Script">
|
||||
<form class="flex flex-col w-full gap-2 rounded" wire:submit='save_new_init_script'>
|
||||
<x-forms.input placeholder="create_test_db.sql" id="new_filename" label="Filename"
|
||||
required />
|
||||
<x-forms.input placeholder="create_test_db.sql" id="new_filename" label="Filename" required />
|
||||
<x-forms.textarea rows="20" placeholder="CREATE DATABASE test;" id="new_content"
|
||||
label="Content" required />
|
||||
<x-forms.button type="submit">
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input label="Name" id="database.name" />
|
||||
<x-forms.input label="Description" id="database.description" />
|
||||
<x-forms.input label="Image" id="database.image" required helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/redis'>https://hub.docker.com/_/redis</a>" />
|
||||
<x-forms.input label="Image" id="database.image" required
|
||||
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/redis'>https://hub.docker.com/_/redis</a>" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
@if (version_compare($redis_version, '6.0', '>='))
|
||||
@@ -36,31 +37,49 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<h3 class="py-2">Network</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings" helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
||||
</div>
|
||||
<x-forms.input label="Redis URL (internal)" helper="If you change the user/password/port, this could be different. This is with the default values." type="password" readonly wire:model="db_url" />
|
||||
<x-forms.input label="Redis URL (internal)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url" />
|
||||
@if ($db_url_public)
|
||||
<x-forms.input label="Redis URL (public)" helper="If you change the user/password/port, this could be different. This is with the default values." type="password" readonly wire:model="db_url_public" />
|
||||
<x-forms.input label="Redis URL (public)"
|
||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||
type="password" readonly wire:model="db_url_public" />
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-2">Proxy</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}" id="database.public_port" label="Public Port" />
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database" container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true" class="w-28">Proxy Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
<div class="flex flex-col py-2 w-64">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<div class="flex items-center">
|
||||
<h3>Proxy</h3>
|
||||
<x-loading wire:loading wire:target="instantSave" />
|
||||
</div>
|
||||
@if (data_get($database, 'is_public'))
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Proxy Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$database"
|
||||
container="{{ data_get($database, 'uuid') }}-proxy" lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}"
|
||||
@click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
||||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||
id="database.public_port" label="Public Port" />
|
||||
</div>
|
||||
<x-forms.textarea helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/redis/redis/7.2/redis.conf'>Redis Default Configuration</a>" label="Custom Redis Configuration" rows="10" id="database.redis_conf" />
|
||||
<x-forms.textarea
|
||||
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/redis/redis/7.2/redis.conf'>Redis Default Configuration</a>"
|
||||
label="Custom Redis Configuration" rows="10" id="database.redis_conf" />
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
<div class="flex flex-col">
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings." instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<h1>Project: {{ data_get($project, 'name') }}</h1>
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<livewire:project.delete-project :disabled="$project->resource_count() > 0" :project_id="$project->id" />
|
||||
<livewire:project.delete-project :disabled="!$project->isEmpty()" :project_id="$project->id" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-2 pb-10">Edit project details here.</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
@forelse ($private_keys as $key)
|
||||
@if ($private_key_id == $key->id)
|
||||
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200 box"
|
||||
wire:click.defer="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
|
||||
wire:click="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="box-title">
|
||||
{{ $key->name }}
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
@else
|
||||
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-200 box"
|
||||
wire:click.defer="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
|
||||
wire:click="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="box-title">
|
||||
{{ $key->name }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div>
|
||||
<div class="flex items-end gap-2">
|
||||
<h1>Create a new Application</h1>
|
||||
<x-modal-input buttonTitle="+ Add GitHub App" title="New GitHub App">
|
||||
<x-modal-input buttonTitle="+ Add GitHub App" title="New GitHub App" closeOutside="false">
|
||||
<livewire:source.github.create />
|
||||
</x-modal-input>
|
||||
@if ($repositories->count() > 0)
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
<div class="pb-4">Deploy resources, like Applications, Databases, Services...</div>
|
||||
<div x-data="searchResources()">
|
||||
@if ($current_step === 'type')
|
||||
<div class="sticky top-0 z-50 py-2">
|
||||
<input autocomplete="off" x-ref="searchInput" class="input w-full" x-model="search"
|
||||
placeholder="Type / to search..." @keydown.window.slash.prevent="$refs.searchInput.focus()">
|
||||
<div x-data="{ isSticky: false }" x-init="window.addEventListener('scroll', () => isSticky = window.pageYOffset > 100)" class="sticky top-0 z-50 py-2">
|
||||
<input autocomplete="off" x-ref="searchInput" class="input-sticky"
|
||||
:class="{ 'input-sticky-active': isSticky }" x-model="search" placeholder="Type / to search..."
|
||||
@keydown.window.slash.prevent="$refs.searchInput.focus()">
|
||||
</div>
|
||||
<div x-show="loading">Loading...</div>
|
||||
<div x-show="!loading" class="flex flex-col gap-4 py-4">
|
||||
@@ -30,8 +31,7 @@
|
||||
<span x-html="application.description"></span>
|
||||
</x-slot>
|
||||
<x-slot:logo>
|
||||
<img class="w-[4.5rem]
|
||||
aspect-square h-[4.5rem] p-2 transition-all duration-200 opacity-30 grayscale group-hover:grayscale-0 group-hover:opacity-100 "
|
||||
<img class="w-[4.5rem] aspect-square h-[4.5rem] p-2 transition-all duration-200 dark:opacity-30 grayscale group-hover:grayscale-0 group-hover:opacity-100 dark:bg-white/10 bg-black/10"
|
||||
:src="application.logo">
|
||||
</x-slot:logo>
|
||||
</x-resource-view>
|
||||
@@ -47,8 +47,7 @@
|
||||
<x-slot:title><span x-text="application.name"></span></x-slot>
|
||||
<x-slot:description><span x-text="application.description"></span></x-slot>
|
||||
<x-slot:logo> <img
|
||||
class="w-[4.5rem]
|
||||
aspect-square h-[4.5rem] p-2 transition-all duration-200 opacity-30 grayscale group-hover:grayscale-0 group-hover:opacity-100 "
|
||||
class="w-[4.5rem] aspect-square h-[4.5rem] p-2 transition-all duration-200 dark:opacity-30 grayscale group-hover:grayscale-0 group-hover:opacity-100 dark:bg-white/10 bg-black/10 "
|
||||
:src="application.logo"></x-slot>
|
||||
</x-resource-view>
|
||||
</div>
|
||||
@@ -100,14 +99,18 @@
|
||||
</x-slot>
|
||||
<x-slot:logo>
|
||||
<template x-if="service.logo">
|
||||
<img class="w-[4.5rem] aspect-square h-[4.5rem] p-2 transition-all duration-200 opacity-30 grayscale group-hover:grayscale-0 group-hover:opacity-100"
|
||||
:src='service.logo'>
|
||||
<img class="w-[4.5rem] aspect-square h-[4.5rem] p-2 transition-all duration-200 dark:opacity-30 grayscale group-hover:grayscale-0 group-hover:opacity-100 dark:bg-white/10 bg-black/10"
|
||||
:src='service.logo'
|
||||
x-on:error.window="$event.target.src = service.logo_github_url"
|
||||
onerror="this.onerror=null; this.src=this.getAttribute('data-fallback');"
|
||||
x-on:error="$event.target.src = '/svgs/coolify.png'"
|
||||
:data-fallback='service.logo_github_url' />
|
||||
</template>
|
||||
</x-slot:logo>
|
||||
<x-slot:documentation>
|
||||
<template x-if="service.documentation">
|
||||
<div class="flex items-center px-2" title="Read the documentation.">
|
||||
<a class="p-2 rounded hover:bg-coolgray-200 hover:no-underline group-hover:dark:text-white text-neutral-600"
|
||||
<a class="p-2 rounded hover:bg-gray-100 dark:hover:bg-coolgray-200 hover:no-underline group-hover:dark:text-white text-neutral-600"
|
||||
onclick="event.stopPropagation()" :href="service.documentation"
|
||||
target="_blank">
|
||||
Docs
|
||||
@@ -166,7 +169,8 @@
|
||||
}
|
||||
const filtered = Object.values(items).filter(item => {
|
||||
return (item.name?.toLowerCase().includes(searchLower) ||
|
||||
item.description?.toLowerCase().includes(searchLower))
|
||||
item.description?.toLowerCase().includes(searchLower) ||
|
||||
item.slogan?.toLowerCase().includes(searchLower))
|
||||
})
|
||||
return isSort ? filtered.sort(sortFn) : filtered;
|
||||
},
|
||||
@@ -205,7 +209,7 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@if ($current_step === 'servers')
|
||||
<h2>Select a server</h2>
|
||||
@@ -270,7 +274,7 @@
|
||||
16 (default).</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="gap-2 border border-transparent cursor-pointer box-without-bg dark:bg-coolgray-100 bg-white dark:hover:text-neutral-400 dark:hover:bg-coollabs group flex"
|
||||
<div class="gap-2 border border-transparent cursor-pointer box-without-bg dark:bg-coolgray-100 bg-white dark:hover:text-neutral-400 dark:hover:bg-coollabs group flex "
|
||||
wire:click="setPostgresqlType('postgres:16-alpine')">
|
||||
<div class="flex flex-col">
|
||||
<div class="box-title">PostgreSQL 16 (default)</div>
|
||||
|
||||
@@ -44,17 +44,108 @@
|
||||
</nav>
|
||||
</div>
|
||||
@if ($environment->isEmpty())
|
||||
<a href="{{ route('project.resource.create', ['project_uuid' => data_get($parameters, 'project_uuid'), 'environment_name' => data_get($parameters, 'environment_name')]) }} "
|
||||
<a href="{{ route('project.resource.create', ['project_uuid' => data_get($parameters, 'project_uuid'), 'environment_name' => data_get($parameters, 'environment_name')]) }} "
|
||||
class="items-center justify-center box">+ Add New Resource</a>
|
||||
@else
|
||||
<div x-data="searchComponent()">
|
||||
<x-forms.input placeholder="Search for name, fqdn..." x-model="search" id="null" />
|
||||
<div class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<template x-if="allFilteredItems.length === 0">
|
||||
<div>No resource found with the search term "<span x-text="search"></span>".</div>
|
||||
</template>
|
||||
<template
|
||||
x-if="filteredApplications.length === 0 && filteredDatabases.length === 0 && filteredServices.length === 0">
|
||||
<div>No resource found with the search term "<span x-text="search"></span>".</div>
|
||||
</template>
|
||||
|
||||
<template x-for="item in allFilteredItems" :key="item.uuid">
|
||||
<template x-if="filteredApplications.length > 0">
|
||||
<h2 class="pt-4">Applications</h2>
|
||||
</template>
|
||||
<div x-show="filteredApplications.length > 0"
|
||||
class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<template x-for="item in filteredApplications" :key="item.uuid">
|
||||
<span>
|
||||
<a class="h-24 box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex gap-2 px-4">
|
||||
<div class="pb-2 truncate box-title" x-text="item.name"></div>
|
||||
<div class="flex-1"></div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div title="running" class="bg-success badge badge-absolute"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div title="exited" class="bg-error badge badge-absolute"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div title="restarting" class="bg-warning badge badge-absolute"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('degraded')">
|
||||
<div title="degraded" class="bg-warning badge badge-absolute"></div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="max-w-full px-4 truncate box-description" x-text="item.description"></div>
|
||||
<div class="max-w-full px-4 truncate box-description" x-text="item.fqdn"></div>
|
||||
<template x-if="item.server_status == false">
|
||||
<div class="px-4 text-xs font-bold text-error">The underlying server has problems
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</a>
|
||||
<div
|
||||
class="flex flex-wrap gap-1 pt-1 group-hover:dark:text-white group-hover:text-black group min-h-6">
|
||||
<template x-for="tag in item.tags">
|
||||
<div class="tag" @click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
||||
</template>
|
||||
<div class="add-tag" @click.prevent="goto(item)">Add tag</div>
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<template x-if="filteredDatabases.length > 0">
|
||||
<h2 class="pt-4">Databases</h2>
|
||||
</template>
|
||||
<div x-show="filteredDatabases.length > 0"
|
||||
class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<template x-for="item in filteredDatabases" :key="item.uuid">
|
||||
<span>
|
||||
<a class="h-24 box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex gap-2 px-4">
|
||||
<div class="pb-2 truncate box-title" x-text="item.name"></div>
|
||||
<div class="flex-1"></div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div title="running" class="bg-success badge badge-absolute"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div title="exited" class="bg-error badge badge-absolute"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div title="restarting" class="bg-warning badge badge-absolute"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('degraded')">
|
||||
<div title="degraded" class="bg-warning badge badge-absolute"></div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="max-w-full px-4 truncate box-description" x-text="item.description"></div>
|
||||
<div class="max-w-full px-4 truncate box-description" x-text="item.fqdn"></div>
|
||||
<template x-if="item.server_status == false">
|
||||
<div class="px-4 text-xs font-bold text-error">The underlying server has problems
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</a>
|
||||
<div
|
||||
class="flex flex-wrap gap-1 pt-1 group-hover:dark:text-white group-hover:text-black group min-h-6">
|
||||
<template x-for="tag in item.tags">
|
||||
<div class="tag" @click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
||||
</template>
|
||||
<div class="add-tag" @click.prevent="goto(item)">Add tag</div>
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<template x-if="filteredServices.length > 0">
|
||||
<h2 class="pt-4">Services</h2>
|
||||
</template>
|
||||
<div x-show="filteredServices.length > 0"
|
||||
class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<template x-for="item in filteredServices" :key="item.uuid">
|
||||
<span>
|
||||
<a class="h-24 box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col w-full">
|
||||
@@ -134,9 +225,11 @@
|
||||
item.tags?.some(tag => tag.name.toLowerCase().includes(searchLower)));
|
||||
}).sort(sortFn);
|
||||
},
|
||||
get allFilteredItems() {
|
||||
get filteredApplications() {
|
||||
return this.filterAndSort(this.applications)
|
||||
},
|
||||
get filteredDatabases() {
|
||||
return [
|
||||
this.applications,
|
||||
this.postgresqls,
|
||||
this.redis,
|
||||
this.mongodbs,
|
||||
@@ -145,8 +238,10 @@
|
||||
this.keydbs,
|
||||
this.dragonflies,
|
||||
this.clickhouses,
|
||||
this.services
|
||||
].flatMap((items) => this.filterAndSort(items))
|
||||
},
|
||||
get filteredServices() {
|
||||
return this.filterAndSort(this.services)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
</div>
|
||||
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
|
||||
<div class="pb-4 dark:text-warning text-coollabs">If you would like to add a volume, you must add it to
|
||||
your compose file (General tab).</div>
|
||||
your compose file (Service Stack tab).</div>
|
||||
@foreach ($applications as $application)
|
||||
<livewire:project.service.storage wire:key="application-{{ $application->id }}" :resource="$application"
|
||||
lazy />
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<x-forms.textarea rows="20" readonly id="service.docker_compose">
|
||||
</x-forms.textarea>
|
||||
</div>
|
||||
<div class="pt-2 w-72">
|
||||
<div class="pt-2 w-96">
|
||||
<x-forms.checkbox label="Escape special characters in labels?"
|
||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||
id="service.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<div class="flex gap-2 ">
|
||||
<h2 class="pb-4">Scheduled Backups</h2>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
|
||||
<livewire:project.database.create-scheduled-backup :database="$serviceDatabase" :s3s="$s3s" />
|
||||
<livewire:project.database.create-scheduled-backup :database="$serviceDatabase" />
|
||||
</x-modal-input>
|
||||
</div>
|
||||
<livewire:project.database.scheduled-backups :database="$serviceDatabase" />
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
volume
|
||||
name, example: <span class='text-helper'>-pr-1</span>" />
|
||||
@if ($resource?->build_pack !== 'dockercompose')
|
||||
<x-modal-input :closeOutside="false" buttonTitle="+ Add" title="New Persistent Storage">
|
||||
<x-modal-input :closeOutside="false" buttonTitle="+ Add" title="New Persistent Storage" minWidth="64rem">
|
||||
<livewire:project.shared.storages.add :resource="$resource" />
|
||||
</x-modal-input>
|
||||
@endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Environment Variables</h2>
|
||||
<div class="flex flex-col items-center">
|
||||
<x-modal-input buttonTitle="+ Add" title="New Environment Variable">
|
||||
<x-modal-input buttonTitle="+ Add" title="New Environment Variable" :closeOutside="false">
|
||||
<livewire:project.shared.environment-variable.add />
|
||||
</x-modal-input>
|
||||
</div>
|
||||
@@ -38,7 +38,7 @@
|
||||
<div>Environment (secrets) variables for Production.</div>
|
||||
</div>
|
||||
@php
|
||||
$requiredEmptyVars = $resource->environment_variables->filter(function($env) {
|
||||
$requiredEmptyVars = $resource->environment_variables->filter(function ($env) {
|
||||
return $env->is_required && empty($env->value);
|
||||
});
|
||||
$otherVars = $resource->environment_variables->diff($requiredEmptyVars);
|
||||
@@ -62,11 +62,13 @@
|
||||
@endif
|
||||
@else
|
||||
<form wire:submit.prevent='submit' class="flex flex-col gap-2">
|
||||
<x-forms.textarea rows="10" class="whitespace-pre-wrap" id="variables" wire:model="variables" label="Production Environment Variables"></x-forms.textarea>
|
||||
<x-forms.textarea rows="10" class="whitespace-pre-wrap" id="variables" wire:model="variables"
|
||||
label="Production Environment Variables"></x-forms.textarea>
|
||||
|
||||
@if ($showPreview)
|
||||
<x-forms.textarea rows="10" class="whitespace-pre-wrap" label="Preview Deployments Environment Variables"
|
||||
id="variablesPreview" wire:model="variablesPreview"></x-forms.textarea>
|
||||
<x-forms.textarea rows="10" class="whitespace-pre-wrap"
|
||||
label="Preview Deployments Environment Variables" id="variablesPreview"
|
||||
wire:model="variablesPreview"></x-forms.textarea>
|
||||
@endif
|
||||
|
||||
<x-forms.button type="submit" class="btn btn-primary">Save All Environment Variables</x-forms.button>
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
@else
|
||||
@if (count($containers) > 0)
|
||||
@if (count($containers) === 1)
|
||||
<form class="w-full pt-4"
|
||||
wire:submit="$dispatchSelf('connectToContainer')" wire:init="$dispatchSelf('connectToContainer')">
|
||||
<form class="w-full pt-4" wire:submit="$dispatchSelf('connectToContainer')"
|
||||
wire:init="$dispatchSelf('connectToContainer')">
|
||||
<x-forms.button class="w-full" type="submit">Reconnect</x-forms.button>
|
||||
</form>
|
||||
@else
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<div>
|
||||
<div class="flex gap-2">
|
||||
<h2>Scheduled Tasks</h2>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Scheduled Task" :closeOutside=false>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Scheduled Task" :closeOutside="false">
|
||||
@if ($resource->type() == 'application')
|
||||
<livewire:project.shared.scheduled-task.add :type="$resource->type()" :containerNames="$containerNames"/>
|
||||
<livewire:project.shared.scheduled-task.add :type="$resource->type()" :containerNames="$containerNames" />
|
||||
@elseif ($resource->type() == 'service')
|
||||
<livewire:project.shared.scheduled-task.add :type="$resource->type()" :containerNames="$containerNames"/>
|
||||
<livewire:project.shared.scheduled-task.add :type="$resource->type()" :containerNames="$containerNames" />
|
||||
@endif
|
||||
</x-modal-input>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if ($resource->isRunning())
|
||||
<x-forms.button type="button" wire:click="executeNow">
|
||||
Execute Now
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<x-modal-confirmation title="Confirm Scheduled Task Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete({{ $task->id }})" :actions="['The selected scheduled task will be permanently deleted.']" confirmationText="{{ $task->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Scheduled Task Name below"
|
||||
@@ -24,27 +29,26 @@
|
||||
|
||||
</div>
|
||||
<div class="w-48">
|
||||
<x-forms.checkbox instantSave id="task.enabled" label="Enabled" />
|
||||
<x-forms.checkbox instantSave id="isEnabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex gap-2 w-full">
|
||||
<x-forms.input placeholder="Name" id="task.name" label="Name" required />
|
||||
<x-forms.input placeholder="php artisan schedule:run" id="task.command" label="Command" required />
|
||||
<x-forms.input placeholder="0 0 * * * or daily" id="task.frequency" label="Frequency" required />
|
||||
<x-forms.input placeholder="Name" id="name" label="Name" required />
|
||||
<x-forms.input placeholder="php artisan schedule:run" id="command" label="Command" required />
|
||||
<x-forms.input placeholder="0 0 * * * or daily" id="frequency" label="Frequency" required />
|
||||
@if ($type === 'application')
|
||||
<x-forms.input placeholder="php"
|
||||
helper="You can leave this empty if your resource only has one container." id="task.container"
|
||||
helper="You can leave this empty if your resource only has one container." id="container"
|
||||
label="Container name" />
|
||||
@elseif ($type === 'service')
|
||||
<x-forms.input placeholder="php"
|
||||
helper="You can leave this empty if your resource only has one service in your stack. Otherwise use the stack name, without the random generated ID. So if you have a mysql service in your stack, use mysql."
|
||||
id="task.container" label="Service name" />
|
||||
id="container" label="Service name" />
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="pt-4">
|
||||
<h3 class="py-4">Recent executions <span class="text-xs text-neutral-500">(click to check output)</span></h3>
|
||||
<livewire:project.shared.scheduled-task.executions :task="$task" key="{{ $task->id }}" selectedKey=""
|
||||
:executions="$task->executions->take(20)" />
|
||||
<livewire:project.shared.scheduled-task.executions :taskId="$task->id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<div class="flex flex-col w-full gap-2 rounded max-h-[80vh] overflow-y-auto scrollbar">
|
||||
<div class="p-4">
|
||||
You can add Volumes, Files and Directories to your resources here.
|
||||
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitPersistentVolume'>
|
||||
<div class="flex flex-col w-full gap-2 max-h-[80vh] overflow-y-auto scrollbar">
|
||||
<form class="flex flex-col w-full gap-2 rounded " wire:submit='submitPersistentVolume'>
|
||||
<div class="flex flex-col">
|
||||
<h3>Volume Mount</h3>
|
||||
@if ($isSwarm)
|
||||
<h5>Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you
|
||||
would
|
||||
like to use a persistent volumes.</h5>
|
||||
@endif
|
||||
<div>Docker Volumes mounted to the container.</div>
|
||||
</div>
|
||||
@if ($isSwarm)
|
||||
<h5>Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you
|
||||
would
|
||||
like to use a persistent volumes.</h5>
|
||||
@endif
|
||||
<div class="flex flex-col gap-2 px-2">
|
||||
<x-forms.input placeholder="pv-name" id="name" label="Name" required helper="Volume name." />
|
||||
@if ($isSwarm)
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" required
|
||||
@@ -19,29 +21,39 @@
|
||||
<x-forms.input placeholder="/tmp/root" id="mount_path" label="Destination Path" required
|
||||
helper="Directory inside the container." />
|
||||
<x-forms.button type="submit" @click="modalOpen=false">
|
||||
Save
|
||||
Add
|
||||
</x-forms.button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorage'>
|
||||
</form>
|
||||
<form class="flex flex-col w-full gap-2 rounded py-4" wire:submit='submitFileStorage'>
|
||||
<div class="flex flex-col">
|
||||
<h3>File Mount</h3>
|
||||
<div>Actual file mounted from the host system to the container.</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 px-2">
|
||||
<x-forms.input placeholder="/etc/nginx/nginx.conf" id="file_storage_path" label="Destination Path" required
|
||||
helper="File inside the container" />
|
||||
helper="File location inside the container" />
|
||||
<x-forms.textarea label="Content" id="file_storage_content"></x-forms.textarea>
|
||||
<x-forms.button type="submit" @click="modalOpen=false">
|
||||
Save
|
||||
Add
|
||||
</x-forms.button>
|
||||
</form>
|
||||
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorageDirectory'>
|
||||
</div>
|
||||
</form>
|
||||
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorageDirectory'>
|
||||
<div class="flex flex-col">
|
||||
<h3>Directory Mount</h3>
|
||||
<div>Directory mounted from the host system to the container.</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 px-2">
|
||||
<x-forms.input placeholder="{{ application_configuration_dir() }}/{{ $resource->uuid }}/etc/nginx"
|
||||
id="file_storage_directory_source" label="Source Directory" required
|
||||
helper="Directory on the host system." />
|
||||
<x-forms.input placeholder="/etc/nginx" id="file_storage_directory_destination"
|
||||
label="Destination Directory" required helper="Directory inside the container." />
|
||||
<x-forms.button type="submit" @click="modalOpen=false">
|
||||
Save
|
||||
Add
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
<script>
|
||||
// expose terminal config to the terminal.js file
|
||||
window.terminalConfig = {
|
||||
protocol: "{{ env('TERMINAL_PROTOCOL') }}",
|
||||
host: "{{ env('TERMINAL_HOST') }}",
|
||||
port: "{{ env('TERMINAL_PORT') }}"
|
||||
protocol: "{{ config('constants.terminal.protocol') }}",
|
||||
host: "{{ config('constants.terminal.host') }}",
|
||||
port: "{{ config('constants.terminal.port') }}"
|
||||
}
|
||||
</script>
|
||||
@endscript
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</x-modal-input>
|
||||
<livewire:project.delete-project :disabled="$project->resource_count() > 0" :project_id="$project->id" />
|
||||
<livewire:project.delete-project :disabled="!$project->isEmpty()" :project_id="$project->id" />
|
||||
</div>
|
||||
<div class="text-xs truncate subtitle lg:text-sm">{{ $project->name }}.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
|
||||
@@ -35,10 +35,15 @@
|
||||
@endif
|
||||
<h4>Token Permissions</h4>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox label="read" wire:model.live="permissions" domValue="read" :checked="in_array('read', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="read:sensitive" wire:model.live="permissions" domValue="read:sensitive" helper="Responses will include secrets, logs, passwords, and compose file contents" :checked="in_array('read:sensitive', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="write" wire:model.live="permissions" domValue="write" helper="Root access, be careful!" :checked="in_array('write', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="deploy" wire:model.live="permissions" domValue="deploy" helper="Can trigger deploy webhooks" :checked="in_array('deploy', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="read" wire:model.live="permissions" value="read"
|
||||
:checked="in_array('read', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="read:sensitive" wire:model.live="permissions" value="read:sensitive"
|
||||
helper="Responses will include secrets, logs, passwords, and compose file contents"
|
||||
:checked="in_array('read:sensitive', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="write" wire:model.live="permissions" value="write"
|
||||
helper="Root access, be careful!" :checked="in_array('write', $permissions)"></x-forms.checkbox>
|
||||
<x-forms.checkbox label="deploy" wire:model.live="permissions" value="deploy"
|
||||
helper="Can trigger deploy webhooks" :checked="in_array('deploy', $permissions)"></x-forms.checkbox>
|
||||
</div>
|
||||
</form>
|
||||
@if (session()->has('token'))
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
<x-helper class="inline-flex"
|
||||
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br> You then can close your server's SSH port in the firewall of your hosting provider.<br><span class='dark:text-warning'>If you choose manual configuration, Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" />
|
||||
</div>
|
||||
<div>Secure your servers with Cloudflare Tunnels</div>
|
||||
|
||||
<div>Secure your servers with Cloudflare Tunnels.</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 pt-6">
|
||||
@if ($isCloudflareTunnelsEnabled)
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
<div>
|
||||
<form wire:submit.prevent='submit' class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<h2>General</h2>
|
||||
@if ($server->id === 0)
|
||||
<x-modal-confirmation title="Confirm Server Settings Change?" buttonTitle="Save" submitAction="submit"
|
||||
:actions="[
|
||||
'You could lose a lot of functionalities if you change the server details of the server where Coolify is running on.',
|
||||
]" :confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Save" />
|
||||
@else
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
@if ($server->isFunctional())
|
||||
<x-slide-over closeWithX fullScreen>
|
||||
<x-slot:title>Validate & configure</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:server.validate-and-install :server="$server" ask />
|
||||
</x-slot:content>
|
||||
<x-forms.button @click="slideOverOpen=true" wire:click.prevent='validateServer' isHighlighted>
|
||||
Revalidate server
|
||||
</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->isFunctional())
|
||||
Server is reachable and validated.
|
||||
@else
|
||||
You can't use this server until it is validated.
|
||||
@endif
|
||||
@if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id !== 0)
|
||||
<x-slide-over closeWithX fullScreen>
|
||||
<x-slot:title>Validate & configure</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:server.validate-and-install :server="$server" />
|
||||
</x-slot:content>
|
||||
<x-forms.button @click="slideOverOpen=true"
|
||||
class="mt-8 mb-4 w-full font-bold box-without-bg bg-coollabs hover:bg-coollabs-100"
|
||||
wire:click.prevent='validateServer' isHighlighted>
|
||||
Validate Server & Install Docker Engine
|
||||
</x-forms.button>
|
||||
</x-slide-over>
|
||||
@if ($server->validation_logs)
|
||||
<h4>Previous Validation Logs</h4>
|
||||
<div class="pb-8">
|
||||
{!! $server->validation_logs !!}
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
@if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id === 0)
|
||||
<x-forms.button class="mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100"
|
||||
wire:click.prevent='checkLocalhostConnection' isHighlighted>
|
||||
Validate Server
|
||||
</x-forms.button>
|
||||
@endif
|
||||
@if ($server->isForceDisabled() && isCloud())
|
||||
<div class="pt-4 font-bold text-red-500">The system has disabled the server because you have exceeded the
|
||||
number of servers for which you have paid.</div>
|
||||
@endif
|
||||
<div class="flex flex-col gap-2 pt-4">
|
||||
<div class="flex flex-col gap-2 w-full lg:flex-row">
|
||||
<x-forms.input id="server.name" label="Name" required />
|
||||
<x-forms.input id="server.description" label="Description" />
|
||||
@if (!$server->settings->is_swarm_worker && !$server->settings->is_build_server)
|
||||
<x-forms.input placeholder="https://example.com" id="wildcard_domain" label="Wildcard Domain"
|
||||
helper='A wildcard domain allows you to receive a randomly generated domain for your new applications. <br><br>For instance, if you set "https://example.com" as your wildcard domain, your applications will receive domains like "https://randomId.example.com".' />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 w-full lg:flex-row">
|
||||
<x-forms.input type="password" id="server.ip" label="IP Address/Domain"
|
||||
helper="An IP Address (127.0.0.1) or domain (example.com). Make sure there is no protocol like http(s):// so you provide a FQDN not a URL."
|
||||
required />
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="server.user" label="User" required />
|
||||
<x-forms.input type="number" id="server.port" label="Port" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full" x-data="{
|
||||
open: false,
|
||||
search: '{{ $server->settings->server_timezone ?: '' }}',
|
||||
timezones: @js($timezones),
|
||||
placeholder: '{{ $server->settings->server_timezone ? 'Search timezone...' : 'Select Server Timezone' }}',
|
||||
init() {
|
||||
this.$watch('search', value => {
|
||||
if (value === '') {
|
||||
this.open = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
}">
|
||||
<div class="flex items-center mb-1">
|
||||
<label for="server.settings.server_timezone">Server
|
||||
Timezone</label>
|
||||
<x-helper class="ml-2" helper="Server's timezone. This is used for backups, cron jobs, etc." />
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="inline-flex relative items-center w-64">
|
||||
<input autocomplete="off"
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300'
|
||||
wire:dirty.class="dark:focus:ring-warning dark:ring-warning" x-model="search"
|
||||
@focus="open = true" @click.away="open = false" @input="open = true" class="w-full input"
|
||||
:placeholder="placeholder" wire:model.debounce.300ms="server.settings.server_timezone">
|
||||
<svg class="absolute right-0 mr-2 w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" @click="open = true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" />
|
||||
</svg>
|
||||
</div>
|
||||
<div x-show="open"
|
||||
class="overflow-auto overflow-x-hidden absolute z-50 mt-1 w-64 max-h-60 bg-white rounded-md border shadow-lg dark:bg-coolgray-100 dark:border-coolgray-200 scrollbar">
|
||||
<template
|
||||
x-for="timezone in timezones.filter(tz => tz.toLowerCase().includes(search.toLowerCase()))"
|
||||
:key="timezone">
|
||||
<div @click="search = timezone; open = false; $wire.set('server.settings.server_timezone', timezone)"
|
||||
class="px-4 py-2 text-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-coolgray-300 dark:text-gray-200"
|
||||
x-text="timezone"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
@if (!$server->isLocalhost())
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="server.settings.is_build_server"
|
||||
label="Use it as a build server?" />
|
||||
</div>
|
||||
|
||||
@if (!$server->isBuildServer() && !$server->settings->is_cloudflare_tunnel)
|
||||
<h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span></h3>
|
||||
<div class="pb-4">Read the docs <a class='underline dark:text-white'
|
||||
href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>.
|
||||
</div>
|
||||
<div class="w-96">
|
||||
@if ($server->settings->is_swarm_worker)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox"
|
||||
id="server.settings.is_swarm_manager"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Manager?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Manager?" />
|
||||
@endif
|
||||
|
||||
@if ($server->settings->is_swarm_manager)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox"
|
||||
id="server.settings.is_swarm_worker"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Worker?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Worker?" />
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@if ($server->isFunctional() && !$server->isSwarm() && !$server->isBuildServer())
|
||||
<form wire:submit.prevent='saveSentinel'>
|
||||
<div class="flex gap-2 items-center pt-4 pb-2">
|
||||
<h3>Sentinel</h3>
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex gap-2 items-center">
|
||||
@if ($server->isSentinelLive())
|
||||
<x-status.running status="In sync" noLoading title="{{ $server->sentinel_updated_at }}" />
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel'>Restart</x-forms.button>
|
||||
@else
|
||||
<x-status.stopped status="Out of sync" noLoading
|
||||
title="{{ $server->sentinel_updated_at }}" />
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel'>Sync</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">Experimental feature <x-helper
|
||||
helper="Sentinel reports your server's & container's health and collects metrics." /></div>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox wire:model.live="server.settings.is_sentinel_enabled" label="Enable Sentinel" />
|
||||
@if ($server->isSentinelEnabled())
|
||||
<x-forms.checkbox id="server.settings.is_sentinel_debug_enabled" label="Enable Sentinel Debug"
|
||||
instantSave />
|
||||
<x-forms.checkbox instantSave id="server.settings.is_metrics_enabled"
|
||||
label="Enable Metrics" />
|
||||
@else
|
||||
<x-forms.checkbox id="server.settings.is_sentinel_debug_enabled" label="Enable Sentinel Debug"
|
||||
disabled instantSave />
|
||||
<x-forms.checkbox instantSave disabled id="server.settings.is_metrics_enabled"
|
||||
label="Enable Metrics" />
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap items-end">
|
||||
<x-forms.input type="password" id="server.settings.sentinel_token" label="Sentinel token"
|
||||
required helper="Token for Sentinel." />
|
||||
<x-forms.button wire:click="regenerateSentinelToken">Regenerate</x-forms.button>
|
||||
</div>
|
||||
|
||||
<x-forms.input id="server.settings.sentinel_custom_url" required label="Coolify URL"
|
||||
helper="URL to your Coolify instance. If it is empty that means you do not have a FQDN set for your Coolify instance." />
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input id="server.settings.sentinel_metrics_refresh_rate_seconds"
|
||||
label="Metrics rate (seconds)" required
|
||||
helper="The interval for gathering metrics. Lower means more disk space will be used." />
|
||||
<x-forms.input id="server.settings.sentinel_metrics_history_days"
|
||||
label="Metrics history (days)" required
|
||||
helper="How many days should the metrics data should be reserved." />
|
||||
<x-forms.input id="server.settings.sentinel_push_interval_seconds"
|
||||
label="Push interval (seconds)" required
|
||||
helper="How many seconds should the metrics data should be pushed to the collector." />
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@@ -11,7 +11,7 @@
|
||||
<h2>Log Drains</h2>
|
||||
<x-loading wire:target="instantSave" wire:loading.delay />
|
||||
</div>
|
||||
<div class="">Sends service logs to 3rd party tools.</div>
|
||||
<div>Sends service logs to 3rd party tools.</div>
|
||||
<div class="flex flex-col gap-4 pt-4">
|
||||
<div class="p-4 border dark:border-coolgray-300">
|
||||
<form wire:submit='submit("newrelic")' class="flex flex-col">
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
helper="If set, all resources will only have docker container labels for {{ str($server->proxyType())->title() }}.<br>For applications, labels needs to be regenerated manually. <br>Resources needs to be restarted."
|
||||
id="server.settings.generate_exact_labels"
|
||||
label="Generate labels only for {{ str($server->proxyType())->title() }}" instantSave />
|
||||
<x-forms.checkbox instantSave="instantSaveRedirect" id="redirect_enabled"
|
||||
label="Override default request handler"
|
||||
helper="Requests to unknown hosts or stopped services will recieve a 503 response or be redirected to the URL you set below (need to enable this first)." />
|
||||
@if ($redirect_enabled)
|
||||
<x-forms.input placeholder="https://app.coolify.io" id="redirect_url"
|
||||
label="Redirect to (optional)" />
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->proxyType() === ProxyTypes::TRAEFIK->value)
|
||||
<h4>Traefik</h4>
|
||||
@@ -40,8 +47,6 @@
|
||||
configurations.
|
||||
</div>
|
||||
@endif
|
||||
<x-forms.input placeholder="https://app.coolify.io" id="redirect_url" label="Default Redirect 404"
|
||||
helper="All urls that has no service available will be redirected to this domain." />
|
||||
<div wire:loading wire:target="loadProxyConfiguration" class="pt-4">
|
||||
<x-loading text="Loading proxy configuration..." />
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
@if (str_replace('|', '.', $fileName) === 'coolify.yaml' ||
|
||||
str_replace('|', '.', $fileName) === 'Caddyfile' ||
|
||||
str_replace('|', '.', $fileName) === 'coolify.caddy' ||
|
||||
str_replace('|', '.', $fileName) === 'default_redirect_404.caddy')
|
||||
str_replace('|', '.', $fileName) === 'default_redirect_503.yaml' ||
|
||||
str_replace('|', '.', $fileName) === 'default_redirect_503.caddy')
|
||||
<div>
|
||||
<h3 class="dark:text-white">File: {{ str_replace('|', '.', $fileName) }}</h3>
|
||||
</div>
|
||||
|
||||
@@ -71,8 +71,7 @@
|
||||
<x-forms.input id="name" label="Name" required />
|
||||
<x-forms.input id="description" label="Description" />
|
||||
@if (!$isSwarmWorker && !$isBuildServer)
|
||||
<x-forms.input placeholder="https://example.com" id="wildcard_domain"
|
||||
label="Wildcard Domain"
|
||||
<x-forms.input placeholder="https://example.com" id="wildcardDomain" label="Wildcard Domain"
|
||||
helper='A wildcard domain allows you to receive a randomly generated domain for your new applications. <br><br>For instance, if you set "https://example.com" as your wildcard domain, your applications will receive domains like "https://randomId.example.com".' />
|
||||
@endif
|
||||
|
||||
@@ -89,7 +88,7 @@
|
||||
<div class="w-full" x-data="{
|
||||
open: false,
|
||||
search: '{{ $serverTimezone ?: '' }}',
|
||||
timezones: @js($timezones),
|
||||
timezones: @js($this->timezones),
|
||||
placeholder: '{{ $serverTimezone ? 'Search timezone...' : 'Select Server Timezone' }}',
|
||||
init() {
|
||||
this.$watch('search', value => {
|
||||
@@ -111,8 +110,7 @@
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300'
|
||||
wire:dirty.class="dark:focus:ring-warning dark:ring-warning" x-model="search"
|
||||
@focus="open = true" @click.away="open = false" @input="open = true"
|
||||
class="w-full input" :placeholder="placeholder"
|
||||
wire:model.debounce.300ms="serverTimezone">
|
||||
class="w-full input" :placeholder="placeholder" wire:model="serverTimezone">
|
||||
<svg class="absolute right-0 mr-2 w-4 h-4" xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
@click="open = true">
|
||||
@@ -125,7 +123,7 @@
|
||||
<template
|
||||
x-for="timezone in timezones.filter(tz => tz.toLowerCase().includes(search.toLowerCase()))"
|
||||
:key="timezone">
|
||||
<div @click="search = timezone; open = false; $wire.set('server.settings.server_timezone', timezone)"
|
||||
<div @click="search = timezone; open = false; $wire.set('serverTimezone', timezone); $wire.submit()"
|
||||
class="px-4 py-2 text-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-coolgray-300 dark:text-gray-200"
|
||||
x-text="timezone"></div>
|
||||
</template>
|
||||
@@ -221,12 +219,12 @@
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input id="sentinelMetricsRefreshRateSeconds"
|
||||
label="Metrics rate (seconds)" required
|
||||
helper="The interval for gathering metrics. Lower means more disk space will be used." />
|
||||
helper="Interval used for gathering metrics. Lower values result in more disk space usage." />
|
||||
<x-forms.input id="sentinelMetricsHistoryDays" label="Metrics history (days)"
|
||||
required helper="How many days should the metrics data should be reserved." />
|
||||
required helper="Number of days to retain metrics data for." />
|
||||
<x-forms.input id="sentinelPushIntervalSeconds" label="Push interval (seconds)"
|
||||
required
|
||||
helper="How many seconds should the metrics data should be pushed to the collector." />
|
||||
helper="Interval at which metrics data is sent to the collector." />
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -86,16 +86,24 @@
|
||||
</g>
|
||||
</svg></div>
|
||||
@isset($docker_version)
|
||||
@if($docker_version)
|
||||
<div class="flex w-64 gap-2">Minimum Docker version: <svg class="w-5 h-5 text-success"
|
||||
viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="currentColor">
|
||||
<path
|
||||
d="m237.66 85.26l-128.4 128.4a8 8 0 0 1-11.32 0l-71.6-72a8 8 0 0 1 0-11.31l24-24a8 8 0 0 1 11.32 0l36.68 35.32a8 8 0 0 0 11.32 0l92.68-91.32a8 8 0 0 1 11.32 0l24 23.6a8 8 0 0 1 0 11.31"
|
||||
opacity=".2" />
|
||||
<path
|
||||
d="m243.28 68.24l-24-23.56a16 16 0 0 0-22.58 0L104 136l-.11-.11l-36.64-35.27a16 16 0 0 0-22.57.06l-24 24a16 16 0 0 0 0 22.61l71.62 72a16 16 0 0 0 22.63 0l128.4-128.38a16 16 0 0 0-.05-22.67M103.62 208L32 136l24-24l.11.11l36.64 35.27a16 16 0 0 0 22.52 0L208.06 56L232 79.6Z" />
|
||||
</g>
|
||||
</svg></div>
|
||||
@else
|
||||
<div class="flex w-64 gap-2">Minimum Docker version: <svg class="w-5 h-5 text-error"
|
||||
viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="currentColor">
|
||||
<path
|
||||
d="m237.66 85.26l-128.4 128.4a8 8 0 0 1-11.32 0l-71.6-72a8 8 0 0 1 0-11.31l24-24a8 8 0 0 1 11.32 0l36.68 35.32a8 8 0 0 0 11.32 0l92.68-91.32a8 8 0 0 1 11.32 0l24 23.6a8 8 0 0 1 0 11.31"
|
||||
opacity=".2" />
|
||||
<path
|
||||
d="m243.28 68.24l-24-23.56a16 16 0 0 0-22.58 0L104 136l-.11-.11l-36.64-35.27a16 16 0 0 0-22.57.06l-24 24a16 16 0 0 0 0 22.61l71.62 72a16 16 0 0 0 22.63 0l128.4-128.38a16 16 0 0 0-.05-22.67M103.62 208L32 136l24-24l.11.11l36.64 35.27a16 16 0 0 0 22.52 0L208.06 56L232 79.6Z" />
|
||||
</g>
|
||||
<path fill="currentColor"
|
||||
d="M208.49 191.51a12 12 0 0 1-17 17L128 145l-63.51 63.49a12 12 0 0 1-17-17L111 128L47.51 64.49a12 12 0 0 1 17-17L128 111l63.51-63.52a12 12 0 0 1 17 17L145 128Z" />
|
||||
</svg></div>
|
||||
@endif
|
||||
@else
|
||||
<div class="w-64"><x-loading text="Minimum Docker version:" /></div>
|
||||
@endisset
|
||||
|
||||
@@ -33,8 +33,11 @@
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input required id="smtpHost" placeholder="smtp.mailgun.org" label="Host" />
|
||||
<x-forms.input required id="smtpPort" placeholder="587" label="Port" />
|
||||
<x-forms.input id="smtpEncryption" helper="If SMTP uses SSL, set it to 'tls'." placeholder="tls"
|
||||
label="Encryption" />
|
||||
<x-forms.select id="smtpEncryption" label="Encryption">
|
||||
<option value="tls">TLS</option>
|
||||
<option value="ssl">SSL</option>
|
||||
<option value="none">None</option>
|
||||
</x-forms.select>
|
||||
</div>
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input id="smtpUsername" label="SMTP Username" />
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<div class="w-full" x-data="{
|
||||
open: false,
|
||||
search: '{{ $settings->instance_timezone ?: '' }}',
|
||||
timezones: @js($timezones),
|
||||
timezones: @js($this->timezones),
|
||||
placeholder: '{{ $settings->instance_timezone ? 'Search timezone...' : 'Select Server Timezone' }}',
|
||||
init() {
|
||||
this.$watch('search', value => {
|
||||
@@ -40,14 +40,13 @@
|
||||
helper="Timezone for the Coolify instance. This is used for the update check and automatic update frequency." />
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="inline-flex items-center relative w-full">
|
||||
<div class="inline-flex relative items-center w-full">
|
||||
<input autocomplete="off"
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300'
|
||||
wire:dirty.class="dark:focus:ring-warning dark:ring-warning" x-model="search"
|
||||
@focus="open = true" @click.away="open = false" @input="open = true"
|
||||
class="w-full input " :placeholder="placeholder"
|
||||
wire:model.debounce.300ms="instance_timezone">
|
||||
<svg class="absolute right-0 w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-full input" :placeholder="placeholder" wire:model="instance_timezone">
|
||||
<svg class="absolute right-0 mr-2 w-4 h-4" xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
@click="open = true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
@@ -55,26 +54,25 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div x-show="open"
|
||||
class="absolute z-50 w-full mt-1 bg-white dark:bg-coolgray-100 border dark:border-coolgray-200 rounded-md shadow-lg max-h-60 overflow-auto scrollbar overflow-x-hidden">
|
||||
class="overflow-auto overflow-x-hidden absolute z-50 mt-1 w-full max-h-60 bg-white rounded-md border shadow-lg dark:bg-coolgray-100 dark:border-coolgray-200 scrollbar">
|
||||
<template
|
||||
x-for="timezone in timezones.filter(tz => tz.toLowerCase().includes(search.toLowerCase()))"
|
||||
:key="timezone">
|
||||
<div @click="search = timezone; open = false; $wire.set('instance_timezone', timezone)"
|
||||
class="px-4 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-coolgray-300 text-gray-800 dark:text-gray-200"
|
||||
<div @click="search = timezone; open = false; $wire.set('instance_timezone', timezone); $wire.submit()"
|
||||
class="px-4 py-2 text-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-coolgray-300 dark:text-gray-200"
|
||||
x-text="timezone"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<div class="flex gap-2 md:flex-row flex-col w-full">
|
||||
<x-forms.input id="public_ipv4" type="password" label="Instance's IPv4"
|
||||
helper="Enter the IPv4 address of the instance.<br><br>It is useful if you have several IPv4 addresses and Coolify could not detect the correct one."
|
||||
placeholder="1.2.3.4" />
|
||||
placeholder="1.2.3.4" autocomplete="new-password" />
|
||||
<x-forms.input id="public_ipv6" type="password" label="Instance's IPv6"
|
||||
helper="Enter the IPv6 address of the instance.<br><br>It is useful if you have several IPv6 addresses and Coolify could not detect the correct one."
|
||||
placeholder="2001:db8::1" />
|
||||
placeholder="2001:db8::1" autocomplete="new-password" />
|
||||
</div>
|
||||
<h4 class="w-full pt-6">DNS Validation</h4>
|
||||
<div class="md:w-96">
|
||||
@@ -92,24 +90,20 @@
|
||||
|
||||
</div>
|
||||
<h4 class="pt-6">API</h4>
|
||||
<div class="pb-4">For API documentation, please visit <a class="dark:text-warning underline"
|
||||
href="/docs/api">/docs/api</a></div>
|
||||
<div class="md:w-96 pb-2">
|
||||
<x-forms.checkbox instantSave id="is_api_enabled" label="Enabled" />
|
||||
</div>
|
||||
<x-forms.input id="allowed_ips" label="Allowed IPs"
|
||||
helper="Allowed IP lists for the API. A comma separated list of IPs. Empty means you allow from everywhere."
|
||||
placeholder="1.1.1.1,8.8.8.8" />
|
||||
|
||||
<h4 class="pt-6">Advanced</h4>
|
||||
<div class="text-right md:w-96">
|
||||
<x-forms.checkbox instantSave id="is_registration_enabled" label="Registration Allowed" />
|
||||
<x-forms.checkbox instantSave id="do_not_track" label="Do Not Track" />
|
||||
</div>
|
||||
<h4 class="pt-6">Update</h4>
|
||||
<div class="text-right md:w-96">
|
||||
@if (!is_null(env('AUTOUPDATE', null)))
|
||||
@if (!is_null(config('constants.coolify.autoupdate', null)))
|
||||
<div class="text-right md:w-96">
|
||||
<x-forms.checkbox instantSave helper="AUTOUPDATE is set in .env file, you need to modify it there."
|
||||
disabled id="is_auto_update_enabled" label="Enabled" />
|
||||
disabled checked="{{ config('constants.coolify.autoupdate') }}" label="Auto Update Enabled" />
|
||||
</div>
|
||||
@else
|
||||
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Auto Update Enabled" />
|
||||
@@ -123,7 +117,7 @@
|
||||
<x-forms.button wire:click='checkManually'>Check Manually</x-forms.button>
|
||||
</div>
|
||||
|
||||
@if (is_null(env('AUTOUPDATE', null)) && $is_auto_update_enabled)
|
||||
@if (is_null(config('constants.coolify.autoupdate', null)) && $is_auto_update_enabled)
|
||||
<x-forms.input required id="auto_update_frequency" label="Auto Update Frequency" placeholder="0 0 * * *"
|
||||
helper="Cron expression for auto update frequency (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
||||
@endif
|
||||
@@ -135,30 +129,48 @@
|
||||
<x-forms.checkbox instantSave id="do_not_track" label="Do Not Track" />
|
||||
</div>
|
||||
|
||||
<h5 class="py-4 font-bold text-white">Confirmation Settings</h5>
|
||||
@if ($disable_two_step_confirmation)
|
||||
<div class="md:w-96 pb-4">
|
||||
<x-forms.checkbox instantSave id="disable_two_step_confirmation" label="Disable Two Step Confirmation"
|
||||
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
|
||||
<h4 class="py-4">Confirmation Settings</h4>
|
||||
<div x-data="{ open: false }" class="mb-32 md:w-[40rem]">
|
||||
<button type="button" @click.prevent="open = !open"
|
||||
class="flex items-center justify-between w-full p-4 rounded-md
|
||||
dark:bg-coolgray-100 dark:hover:bg-coolgray-200
|
||||
bg-gray-100 hover:bg-gray-200">
|
||||
<span class="font-medium">Two-Step Confirmation Settings</span>
|
||||
<svg class="w-5 h-5 transition-transform" :class="{ 'rotate-180': open }" fill="none"
|
||||
stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div x-show="open" x-transition class="mt-4">
|
||||
@if ($disable_two_step_confirmation)
|
||||
<div class="md:w-96 pb-4">
|
||||
<x-forms.checkbox instantSave id="disable_two_step_confirmation"
|
||||
label="Disable Two Step Confirmation"
|
||||
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
|
||||
</div>
|
||||
@else
|
||||
<div class="md:w-96 pb-4">
|
||||
<x-modal-confirmation title="Disable Two Step Confirmation?"
|
||||
buttonTitle="Disable Two Step Confirmation" isErrorButton
|
||||
submitAction="toggleTwoStepConfirmation" :actions="[
|
||||
'Tow Step confimation will be disabled globally.',
|
||||
'Disabling two step confirmation reduces security (as anyone can easily delete anything).',
|
||||
'The risk of accidental actions will increase.',
|
||||
]"
|
||||
confirmationText="DISABLE TWO STEP CONFIRMATION"
|
||||
confirmationLabel="Please type the confirmation text to disable two step confirmation."
|
||||
shortConfirmationLabel="Confirmation text"
|
||||
step3ButtonText="Disable Two Step Confirmation" />
|
||||
</div>
|
||||
<div class="w-full px-4 py-2 mb-4 text-white rounded-sm border-l-4 border-red-500 bg-error">
|
||||
<p class="font-bold">Warning!</p>
|
||||
<p>Disabling two step confirmation reduces security (as anyone can easily delete anything) and
|
||||
increases
|
||||
the risk of accidental actions. This is not recommended for production servers.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="md:w-96 pb-4">
|
||||
<x-modal-confirmation title="Disable Two Step Confirmation?"
|
||||
buttonTitle="Disable Two Step Confirmation" isErrorButton submitAction="toggleTwoStepConfirmation"
|
||||
:actions="[
|
||||
'Tow Step confimation will be disabled globally.',
|
||||
'Disabling two step confirmation reduces security (as anyone can easily delete anything).',
|
||||
'The risk of accidental actions will increase.',
|
||||
]" confirmationText="DISABLE TWO STEP CONFIRMATION"
|
||||
confirmationLabel="Please type the confirmation text to disable two step confirmation."
|
||||
shortConfirmationLabel="Confirmation text" step3ButtonText="Disable Two Step Confirmation" />
|
||||
</div>
|
||||
<div class="p-4 mb-4 text-white border-l-4 border-red-500 bg-error md:w-[40rem] w-full mb-32">
|
||||
<p class="font-bold">Warning!</p>
|
||||
<p>Disabling two step confirmation reduces security (as anyone can easily delete anything) and increases
|
||||
the
|
||||
risk of accidental actions. This is not recommended for production servers.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<div>
|
||||
<x-settings.navbar />
|
||||
<h2>Resale License</h2>
|
||||
<form wire:submit='submit' class="flex flex-col gap-2">
|
||||
<div>
|
||||
@if ($settings->is_resale_license_active)
|
||||
<div class="text-success">License is active</div>
|
||||
@else
|
||||
<div class="text-error">License is not active</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input type="password" id="settings.resale_license"
|
||||
placeholder="eg: BE558E91-0CC5-4AA2-B1C0-B6403C2988DD" label="License Key" />
|
||||
<x-forms.input type="password" id="instance_id" label="Instance Id (do not change this)" disabled />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.button type="submit">
|
||||
Check License
|
||||
</x-forms.button>
|
||||
</div>
|
||||
@if (session()->has('error'))
|
||||
<div class="text-error">
|
||||
{!! session('error') !!}
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
@@ -58,7 +58,18 @@
|
||||
@else
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="github_app.name" label="App Name" disabled />
|
||||
<div class="flex items-end gap-2 w-full">
|
||||
<x-forms.input id="github_app.name" label="App Name" disabled />
|
||||
<x-forms.button wire:click.prevent="updateGithubAppName" class="bg-coollabs">
|
||||
Sync Name
|
||||
</x-forms.button>
|
||||
<a href="{{ $this->getGithubAppNameUpdatePath() }}">
|
||||
<x-forms.button>
|
||||
Rename
|
||||
<x-external-link />
|
||||
</x-forms.button>
|
||||
</a>
|
||||
</div>
|
||||
<x-forms.input id="github_app.organization" label="Organization" disabled
|
||||
placeholder="If empty, personal user will be used" />
|
||||
</div>
|
||||
@@ -254,7 +265,7 @@
|
||||
const name = @js($name);
|
||||
const isDev = @js(config('app.env')) ===
|
||||
'local';
|
||||
const devWebhook = @js(config('coolify.dev_webhook'));
|
||||
const devWebhook = @js(config('constants.webhooks.dev_webhook'));
|
||||
if (isDev && devWebhook) {
|
||||
baseUrl = devWebhook;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<div class="w-full">
|
||||
<div class="mb-4">For more details, please visit the <a class="underline dark:text-warning"
|
||||
href="https://coolify.io/docs/knowledge-base/s3" target="_blank">Coolify Docs</a>.</div>
|
||||
<form class="flex flex-col gap-2" wire:submit='submit'>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input required label="Name" id="name" />
|
||||
@@ -7,14 +9,15 @@
|
||||
<x-forms.input required type="url" label="Endpoint" wire:model.blur="endpoint" />
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input required label="Bucket" id="bucket" />
|
||||
<x-forms.input required label="Region" id="region" />
|
||||
<x-forms.input required helper="Region only required for AWS. Leave it as-is for other providers."
|
||||
label="Region" id="region" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input required type="password" label="Access Key" id="key" />
|
||||
<x-forms.input required type="password" label="Secret Key" id="secret" />
|
||||
</div>
|
||||
|
||||
<x-forms.button type="submit">
|
||||
<x-forms.button class="mt-4" type="submit">
|
||||
Validate Connection & Continue
|
||||
</x-forms.button>
|
||||
</form>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
@if (!$storage->is_usable)
|
||||
<div class="text-red-500">Not Usable</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
If you have any problems, please <a class="underline dark:text-white" href="{{ config('coolify.contact') }}"
|
||||
If you have any problems, please <a class="underline dark:text-white" href="{{ config('constants.urls.contact') }}"
|
||||
target="_blank">contact us.</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<x-forms.select wire:model.live="selectedTeamId" label="Current Team">
|
||||
<option value="default" disabled selected>Switch team</option>
|
||||
@foreach (auth()->user()->teams as $team)
|
||||
<option value="{{ $team->id }}">{{ $team->name }}</option>
|
||||
<option value="{{ $team->id }}">{{ $team->name }}</option>
|
||||
@endforeach
|
||||
</x-forms.select>
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
<div>
|
||||
<h1>Tags</h1>
|
||||
<div class="flex flex-col pb-6">
|
||||
<div class="subtitle">Tags help you to perform actions on multiple resources.</div>
|
||||
<div class="">
|
||||
@if ($tags->count() === 0)
|
||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||
@else
|
||||
<x-forms.datalist wire:model="tag" onUpdate='tagUpdated'>
|
||||
@foreach ($tags as $oneTag)
|
||||
<option value="{{ $oneTag->name }}">{{ $oneTag->name }}</option>
|
||||
@endforeach
|
||||
</x-forms.datalist>
|
||||
@if ($tag)
|
||||
<div class="pt-5">
|
||||
<div class="flex items-end gap-2 ">
|
||||
<div class="w-[500px]">
|
||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||
</div>
|
||||
<x-modal-confirmation title="Redeploy all resources with this tag?" isHighlighted
|
||||
buttonTitle="Redeploy All" submitAction="redeployAll" :actions="[
|
||||
'All resources with this tag will be redeployed.',
|
||||
'During redeploy resources will be temporarily unavailable.',
|
||||
]"
|
||||
confirmationText="{{ $tag }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Tag Name below"
|
||||
shortConfirmationLabel="Tag Name" :confirmWithPassword="false" step2ButtonText="Redeploy All" />
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
@foreach ($applications as $application)
|
||||
<a href="{{ $application->link() }}"class="box group">
|
||||
<div class="flex flex-col">
|
||||
<div class="box-title">{{ $application->name }}</div>
|
||||
<div class="box-description">
|
||||
{{ $application->project()->name }}/{{ $application->environment->name }}
|
||||
</div>
|
||||
<div class="box-description">{{ $application->description }}</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
@foreach ($services as $service)
|
||||
<a href="{{ $service->link() }}" class="box group">
|
||||
<div class="flex flex-col ">
|
||||
<div class="box-title">{{ $service->name }}</div>
|
||||
<div class="box-description">
|
||||
{{ $service->project()->name }}/{{ $service->environment->name }}</div>
|
||||
<div class="box-description">{{ $service->description }}</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deploymentsPerTagPerServer) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
</div>
|
||||
<livewire:tags.deployments :deploymentsPerTagPerServer="$deploymentsPerTagPerServer" :resourceIds="$applications->pluck('id')" />
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,87 +1,96 @@
|
||||
<div>
|
||||
<div class="flex items-start gap-2">
|
||||
<div class="flex items-start gap-2 pb-10">
|
||||
<div>
|
||||
<h1>Tags</h1>
|
||||
<div>Tags help you to perform actions on multiple resources.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 pb-6 ">
|
||||
<div>Available tags</div>
|
||||
<div class="flex flex-wrap gap-2 ">
|
||||
@forelse ($tags as $oneTag)
|
||||
<a :class="{{ $tag->id == $oneTag->id }} && 'bg-coollabs hover:bg-coollabs-100'" class="w-64 box"
|
||||
href="{{ route('tags.show', ['tag_name' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
||||
@empty
|
||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 ">
|
||||
@forelse ($tags as $oneTag)
|
||||
<a :class="{{ $tag?->id == $oneTag->id }} && 'dark:bg-coollabs hover:bg-coollabs-100'"
|
||||
class="w-64 box-without-bg dark:bg-coolgray-100 dark:text-white font-bold"
|
||||
href="{{ route('tags.show', ['tagName' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
||||
@empty
|
||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="py-4">Details</h3>
|
||||
<div class="flex items-end gap-2 ">
|
||||
<div class="w-[500px]">
|
||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||
@if (isset($tag))
|
||||
<div>
|
||||
<h3 class="py-4">Details</h3>
|
||||
<div class="flex items-end gap-2 ">
|
||||
<div class="w-[500px]">
|
||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||
</div>
|
||||
<x-modal-confirmation title="Redeploy all resources with this tag?" isHighlighted
|
||||
buttonTitle="Redeploy All" submitAction="redeployAll" :actions="[
|
||||
'All resources with this tag will be redeployed.',
|
||||
'During redeploy resources will be temporarily unavailable.',
|
||||
]"
|
||||
confirmationText="{{ $tag->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Tag Name below"
|
||||
shortConfirmationLabel="Tag Name" :confirmWithPassword="false" step2ButtonText="Redeploy All" />
|
||||
</div>
|
||||
<x-modal-confirmation title="Redeploy all resources with this tag?" isHighlighted buttonTitle="Redeploy All"
|
||||
submitAction="redeploy_all" :actions="[
|
||||
'All resources with this tag will be redeployed.',
|
||||
'During redeploy resources will be temporarily unavailable.',
|
||||
]" confirmationText="{{ $tag }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Tag Name below"
|
||||
shortConfirmationLabel="Tag Name" :confirmWithPassword="false" step2ButtonText="Redeploy All" />
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
@foreach ($applications as $application)
|
||||
<a href="{{ $application->link() }}" class="box group">
|
||||
<div class="flex flex-col">
|
||||
<div class="box-title">{{ $application->project()->name }}/{{ $application->environment->name }}
|
||||
</div>
|
||||
<div class="box-description">{{ $application->name }}</div>
|
||||
<div class="box-description">{{ $application->description }}</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
@foreach ($services as $service)
|
||||
<a href="{{ $service->link() }}" class="flex flex-col box group">
|
||||
<div class="flex flex-col">
|
||||
<div class="box-title">{{ $service->project()->name }}/{{ $service->environment->name }}
|
||||
</div>
|
||||
<div class="box-description">{{ $service->name }}</div>
|
||||
<div class="box-description">{{ $service->description }}</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deployments_per_tag_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
</div>
|
||||
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_tag_per_server as $server_name => $deployments)
|
||||
<h4 class="py-4">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'dark:border-coolgray-300' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold dark:text-white">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
@if (isset($applications) && count($applications) > 0)
|
||||
@foreach ($applications as $application)
|
||||
<a href="{{ $application->link() }}" class="box group">
|
||||
<div class="flex flex-col">
|
||||
<div class="box-title">
|
||||
{{ $application->project()->name }}/{{ $application->environment->name }}
|
||||
</div>
|
||||
<div class="box-description">{{ $application->name }}</div>
|
||||
<div class="box-description">{{ $application->description }}</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
@endif
|
||||
@if (isset($services) && count($services) > 0)
|
||||
@foreach ($services as $service)
|
||||
<a href="{{ $service->link() }}" class="flex flex-col box group">
|
||||
<div class="flex flex-col">
|
||||
<div class="box-title">
|
||||
{{ $service->project()->name }}/{{ $service->environment->name }}
|
||||
</div>
|
||||
<div class="box-description">{{ $service->name }}</div>
|
||||
<div class="box-description">{{ $service->description }}</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deploymentsPerTagPerServer) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
</div>
|
||||
<div wire:poll="getDeployments" class="grid grid-cols-1">
|
||||
@forelse ($deploymentsPerTagPerServer as $serverName => $deployments)
|
||||
<h4 class="py-4">{{ $serverName }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'dark:border-coolgray-300' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold dark:text-white">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<tr @class([
|
||||
'dark:text-white text-black dark:bg-coolblack dark:hover:bg-coolgray-100',
|
||||
'dark:bg-coolgray-100 bg-neutral-200' => $member->id == auth()->user()->id,
|
||||
'dark:bg-coolgray-100 bg-neutral-200' => $member->id == Auth::id(),
|
||||
])>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ $member->name }}
|
||||
@@ -12,9 +12,9 @@
|
||||
{{ data_get($member, 'pivot.role') }}
|
||||
</td>
|
||||
<td class="flex gap-2 px-5 py-4 text-sm whitespace-nowrap">
|
||||
@if (auth()->user()->isAdminFromSession())
|
||||
@if ($member->id !== auth()->user()->id)
|
||||
@if (auth()->user()->isOwner())
|
||||
@if (Auth::user()->isAdminFromSession())
|
||||
@if ($member->id !== Auth::id())
|
||||
@if (Auth::user()->isOwner())
|
||||
@if (data_get($member, 'pivot.role') === 'owner')
|
||||
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
|
||||
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
|
||||
@@ -30,7 +30,7 @@
|
||||
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
|
||||
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
|
||||
@endif
|
||||
@elseif (auth()->user()->isAdmin())
|
||||
@elseif (Auth::user()->isAdmin())
|
||||
@if (data_get($member, 'pivot.role') === 'admin')
|
||||
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
|
||||
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
|
||||
|
||||
@@ -8,27 +8,32 @@
|
||||
<x-helper
|
||||
helper="If you're having trouble connecting to your server, make sure that the port is open.<br><br><a class='underline' href='https://coolify.io/docs/knowledge-base/server/firewall/#terminal' target='_blank'>Documentation</a>"></x-helper>
|
||||
</div>
|
||||
<div>
|
||||
<form class="flex flex-col gap-2 justify-center xl:items-end xl:flex-row"
|
||||
wire:submit="$dispatchSelf('connectToContainer')">
|
||||
<x-forms.select id="server" required wire:model.live="selected_uuid">
|
||||
@foreach ($servers as $server)
|
||||
@if ($loop->first)
|
||||
<option disabled value="default">Select a server or container</option>
|
||||
@endif
|
||||
<option value="{{ $server->uuid }}">{{ $server->name }}</option>
|
||||
@foreach ($containers as $container)
|
||||
@if ($container['server_uuid'] == $server->uuid)
|
||||
<option value="{{ $container['uuid'] }}">
|
||||
{{ $server->name }} -> {{ $container['name'] }}
|
||||
</option>
|
||||
<div x-init="$wire.loadContainers()">
|
||||
@if ($isLoadingContainers)
|
||||
<div class="pt-1">
|
||||
<x-loading text="Loading servers and containers..." />
|
||||
</div>
|
||||
@else
|
||||
<form class="flex flex-col gap-2 justify-center xl:items-end xl:flex-row"
|
||||
wire:submit="$dispatchSelf('connectToContainer')">
|
||||
<x-forms.select id="server" required wire:model.live="selected_uuid">
|
||||
@foreach ($servers as $server)
|
||||
@if ($loop->first)
|
||||
<option disabled value="default">Select a server or container</option>
|
||||
@endif
|
||||
<option value="{{ $server->uuid }}">{{ $server->name }}</option>
|
||||
@foreach ($containers as $container)
|
||||
@if ($container['server_uuid'] == $server->uuid)
|
||||
<option value="{{ $container['uuid'] }}">
|
||||
{{ $server->name }} -> {{ $container['name'] }}
|
||||
</option>
|
||||
@endif
|
||||
@endforeach
|
||||
@endforeach
|
||||
@endforeach
|
||||
</x-forms.select>
|
||||
<x-forms.button type="submit">Connect</x-forms.button>
|
||||
</form>
|
||||
</x-forms.select>
|
||||
<x-forms.button type="submit">Connect</x-forms.button>
|
||||
</form>
|
||||
@endif
|
||||
<livewire:project.shared.terminal />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -2,31 +2,29 @@
|
||||
x-init="$wire.checkUpdate" x-data="upgradeModal">
|
||||
@if ($isUpgradeAvailable)
|
||||
<div :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto">
|
||||
<button class="menu-item" @click="modalOpen=true">
|
||||
@if ($showProgress)
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-6 h-6 text-pink-500 transition-colors hover:text-pink-300 lds-heart" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
|
||||
</svg>
|
||||
In progress
|
||||
@else
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-6 h-6 text-pink-500 transition-colors hover:text-pink-300" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path
|
||||
d="M9 12h-3.586a1 1 0 0 1 -.707 -1.707l6.586 -6.586a1 1 0 0 1 1.414 0l6.586 6.586a1 1 0 0 1 -.707 1.707h-3.586v3h-6v-3z" />
|
||||
<path d="M9 21h6" />
|
||||
<path d="M9 18h6" />
|
||||
</svg>
|
||||
Upgrade
|
||||
@endif
|
||||
<button class="menu-item" @click="modalOpen=true" x-show="showProgress">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-6 h-6 text-pink-500 transition-colors hover:text-pink-300 lds-heart" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
|
||||
</svg>
|
||||
In progress
|
||||
</button>
|
||||
<button class="menu-item" @click="modalOpen=true" x-show="!showProgress">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-6 h-6 text-pink-500 transition-colors hover:text-pink-300" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path
|
||||
d="M9 12h-3.586a1 1 0 0 1 -.707 -1.707l6.586 -6.586a1 1 0 0 1 1.414 0l6.586 6.586a1 1 0 0 1 -.707 1.707h-3.586v3h-6v-3z" />
|
||||
<path d="M9 21h6" />
|
||||
<path d="M9 18h6" />
|
||||
</svg>
|
||||
Upgrade
|
||||
</button>
|
||||
|
||||
<template x-teleport="body">
|
||||
<div x-show="modalOpen"
|
||||
class="fixed top-0 lg:pt-10 left-0 z-[99] flex items-start justify-center w-screen h-screen"
|
||||
@@ -45,19 +43,21 @@
|
||||
class="relative w-full py-6 border rounded min-w-full lg:min-w-[36rem] max-w-fit bg-neutral-100 border-neutral-400 dark:bg-base px-7 dark:border-coolgray-300">
|
||||
<div class="flex items-center justify-between pb-3">
|
||||
<h3 class="text-lg font-semibold">Upgrade confirmation</h3>
|
||||
@if (!$showProgress)
|
||||
<button @click="modalOpen=false"
|
||||
class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50">
|
||||
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
@endif
|
||||
<button x-show="!showProgress" @click="modalOpen=false"
|
||||
class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50">
|
||||
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="relative w-auto pb-8">
|
||||
<p>Are you sure you would like to upgrade your instance to {{ $latestVersion }}?</p>
|
||||
<br />
|
||||
|
||||
<div class="p-4 mb-4 text-yellow-800 border border-yellow-300 rounded-lg bg-yellow-50 dark:bg-yellow-900/30 dark:text-yellow-300 dark:border-yellow-800">
|
||||
<p class="font-medium">Warning: Any deployments running during the update process will fail. Please ensure no deployments are in progress on any server before continuing.</p>
|
||||
</div>
|
||||
<p>You can review the changelogs <a class="font-bold underline dark:text-white"
|
||||
href="https://github.com/coollabsio/coolify/releases" target="_blank">here</a>.</p>
|
||||
<br />
|
||||
@@ -65,22 +65,18 @@
|
||||
<a class="font-bold underline dark:text-white" href="https://coolify.io/docs/upgrade"
|
||||
target="_blank">guide</a> on what to do.
|
||||
</p>
|
||||
@if ($showProgress)
|
||||
<div class="flex flex-col pt-4">
|
||||
<h2>Progress <x-loading /></h2>
|
||||
<div x-html="currentStatus"></div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex flex-col pt-4" x-show="showProgress">
|
||||
<h2>Progress <x-loading /></h2>
|
||||
<div x-html="currentStatus"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
@if (!$showProgress)
|
||||
<x-forms.button @click="modalOpen=false"
|
||||
class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||
</x-forms.button>
|
||||
<div class="flex-1"></div>
|
||||
<x-forms.button @click="confirmed" class="w-24" isHighlighted type="button">Continue
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<div class="flex gap-4" x-show="!showProgress">
|
||||
<x-forms.button @click="modalOpen=false"
|
||||
class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||
</x-forms.button>
|
||||
<div class="flex-1"></div>
|
||||
<x-forms.button @click="confirmed" class="w-24" isHighlighted type="button">Continue
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,12 +89,12 @@
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('upgradeModal', () => ({
|
||||
modalOpen: false,
|
||||
showProgress: @js($showProgress),
|
||||
showProgress: false,
|
||||
currentStatus: '',
|
||||
confirmed() {
|
||||
this.showProgress = true;
|
||||
this.$wire.$call('upgrade')
|
||||
this.upgrade();
|
||||
this.$wire.showProgress = true;
|
||||
window.addEventListener('beforeunload', (event) => {
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</x-slot>
|
||||
<div class="flex items-start gap-2">
|
||||
<h1>Sources</h1>
|
||||
<x-modal-input buttonTitle="+ Add" title="New GitHub App">
|
||||
<x-modal-input buttonTitle="+ Add" title="New GitHub App" :closeOutside="false">
|
||||
<livewire:source.github.create />
|
||||
</x-modal-input>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<x-layout>
|
||||
<h1>New GitHub Source</h1>
|
||||
|
||||
</x-layout>
|
||||
@@ -1,22 +0,0 @@
|
||||
<x-layout>
|
||||
<h1>New Source</h1>
|
||||
<div class="subtitle ">Add source providers for your applications.</div>
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'github' }">
|
||||
{{-- <div class="flex justify-center h-full gap-2 pb-6">
|
||||
<a class="flex items-center justify-center w-1/2 p-2 transition-colors rounded-none min-h-12 bg-coolgray-200 hover:bg-coollabs-100 hover:dark:text-white hover:no-underline"
|
||||
:class="activeTab === 'github' && 'bg-coollabs dark:text-white'"
|
||||
@click.prevent="activeTab = 'github'; window.location.hash = 'github'" href="#">GitHub
|
||||
</a>
|
||||
<a class="flex items-center justify-center w-1/2 p-2 transition-colors rounded-none min-h-12 bg-coolgray-200 hover:bg-coollabs-100 hover:dark:text-white hover:no-underline"
|
||||
:class="activeTab === 'gitlab' && 'bg-coollabs dark:text-white'"
|
||||
@click.prevent="activeTab = 'gitlab'; window.location.hash = 'gitlab'" href="#">GitLab
|
||||
</a>
|
||||
</div> --}}
|
||||
<div x-cloak x-show="activeTab === 'github'" class="h-full">
|
||||
<livewire:source.github.create />
|
||||
</div>
|
||||
{{-- <div x-cloak x-show="activeTab === 'gitlab'" class="h-full">
|
||||
WIP
|
||||
</div> --}}
|
||||
</div>
|
||||
</x-layout>
|
||||
Reference in New Issue
Block a user