Merge branch 'next' into feat--terminal-pty

This commit is contained in:
Andras Bacsai
2024-09-11 10:41:33 +02:00
committed by GitHub
197 changed files with 8925 additions and 3563 deletions

View File

@@ -31,11 +31,12 @@
@endif
@forelse ($deployments as $deployment)
<div @class([
'dark:bg-coolgray-100 p-2 border-l border-dashed 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' =>
'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 ' =>
data_get($deployment, 'status') === 'in_progress' ||
data_get($deployment, 'status') === 'cancelled-by-user',
'border-error' => data_get($deployment, 'status') === 'failed',
'border-error border-dashed ' =>
data_get($deployment, 'status') === 'failed',
'border-success' => data_get($deployment, 'status') === 'finished',
])
x-on:click.stop="goto('{{ $current_url . '/' . data_get($deployment, 'deployment_uuid') }}')">
@@ -106,7 +107,7 @@
<div class="flex flex-col" x-data="elapsedTime('{{ $deployment->deployment_uuid }}', '{{ $deployment->status }}', '{{ $deployment->created_at }}', '{{ $deployment->updated_at }}')">
<div>
@if ($deployment->status !== 'in_progress')
Finished <span x-text="measure_since_started()">0s</span> in
Finished <span x-text="measure_since_started()">0s</span> ago in
<span class="font-bold" x-text="measure_finished_time()">0s</span>
@else
Running for <span class="font-bold" x-text="measure_since_started()">0s</span>
@@ -157,7 +158,7 @@
}
},
measure_since_started() {
return dayjs.utc(created_at).fromNow();
return dayjs.utc(created_at).fromNow(true); // "true" prevents the "ago" suffix
},
}))
</script>

View File

@@ -9,6 +9,7 @@
fullscreen: false,
alwaysScroll: false,
intervalId: null,
showTimestamps: true,
makeFullscreen() {
this.fullscreen = !this.fullscreen;
if (this.fullscreen === false) {
@@ -53,63 +54,69 @@
class="dark:text-warning">{{ Str::headline(data_get($application_deployment_queue, 'status')) }}</span>.
</div>
@endif
<div id="screen" :class="fullscreen ? 'fullscreen' : ''">
<div id="screen" :class="fullscreen ? 'fullscreen' : 'relative'">
<div @if ($isKeepAliveOn) wire:poll.2000ms="polling" @endif
class="relative 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 ? '' : 'max-h-[40rem] border border-dotted rounded'">
<button title="Minimize" x-show="fullscreen" class="fixed top-4 right-4"
x-on:click="makeFullscreen"><svg class="icon" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<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" />
</svg></button>
<button title="Go Top" x-show="fullscreen" class="fixed top-4 right-28" x-on:click="goTop"> <svg
class="icon" 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' : ''"
class="fixed top-4 right-16" x-on:click="toggleScroll"><svg class="icon" 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>
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="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">
<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">
<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">
<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">
<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" />
<path fill="currentColor"
d="M9.793 12.793a1 1 0 0 1 1.497 1.32l-.083.094L6.414 19H9a1 1 0 0 1 .117 1.993L9 21H4a1 1 0 0 1-.993-.883L3 20v-5a1 1 0 0 1 1.993-.117L5 15v2.586l4.793-4.793ZM20 3a1 1 0 0 1 .993.883L21 4v5a1 1 0 0 1-1.993.117L19 9V6.414l-4.793 4.793a1 1 0 0 1-1.497-1.32l.083-.094L17.586 5H15a1 1 0 0 1-.117-1.993L15 3h5Z" />
</g>
</svg>
</button>
<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">
<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" />
</svg>
</button>
</div>
</div>
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-2 right-8"
x-on:click="makeFullscreen"><svg class="fixed icon" 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" />
<path fill="currentColor"
d="M9.793 12.793a1 1 0 0 1 1.497 1.32l-.083.094L6.414 19H9a1 1 0 0 1 .117 1.993L9 21H4a1 1 0 0 1-.993-.883L3 20v-5a1 1 0 0 1 1.993-.117L5 15v2.586l4.793-4.793ZM20 3a1 1 0 0 1 .993.883L21 4v5a1 1 0 0 1-1.993.117L19 9V6.414l-4.793 4.793a1 1 0 0 1-1.497-1.32l.083-.094L17.586 5H15a1 1 0 0 1-.117-1.993L15 3h5Z" />
</g>
</svg></button>
<div id="logs" class="flex flex-col font-mono">
@if (decode_remote_command_output($application_deployment_queue)->count() > 0)
@foreach (decode_remote_command_output($application_deployment_queue) as $line)
@forelse ($this->logLines as $line)
<div @class([
'mt-2' => $line['command'] ?? false,
'flex gap-2 dark:hover:bg-coolgray-500 hover:bg-gray-100',
])>
<span x-show="showTimestamps" class="shrink-0 text-gray-500">{{ $line['timestamp'] }}</span>
<span @class([
'text-coollabs dark:text-warning whitespace-pre-line' => $line['hidden'],
'text-red-500 font-bold whitespace-pre-line' => $line['type'] == 'stderr',
])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
<br><br>[COMMAND] {{ $line['command'] }}<br>[OUTPUT]
@endif @if (str($line['output'])->contains('http://') || str($line['output'])->contains('https://'))
@php
$line['output'] = preg_replace(
'/(https?:\/\/[^\s]+)/',
'<a href="$1" target="_blank" class="underline text-neutral-400">$1</a>',
$line['output'],
);
@endphp {!! $line['output'] !!}
@else
{{ $line['output'] }}
@endif
</span>
@endforeach
@else
<span class="font-mono text-neutral-400">No logs yet.</span>
@endif
'text-coollabs dark:text-warning' => $line['hidden'],
'text-red-500' => $line['stderr'],
'font-bold' => $line['command'] ?? false,
'whitespace-pre-wrap',
])>{!! $line['line'] !!}</span>
</div>
@empty
<span class="font-mono text-neutral-400 mb-2">No logs yet.</span>
@endforelse
</div>
</div>
</div>

View File

@@ -254,6 +254,11 @@
helper="You need to modify the docker compose file." monacoEditorLanguage="yaml"
useMonacoEditor />
@else
@if ($application->compose_parsing_version === '3')
<x-forms.textarea rows="10" readonly id="application.docker_compose_raw"
label="Docker Compose Content (raw)" helper="You need to modify the docker compose file."
monacoEditorLanguage="yaml" useMonacoEditor />
@endif
<x-forms.textarea rows="10" readonly id="application.docker_compose"
label="Docker Compose Content" helper="You need to modify the docker compose file."
monacoEditorLanguage="yaml" useMonacoEditor />

View File

@@ -4,34 +4,45 @@
<h3 class="py-4">Executions</h3>
<x-forms.button wire:click='cleanupFailed'>Cleanup Failed Backups</x-forms.button>
</div>
<div class="flex flex-col-reverse gap-2">
<div class="flex flex-col gap-4">
@forelse($executions as $execution)
<form wire:key="{{ data_get($execution, 'id') }}"
class="relative flex flex-col p-4 bg-white box-without-bg dark:bg-coolgray-100"
@class([
'border-green-500' => data_get($execution, 'status') === 'success',
'border-red-500' => data_get($execution, 'status') === 'failed',
])>
<div wire:key="{{ data_get($execution, 'id') }}" @class([
'flex flex-col border-l-2 transition-colors p-4 ',
'bg-white dark:bg-coolgray-100 ',
'text-black dark:text-white',
'border-green-500' => data_get($execution, 'status') === 'success',
'border-red-500' => data_get($execution, 'status') === 'failed',
'border-yellow-500' => data_get($execution, 'status') === 'running',
])>
@if (data_get($execution, 'status') === 'running')
<div class="absolute top-2 right-2">
<x-loading />
</div>
@endif
<div>Database: {{ data_get($execution, 'database_name', 'N/A') }}</div>
<div>Status: {{ data_get($execution, 'status') }}</div>
<div>Started At: {{ data_get($execution, 'created_at') }}</div>
@if (data_get($execution, 'message'))
<div>Message: {{ data_get($execution, 'message') }}</div>
@endif
<div>Size: {{ data_get($execution, 'size') }} B /
{{ round((int) data_get($execution, 'size') / 1024, 2) }}
kB / {{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB
<div class="text-gray-700 dark:text-gray-300 font-semibold mb-1">Status:
{{ data_get($execution, 'status') }}</div>
<div class="text-gray-600 dark:text-gray-400 text-sm">
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at')) }}
</div>
<div>Location: {{ data_get($execution, 'filename', 'N/A') }}</div>
<div class="flex gap-2">
<div class="flex-1"></div>
<div class="text-gray-600 dark:text-gray-400 text-sm">
Database: {{ data_get($execution, 'database_name', 'N/A') }}
</div>
<div class="text-gray-600 dark:text-gray-400 text-sm">
Size: {{ data_get($execution, 'size') }} B /
{{ round((int) data_get($execution, 'size') / 1024, 2) }} kB /
{{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB
</div>
<div class="text-gray-600 dark:text-gray-400 text-sm">
Location: {{ data_get($execution, 'filename', 'N/A') }}
</div>
@if (data_get($execution, 'message'))
<div class="mt-2 p-2 bg-gray-100 dark:bg-coolgray-200 rounded">
<pre class="whitespace-pre-wrap text-sm">{{ data_get($execution, 'message') }}</pre>
</div>
@endif
<div class="flex gap-2 mt-4">
@if (data_get($execution, 'status') === 'success')
<x-forms.button class=" dark:hover:bg-coolgray-400"
<x-forms.button class="dark:hover:bg-coolgray-400"
x-on:click="download_file('{{ data_get($execution, 'id') }}')">Download</x-forms.button>
@endif
<x-modal-confirmation isErrorButton action="deleteBackup({{ data_get($execution, 'id') }})">
@@ -41,10 +52,9 @@
This will delete this backup. It is not reversible.<br>Please think again.
</x-modal-confirmation>
</div>
</form>
</div>
@empty
<div>No executions found.</div>
<div class="p-4 bg-gray-100 dark:bg-coolgray-100 rounded">No executions found.</div>
@endforelse
</div>
<script>
@@ -53,5 +63,4 @@
}
</script>
@endisset
</div>

View File

@@ -21,14 +21,18 @@
readonly helper="You can only change this in the database." />
</div>
@else
<div class="pt-8 dark:text-warning">Please verify these values. You can only modify them before the initial
<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 pb-8">
<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 />
</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" />
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -11,6 +11,10 @@
<x-forms.input label="Description" id="database.description" />
<x-forms.input label="Image" id="database.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" />
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -12,6 +12,10 @@
<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/r/eqalpha/keydb'>https://hub.docker.com/r/eqalpha/keydb</a>" />
</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" />
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -16,30 +16,40 @@
automations (like backups) won't work.
</div>
@if ($database->started_at)
<div class="flex flex-col gap-2">
<div class="flex xl:flex-row flex-col gap-2">
<x-forms.input label="Root Password" id="database.mariadb_root_password" type="password" required
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
<x-forms.input label="Normal User" id="database.mariadb_user" required
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
<x-forms.input label="Normal User Password" id="database.mariadb_password" type="password" required
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
</div>
<div class="flex flex-col gap-2">
<x-forms.input label="Initial Database" id="database.mariadb_database"
placeholder="If empty, it will be the same as Username." readonly
helper="You can only change this in the database." />
</div>
@else
<div class="flex flex-col gap-2 pb-2">
<div class="flex xl:flex-row flex-col gap-2 pb-2">
<x-forms.input label="Root Password" id="database.mariadb_root_password" type="password"
helper="You can only change this in the database." />
<x-forms.input label="Normal User" id="database.mariadb_user" required
helper="You can only change this in the database." />
<x-forms.input label="Normal User Password" id="database.mariadb_password" type="password" required
helper="You can only change this in the database." />
</div>
<div class="flex flex-col gap-2">
<x-forms.input label="Initial Database" id="database.mariadb_database"
placeholder="If empty, it will be the same as Username."
helper="You can only change this in the database." />
</div>
@endif
<div class="pt-2">
<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" />
</div>
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -16,7 +16,7 @@
automations (like backups) won't work.
</div>
@if ($database->started_at)
<div class="flex flex-col gap-2">
<div class="flex xl:flex-row flex-col gap-2">
<x-forms.input label="Initial Username" id="database.mongo_initdb_root_username"
placeholder="If empty: postgres"
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
@@ -28,7 +28,7 @@
helper="You can only change this in the database." />
</div>
@else
<div class="flex flex-col gap-2 pb-2">
<div class="flex xl:flex-row flex-col gap-2 pb-2">
<x-forms.input required label="Username" id="database.mongo_initdb_root_username"
placeholder="If empty: postgres" />
<x-forms.input label="Password" id="database.mongo_initdb_root_password" type="password" required />
@@ -36,6 +36,10 @@
placeholder="If empty, it will be the same as Username." />
</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" />
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -16,30 +16,40 @@
automations (like backups) won't work.
</div>
@if ($database->started_at)
<div class="flex flex-col gap-2">
<div class="flex xl:flex-row flex-col gap-2">
<x-forms.input label="Root Password" id="database.mysql_root_password" type="password" required
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
<x-forms.input label="Normal User" id="database.mysql_user" required
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
<x-forms.input label="Normal User Password" id="database.mysql_password" type="password" required
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
</div>
<div class="flex flex-col gap-2">
<x-forms.input label="Initial Database" id="database.mysql_database"
placeholder="If empty, it will be the same as Username." readonly
helper="You can only change this in the database." />
</div>
@else
<div class="flex flex-col gap-4 pb-2">
<div class="flex xl:flex-row flex-col gap-4 pb-2">
<x-forms.input label="Root Password" id="database.mysql_root_password" type="password"
helper="You can only change this in the database." />
<x-forms.input label="Normal User" id="database.mysql_user" required
helper="You can only change this in the database." />
<x-forms.input label="Normal User Password" id="database.mysql_password" type="password" required
helper="You can only change this in the database." />
</div>
<div class="flex flex-col gap-2">
<x-forms.input label="Initial Database" id="database.mysql_database"
placeholder="If empty, it will be the same as Username."
helper="You can only change this in the database." />
</div>
@endif
<div class="pt-2">
<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" />
</div>
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -30,7 +30,7 @@
automations (like backups) won't work.
</div>
@if ($database->started_at)
<div class="flex flex-col gap-2">
<div class="flex xl:flex-row flex-col gap-2">
<x-forms.input label="Username" id="database.postgres_user" placeholder="If empty: postgres"
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
<x-forms.input label="Password" id="database.postgres_password" type="password" required
@@ -40,7 +40,7 @@
helper="You can only change this in the database." />
</div>
@else
<div class="flex flex-col gap-2 pb-2">
<div class="flex xl:flex-row flex-col gap-2 pb-2">
<x-forms.input label="Username" id="database.postgres_user" placeholder="If empty: postgres" />
<x-forms.input label="Password" id="database.postgres_password" type="password" required />
<x-forms.input label="Initial Database" id="database.postgres_db"
@@ -53,6 +53,10 @@
<x-forms.input label="Host Auth Method" id="database.postgres_host_auth_method"
placeholder="If empty, use default. See in docker docs." />
</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" />
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -12,6 +12,10 @@
<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>
<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" />
<div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3>
<div class="flex items-end gap-2">

View File

@@ -1,38 +1,37 @@
<div>
<div class="flex flex-col gap-2">
@forelse($database->scheduledBackups as $backup)
@if ($type == 'database')
<a class="box"
href="{{ route('project.database.backup.execution', [...$parameters, 'backup_uuid' => $backup->uuid]) }}">
<div class="flex flex-col">
<div>Frequency: {{ $backup->frequency }}</div>
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
<div>Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}</div>
</div>
</a>
@else
<div class="box" wire:click="setSelectedBackup('{{ data_get($backup, 'id') }}')">
<div @class([
'border-coollabs' =>
data_get($backup, 'id') === data_get($selectedBackup, 'id'),
'flex flex-col border-l-2 border-transparent',
])>
<div>Frequency: {{ $backup->frequency }}</div>
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
<div>Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}</div>
</div>
</div>
@endif
@if ($type == 'database')
<a class="box"
href="{{ route('project.database.backup.execution', [...$parameters, 'backup_uuid' => $backup->uuid]) }}">
<div class="flex flex-col">
<div>Frequency: {{ $backup->frequency }}</div>
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
<div>Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}</div>
</div>
</a>
@else
<div class="box" wire:click="setSelectedBackup('{{ data_get($backup, 'id') }}')">
<div @class([ 'border-coollabs'=>
data_get($backup, 'id') === data_get($selectedBackup, 'id'),
'flex flex-col border-l-2 border-transparent',
])>
<div>Frequency: {{ $backup->frequency }}</div>
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
<div>Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}</div>
</div>
</div>
@endif
@empty
<div>No scheduled backups configured.</div>
<div>No scheduled backups configured.</div>
@endforelse
</div>
@if ($type === 'service-database' && $selectedBackup)
<div class="pt-10">
<livewire:project.database.backup-edit wire:key="{{ $selectedBackup->id }}" :backup="$selectedBackup"
:s3s="$s3s" :status="data_get($database, 'status')" />
<h3 class="py-4">Executions</h3>
<livewire:project.database.backup-executions wire:key="{{ $selectedBackup->id }}" :backup="$selectedBackup" />
</div>
<div class="pt-10">
<livewire:project.database.backup-edit wire:key="{{ $selectedBackup->id }}" :backup="$selectedBackup"
:s3s="$s3s" :status="data_get($database, 'status')" />
<h3 class="py-4">Executions</h3>
<livewire:project.database.backup-executions wire:key="{{ $selectedBackup->id }}" :backup="$selectedBackup" :database="$database" />
</div>
@endif
</div>

View File

@@ -11,9 +11,8 @@
<div class="subtitle">All your projects are here.</div>
<div class="grid gap-2 lg:grid-cols-2">
@forelse ($projects as $project)
<div class="box group" x-data x-on:click="goto('{{ $project->uuid }}')">
<div class="flex flex-col justify-center flex-1 mx-6"
onclick="gotoProject('{{ $project->uuid }}','{{ $project->default_environment() }}')">
<div class="box group" onclick="gotoProject('{{ $project->uuid }}', '{{ $project->default_environment() }}')">
<div class="flex flex-col justify-center flex-1 mx-6">
<div class="box-title">{{ $project->name }}</div>
<div class="box-description ">
{{ $project->description }}</div>
@@ -33,15 +32,12 @@
</div>
<script>
function goto(uuid) {
function gotoProject(uuid, environment) {
if (environment) {
window.location.href = '/project/' + uuid + '/' + environment;
} else {
window.location.href = '/project/' + uuid;
}
function gotoProject(uuid, environment) {
if (!environment) {
window.location.href = '/project/' + uuid;
}
window.location.href = '/project/' + uuid + '/' + environment;
}
</script>
}
</script>
</div>

View File

@@ -4,7 +4,7 @@
<form class="flex flex-col gap-2" wire:submit='loadBranch'>
<div class="flex flex-col gap-2">
<div class="flex flex-col gap-2">
<div class="flex items-end gap-2">
<div class="flex gap-2 items-end">
<x-forms.input required id="repository_url" label="Repository URL (https://)"
helper="{!! __('repository.url') !!}" />
<x-forms.button type="submit">
@@ -47,7 +47,7 @@
@if ($build_pack === 'dockercompose')
<x-forms.input placeholder="/" wire:model.blur="base_directory" label="Base Directory"
helper="Directory to use as root. Useful for monorepos." />
<x-forms.input placeholder="/docker-compose.yaml" id="docker_compose_location"
<x-forms.input placeholder="/docker-compose.yaml" wire:model.blur="docker_compose_location"
label="Docker Compose Location"
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>" />
Compose file location in your repository:<span

View File

@@ -617,6 +617,85 @@
@endif
</div>
@endif
@if ($current_step === 'select-postgresql-type')
<h2>Select a Postgresql type</h2>
<div>If you need extra extensions, you can select Supabase PostgreSQL (or others), otherwise select PostgreSQL
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"
wire:click="setPostgresqlType('postgres:16-alpine')">
<div class="flex flex-col">
<div class="box-title">PostgreSQL 16 (default)</div>
<div class="box-description">
PostgreSQL is a powerful, open-source object-relational database system (no extensions).
</div>
</div>
<div class="flex-1"></div>
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline group-hover:dark:text-white dark:text-white text-neutral-6000"
onclick="event.stopPropagation()" href="https://hub.docker.com/_/postgres/"
target="_blank">
Documentation
</a>
</div>
</div>
<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('supabase/postgres:15.6.1.113')">
<div class="flex flex-col">
<div class="box-title">Supabase PostgreSQL (with extensions)</div>
<div class="box-description">
Supabase is a modern, open-source alternative to PostgreSQL with lots of extensions.
</div>
</div>
<div class="flex-1"></div>
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline group-hover:dark:text-white dark:text-white text-neutral-600"
onclick="event.stopPropagation()" href="https://github.com/supabase/postgres"
target="_blank">
Documentation
</a>
</div>
</div>
<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('postgis/postgis')">
<div class="flex flex-col">
<div class="box-title">PostGIS</div>
<div class="box-description">
PostGIS is a PostgreSQL extension for geographic objects.
</div>
</div>
<div class="flex-1"></div>
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline group-hover:dark:text-white dark:text-white text-neutral-600"
onclick="event.stopPropagation()" href="https://github.com/postgis/docker-postgis"
target="_blank">
Documentation
</a>
</div>
</div>
<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('pgvector/pgvector:pg16')">
<div class="flex flex-col">
<div class="box-title">PGVector (16)</div>
<div class="box-description">
PGVector is a PostgreSQL extension for vector data types.
</div>
</div>
<div class="flex-1"></div>
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline group-hover:dark:text-white dark:text-white text-neutral-600"
onclick="event.stopPropagation()" href="https://github.com/pgvector/pgvector"
target="_blank">
Documentation
</a>
</div>
</div>
</div>
</div>
@endif
@if ($current_step === 'existing-postgresql')
<form wire:submit='addExistingPostgresql' class="flex items-end gap-4">
<x-forms.input placeholder="postgres://username:password@database:5432" label="Database URL"

View File

@@ -1,16 +1,17 @@
<div class="p-4 transition border rounded dark:border-coolgray-200">
<div class="py-4 ">
<div class="flex flex-col justify-center pb-4 text-sm select-text">
@if (data_get($resource, 'build_pack') === 'dockercompose')
<h2>{{ data_get($resource, 'name', 'unknown') }}</h2>
@endif
{{-- @if (data_get($resource, 'build_pack') === 'dockercompose')
<h4>{{ data_get($resource, 'name', 'unknown') }}</h4>
@endif --}}
@if ($fileStorage->is_directory)
<div class="dark:text-white">Directory Mount</div>
<h4 class="dark:text-white pt-4 border-t dark:border-coolgray-200">Directory Mount</h4>
@else
<div class="dark:text-white">File Mount</div>
<h4 class="dark:text-white pt-4 border-t dark:border-coolgray-200">File Mount</h4>
@endif
<div>{{ $workdir }}{{ $fs_path }} -> {{ $fileStorage->mount_path }}</div>
</div>
<x-forms.input label="Source Path" :value="$fileStorage->fs_path" readonly />
<x-forms.input label="Destination Path" :value="$fileStorage->mount_path" readonly />
</div>
<form wire:submit='submit' class="flex flex-col gap-2">
<div class="flex gap-2">
@if ($fileStorage->is_directory)
@@ -62,5 +63,4 @@
@endif
</form>
</div>

View File

@@ -31,10 +31,11 @@
@endif
@if ($resource->persistentStorages()->get()->count() > 0)
<h3 class="pt-4">Volumes</h3>
<livewire:project.shared.storages.all :resource="$resource" />
@endif
@if ($fileStorage->count() > 0)
<div class="flex flex-col gap-4 pt-4">
<div class="flex flex-col gap-2">
@foreach ($fileStorage->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage"
wire:key="resource-{{ $fileStorage->uuid }}" />

View File

@@ -8,9 +8,9 @@
</x-modal-input>
</div>
<x-forms.button
wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view (required to set variables at build time)' }}</x-forms.button>
</div>
<div>Environment variables (secrets) for this resource.</div>
<div>Environment variables (secrets) for this resource. </div>
@if ($this->resourceClass === 'App\Models\Application' && data_get($this->resource, 'build_pack') !== 'dockercompose')
<div class="w-64 pt-2">
<x-forms.checkbox id="resource.settings.is_env_sorting_enabled" label="Sort alphabetically"

View File

@@ -29,18 +29,18 @@
@if (data_get($this->parameters, 'application_uuid'))
@foreach ($containers as $container)
<option value="{{ data_get($container, 'container.Names') }}">
{{ data_get($container, 'container.Names') }}
{{ data_get($container, 'container.Names') }} ({{ data_get($container, 'server.name') }})
</option>
@endforeach
@elseif(data_get($this->parameters, 'service_uuid'))
@foreach ($containers as $container)
<option value="{{ $container }}">
{{ $container }}
{{ $container }} ({{ data_get($servers, '0.name') }})
</option>
@endforeach
@else
<option value="{{ $container }}">
{{ $container }}
{{ $container }} ({{ data_get($servers, '0.name') }})
</option>
@endif
</x-forms.select>

View File

@@ -33,7 +33,7 @@
screen.scrollTop = 0;
}
}">
<div class="flex items-center gap-2 ">
<div class="flex gap-2 items-center">
@if ($resource?->type() === 'application' || str($resource?->type())->startsWith('standalone'))
<h4>{{ $container }}</h4>
@else
@@ -46,9 +46,9 @@
<x-loading wire:poll.2000ms='getLogs(true)' />
@endif
</div>
<form wire:submit='getLogs(true)' class="flex items-end gap-2 ">
<form wire:submit='getLogs(true)' class="flex gap-2 items-end">
<div class="w-96">
<x-forms.input label="Only Show Number of Lines" placeholder="1000" required
<x-forms.input label="Only Show Number of Lines" placeholder="1000" type="number" required
id="numberOfLines"></x-forms.input>
</div>
<x-forms.button type="submit">Refresh</x-forms.button>
@@ -56,7 +56,7 @@
<x-forms.checkbox instantSave label="Include Timestamps" id="showTimeStamps"></x-forms.checkbox>
</form>
<div :class="fullscreen ? 'fullscreen' : 'relative w-full py-4 mx-auto'">
<div class="flex flex-col-reverse w-full px-4 py-2 overflow-y-auto bg-white dark:text-white dark:bg-coolgray-100 scrollbar dark:border-coolgray-300"
<div class="flex overflow-y-auto flex-col-reverse px-4 py-2 w-full bg-white dark:text-white dark:bg-coolgray-100 scrollbar dark:border-coolgray-300"
:class="fullscreen ? '' : 'max-h-96 border border-solid rounded'">
<button title="Minimize" x-show="fullscreen" class="fixed top-4 right-4"
x-on:click="makeFullscreen"><svg class="icon" viewBox="0 0 24 24"
@@ -76,7 +76,7 @@
stroke-width="2" d="M12 5v14m4-4l-4 4m-4-4l4 4" />
</svg></button>
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-5 right-1"
<button title="Fullscreen" x-show="!fullscreen" class="absolute right-1 top-5"
x-on:click="makeFullscreen"><svg class="icon" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<g fill="none">

View File

@@ -13,7 +13,7 @@
</x-forms.select>
@else
<x-forms.input placeholder="php" id="container"
helper="You can leave it empty if your resource only have one container." label="Container name" />
helper="You can leave this empty if your resource only has one container." label="Container name" />
@endif
@elseif ($type === 'service')
<x-forms.select id="container" label="Container name">

View File

@@ -1,32 +1,38 @@
<div class="flex flex-col-reverse gap-2">
<div class="flex flex-col gap-4">
@forelse($executions as $execution)
@if (data_get($execution, 'id') == $selectedKey)
<div class="p-2">
@if (data_get($execution, 'message'))
<div>
<pre>{{ data_get($execution, 'message') }}</pre>
</div>
@else
<div>No output was recorded for this execution.</div>
@endif
</div>
@endif
<a wire:click="selectTask({{ data_get($execution, 'id') }})" @class([
'flex flex-col border-l transition-colors box-without-bg bg-coolgray-100 hover:bg-coolgray-200 cursor-pointer',
'bg-coolgray-200 dark:text-white hover:bg-coolgray-200' =>
'flex flex-col border-l-2 transition-colors p-4 cursor-pointer',
'bg-white hover:bg-gray-100 dark:bg-coolgray-100 dark:hover:bg-coolgray-200',
'text-black dark:text-white',
'bg-gray-200 dark:bg-coolgray-200' =>
data_get($execution, 'id') == $selectedKey,
'border-green-500' => data_get($execution, 'status') === 'success',
'border-red-500' => data_get($execution, 'status') === 'failed',
'border-yellow-500' => data_get($execution, 'status') === 'running',
])>
@if (data_get($execution, 'status') === 'running')
<div class="absolute top-2 right-2">
<x-loading />
</div>
@endif
<div>Status: {{ data_get($execution, 'status') }}</div>
<div>Started At: {{ data_get($execution, 'created_at') }}</div>
<div class="text-gray-700 dark:text-gray-300 font-semibold mb-1">Status: {{ data_get($execution, 'status') }}
</div>
<div class="text-gray-600 dark:text-gray-400 text-sm">
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at', now())) }}
</div>
</a>
@if (data_get($execution, 'id') == $selectedKey)
<div class="p-4 mb-2 bg-gray-100 dark:bg-coolgray-200 rounded">
@if (data_get($execution, 'message'))
<div>
<pre class="whitespace-pre-wrap">{{ data_get($execution, 'message') }}</pre>
</div>
@else
<div>No output was recorded for this execution.</div>
@endif
</div>
@endif
@empty
<div>No executions found.</div>
<div class="p-4 bg-gray-100 dark:bg-coolgray-100 rounded">No executions found.</div>
@endforelse
</div>

View File

@@ -1,47 +1,47 @@
<div>
<x-slot:title>
{{ data_get_str($resource, 'name')->limit(10) }} > Scheduled Tasks | Coolify
</x-slot>
@if ($type === 'application')
</x-slot>
@if ($type === 'application')
<h1>Scheduled Task</h1>
<livewire:project.application.heading :application="$resource" />
@elseif ($type === 'service')
@elseif ($type === 'service')
<livewire:project.service.navbar :service="$resource" :parameters="$parameters" />
@endif
@endif
<form wire:submit="submit" class="w-full">
<div class="flex flex-col gap-2 pb-2">
<div class="flex items-end gap-2 pt-4">
<h2>Scheduled Task</h2>
<x-forms.button type="submit">
Save
</x-forms.button>
<x-modal-confirmation isErrorButton buttonTitle="Delete Scheduled Task">
You will delete scheduled task <span class="font-bold dark:text-warning">{{ $task->name }}</span>.
</x-modal-confirmation>
<form wire:submit="submit" class="w-full">
<div class="flex flex-col gap-2 pb-2">
<div class="flex items-end gap-2 pt-4">
<h2>Scheduled Task</h2>
<x-forms.button type="submit">
Save
</x-forms.button>
<x-modal-confirmation isErrorButton buttonTitle="Delete Scheduled Task">
You will delete scheduled task <span class="font-bold dark:text-warning">{{ $task->name }}</span>.
</x-modal-confirmation>
</div>
<div class="w-48">
<x-forms.checkbox instantSave id="task.enabled" label="Enabled" />
</div>
</div>
<div class="w-48">
<x-forms.checkbox instantSave id="task.enabled" label="Enabled" />
</div>
</div>
<div class="flex w-full gap-2">
<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 />
@if ($type === 'application')
<div class="flex w-full gap-2">
<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 />
@if ($type === 'application')
<x-forms.input placeholder="php"
helper="You can leave it empty if your resource only have one container." id="task.container"
helper="You can leave this empty if your resource only has one container." id="task.container"
label="Container name" />
@elseif ($type === 'service')
@elseif ($type === 'service')
<x-forms.input placeholder="php"
helper="You can leave it empty if your resource only have 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."
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" />
@endif
</div>
</form>
@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 key="{{ $task->id }}" selectedKey="" :executions="$task->executions->take(-20)" />
</div>
<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)" />
</div>
</div>

View File

@@ -1,43 +1,47 @@
<div class="flex flex-col w-full gap-2 rounded">
You can add Volumes, Files and Directories to your resources here.
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitPersistentVolume'>
<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
<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
<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'>
<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
<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
helper="Directory on the host system." />
@else
<x-forms.input placeholder="/root" id="host_path" label="Source Path"
helper="Directory on the host system." />
@endif
<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
</x-forms.button>
</form>
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorage'>
<h3>File Mount</h3>
<x-forms.input placeholder="/etc/nginx/nginx.conf" id="file_storage_path" label="Destination Path" required
helper="File inside the container" />
<x-forms.textarea label="Content" id="file_storage_content"></x-forms.textarea>
<x-forms.button type="submit" @click="modalOpen=false">
Save
</x-forms.button>
</form>
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorageDirectory'>
<h3>Directory Mount</h3>
<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." />
@else
<x-forms.input placeholder="/root" id="host_path" label="Source Path"
helper="Directory on the host system." />
@endif
<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
</x-forms.button>
</form>
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorage'>
<h3>File Mount</h3>
<x-forms.input placeholder="/etc/nginx/nginx.conf" id="file_storage_path" label="Destination Path" required
helper="File inside the container" />
<x-forms.textarea label="Content" id="file_storage_content"></x-forms.textarea>
<x-forms.button type="submit" @click="modalOpen=false">
Save
</x-forms.button>
</form>
<form class="flex flex-col w-full gap-2 rounded" wire:submit='submitFileStorageDirectory'>
<h3>Directory Mount</h3>
<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
</x-forms.button>
</form>
<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
</x-forms.button>
</form>
</div>
</div>