The earlier refreshStatus fix kept user-typed values intact but Livewire still absorbed deferred wire:model values into the snapshot on every broadcast- triggered roundtrip, clearing the unsaved-changes indicator and making the form look auto-saved. Move all status-derived display (DB URLs, SSL toggle/mode, cert expiry) out of each DB General form into a sibling StatusInfo Livewire component, so the form never roundtrips on broadcasts. Shared scaffolding lives in App\Traits\HasDatabaseStatusInfo plus an x-database- status-info Blade component, leaving each per-DB StatusInfo class as a ~20-50 line declaration of label, SSL mode options, and SSL save hooks. Parents dispatch databaseUpdated from save methods so the sibling refreshes after writes. Tests cover the architecture (no DB form subscribes to status broadcasts) and the sibling's refresh-on-status-change behavior.
141 lines
8.5 KiB
PHP
141 lines
8.5 KiB
PHP
<div>
|
|
<dialog id="newInitScript" class="modal">
|
|
<form method="dialog" class="flex flex-col gap-2 rounded-sm modal-box" wire:submit='save_new_init_script'>
|
|
<h3 class="text-lg font-bold">Add Init Script</h3>
|
|
<x-forms.input placeholder="create_test_db.sql" id="new_filename" label="Filename" required />
|
|
<x-forms.textarea placeholder="CREATE DATABASE test;" id="new_content" label="Content" required />
|
|
<x-forms.button onclick="newInitScript.close()" type="submit">
|
|
Save
|
|
</x-forms.button>
|
|
</form>
|
|
<form method="dialog" class="modal-backdrop">
|
|
<button>close</button>
|
|
</form>
|
|
</dialog>
|
|
|
|
<form wire:submit="submit" class="flex flex-col gap-2">
|
|
<div class="flex items-center gap-2">
|
|
<h2>General</h2>
|
|
<x-forms.button type="submit" canGate="update" :canResource="$database">
|
|
Save
|
|
</x-forms.button>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
|
<x-forms.input label="Name" id="name" canGate="update" :canResource="$database" />
|
|
<x-forms.input label="Description" id="description" canGate="update" :canResource="$database" />
|
|
<x-forms.input label="Image" id="image" required canGate="update" :canResource="$database"
|
|
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/postgres'>https://hub.docker.com/_/postgres</a>" />
|
|
</div>
|
|
<div class="pt-2 dark:text-warning">If you change the values in the database, please sync it here, otherwise
|
|
automations (like backups) won't work.
|
|
</div>
|
|
@if ($database->started_at)
|
|
<div class="flex xl:flex-row flex-col gap-2">
|
|
<x-forms.input label="Username" id="postgresUser" placeholder="If empty: postgres" canGate="update"
|
|
:canResource="$database"
|
|
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="postgresPassword" type="password" required canGate="update"
|
|
:canResource="$database"
|
|
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
|
|
<x-forms.input label="Initial Database" id="postgresDb"
|
|
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 xl:flex-row flex-col gap-2 pb-2">
|
|
<x-forms.input label="Username" id="postgresUser" placeholder="If empty: postgres" canGate="update"
|
|
:canResource="$database" />
|
|
<x-forms.input label="Password" id="postgresPassword" type="password" required canGate="update"
|
|
:canResource="$database" />
|
|
<x-forms.input label="Initial Database" id="postgresDb"
|
|
placeholder="If empty, it will be the same as Username." canGate="update" :canResource="$database" />
|
|
</div>
|
|
@endif
|
|
<div class="flex gap-2">
|
|
<x-forms.input label="Initial Database Arguments" canGate="update" :canResource="$database" id="postgresInitdbArgs"
|
|
placeholder="If empty, use default. See in docker docs." />
|
|
<x-forms.input label="Host Auth Method" canGate="update" :canResource="$database" id="postgresHostAuthMethod"
|
|
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' {{ wireNavigate() }} 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="customDockerRunOptions" label="Custom Docker Options" canGate="update" :canResource="$database" />
|
|
<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="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"
|
|
canGate="update" :canResource="$database" />
|
|
</div>
|
|
</div>
|
|
<livewire:project.database.postgresql.status-info :database="$database" />
|
|
<div class="flex flex-col gap-2">
|
|
<div class="flex items-center gap-2 py-2">
|
|
<h3>Proxy</h3>
|
|
<x-loading wire:loading wire:target="instantSave" />
|
|
@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" :collapsible="false" 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>
|
|
<div class="flex flex-col gap-2 w-64">
|
|
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available"
|
|
canGate="update" :canResource="$database" />
|
|
</div>
|
|
<div class="flex flex-col gap-2">
|
|
<x-forms.input type="number" placeholder="5432" disabled="{{ $isPublic }}" id="publicPort"
|
|
label="Public Port" canGate="update" :canResource="$database" />
|
|
<x-forms.input type="number" placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
|
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col gap-2">
|
|
<x-forms.textarea label="Custom PostgreSQL Configuration" rows="10" id="postgresConf"
|
|
canGate="update" :canResource="$database" />
|
|
</div>
|
|
</form>
|
|
|
|
<div class="flex flex-col gap-4 pt-4">
|
|
<h3>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="isLogDrainEnabled" label="Drain Logs" canGate="update"
|
|
:canResource="$database" />
|
|
</div>
|
|
|
|
<div class="pb-16">
|
|
<div class="flex items-center gap-2 pb-2">
|
|
|
|
<h3>Initialization scripts</h3>
|
|
@can('update', $database)
|
|
<x-modal-input buttonTitle="+ Add" title="New Init Script">
|
|
<form class="flex flex-col w-full gap-2 rounded-sm" wire:submit='save_new_init_script'>
|
|
<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">
|
|
Save
|
|
</x-forms.button>
|
|
</form>
|
|
</x-modal-input>
|
|
@endcan
|
|
</div>
|
|
<div class="flex flex-col gap-2">
|
|
@forelse($initScripts ?? [] as $script)
|
|
<livewire:project.database.init-script :script="$script" :wire:key="$script['index']" />
|
|
@empty
|
|
<div>No initialization scripts found.</div>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|