Merge remote-tracking branch 'origin/next' into feature/vultr-cloud-provider

This commit is contained in:
Andras Bacsai committed 2026-07-07 21:23:07 +02:00
commit 31f904ef9f
35 files changed
+7215 -113

No files matched your search

+1 -1
View File
@@ -289,7 +289,7 @@
}
@utility info-helper-popup {
@apply hidden absolute z-40 text-xs rounded-sm text-neutral-700 group-hover:block dark:border-coolgray-500 border-neutral-900 dark:bg-coolgray-400 bg-neutral-200 dark:text-neutral-300 max-w-sm whitespace-normal break-words;
@apply hidden absolute right-0 z-40 w-max max-w-[min(20rem,calc(100vw-2rem))] text-xs rounded-sm text-neutral-700 group-hover:block dark:border-coolgray-500 border-neutral-900 dark:bg-coolgray-400 bg-neutral-200 dark:text-neutral-300 whitespace-normal break-words;
}
@utility buyme {
+25 -8
View File
@@ -1,3 +1,9 @@
@props([
'inline' => false,
'triggerClass' => '',
'panelClass' => '',
])
<div x-data="{
dropdownOpen: false,
panelStyles: '',
@@ -9,7 +15,7 @@
this.dropdownOpen = false;
},
updatePanelPosition() {
if (window.innerWidth >= 768) {
if ({{ $inline ? 'true' : 'false' }} || window.innerWidth >= 768) {
this.panelStyles = '';
return;
@@ -37,9 +43,13 @@
this.panelStyles = `position: fixed; left: ${left}px; top: ${top}px;`;
});
}
}" class="relative" @click.outside="close()" x-on:resize.window="if (dropdownOpen) updatePanelPosition()">
<button x-ref="trigger" @click="dropdownOpen ? close() : open()"
class="inline-flex items-center justify-start pr-8 transition-colors focus:outline-hidden disabled:opacity-50 disabled:pointer-events-none">
}" @class(['relative', 'w-full' => $inline]) @click.outside="if (! {{ $inline ? 'true' : 'false' }}) close()" x-on:resize.window="if (dropdownOpen) updatePanelPosition()">
<button type="button" x-ref="trigger" @click="dropdownOpen ? close() : open()"
@class([
'inline-flex items-center justify-start pr-8 transition-colors focus:outline-hidden disabled:opacity-50 disabled:pointer-events-none',
'w-full border border-neutral-300 bg-white px-3 py-2 text-left dark:border-coolgray-300 dark:bg-coolgray-100' => $inline,
$triggerClass,
])>
<span class="flex flex-col items-start h-full leading-none">
{{ $title }}
</span>
@@ -50,11 +60,18 @@
</svg>
</button>
<div x-ref="panel" x-show="dropdownOpen" @click.away="close()" x-transition:enter="ease-out duration-200"
<div x-ref="panel" x-show="dropdownOpen" @click.away="if (! {{ $inline ? 'true' : 'false' }}) close()" x-transition:enter="ease-out duration-200"
x-transition:enter-start="-translate-y-2" x-transition:enter-end="translate-y-0"
:style="panelStyles" class="absolute top-full z-50 mt-1 min-w-max max-w-[calc(100vw-1rem)] md:top-0 md:mt-6" x-cloak>
<div
class="border border-neutral-300 bg-white p-1 shadow-sm dark:border-coolgray-300 dark:bg-coolgray-200">
:style="panelStyles" @class([
'mt-1 w-full' => $inline,
'absolute top-full z-50 mt-1 min-w-max max-w-[calc(100vw-1rem)] md:top-0 md:mt-6' => ! $inline,
]) x-cloak>
<div @class([
'border border-neutral-300 bg-white p-1 dark:border-coolgray-300',
'shadow-sm dark:bg-coolgray-200' => ! $inline,
'border-0 bg-transparent shadow-none dark:border-0 dark:bg-transparent' => $inline,
$panelClass,
])>
{{ $slot }}
</div>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
<div x-data="{ open: false }" @click.stop="open = !open" @click.outside="open = false"
{{ $attributes->merge(['class' => 'group']) }}>
{{ $attributes->merge(['class' => 'group relative inline-block align-middle']) }}>
<div class="info-helper">
@isset($icon)
{{ $icon }}
@@ -73,7 +73,7 @@
@if (isset($serverType['cpu_vendor_info']) && $serverType['cpu_vendor_info'])
({{ $serverType['cpu_vendor_info'] }})
@endif
, {{ $serverType['memory'] }}GB RAM,
, {{ $serverType['memory'] }}GB RAM,
{{ $serverType['disk'] }}GB
@if (isset($serverType['architecture']))
[{{ $serverType['architecture'] }}]
@@ -135,58 +135,118 @@
</p>
@endif
</div>
<div>
<x-forms.datalist label="Additional SSH Keys (from Hetzner)" id="selectedHetznerSshKeyIds"
helper="Select existing SSH keys from your Hetzner account to add to this server. The Coolify SSH key will be automatically added."
:multiple="true" :disabled="count($hetznerSshKeys) === 0" :placeholder="count($hetznerSshKeys) > 0
? 'Search and select SSH keys...'
: 'No SSH keys found in Hetzner account'">
@foreach ($hetznerSshKeys as $sshKey)
<option value="{{ $sshKey['id'] }}">
{{ $sshKey['name'] }} - {{ substr($sshKey['fingerprint'], 0, 20) }}...
</option>
@endforeach
</x-forms.datalist>
</div>
<div class="flex flex-col gap-2">
<label class="text-sm font-medium">Network Configuration</label>
<div class="flex gap-4">
<x-forms.checkbox id="enable_ipv4" label="Enable IPv4"
helper="Enable public IPv4 address for this server" />
<x-forms.checkbox id="enable_ipv6" label="Enable IPv6"
helper="Enable public IPv6 address for this server" />
</div>
</div>
<div class="flex flex-col gap-2">
<div class="flex justify-between items-center gap-2">
<label class="text-sm font-medium w-32">Cloud-Init Script</label>
@if ($saved_cloud_init_scripts->count() > 0)
<div class="flex items-center gap-2 flex-1">
<x-forms.select wire:model.live="selected_cloud_init_script_id" label="" helper="">
<option value="">Load saved script...</option>
@foreach ($saved_cloud_init_scripts as $script)
<option value="{{ $script->id }}">{{ $script->name }}</option>
@endforeach
</x-forms.select>
<x-forms.button type="button" wire:click="clearCloudInitScript">
Clear
</x-forms.button>
</div>
<x-dropdown inline panelClass="max-h-[55vh] overflow-y-auto scrollbar">
<x-slot:title>
<span class="text-sm font-medium">Advanced Hetzner options</span>
<span class="mt-1 text-xs text-neutral-500 dark:text-neutral-400">SSH keys, firewalls, private networks, backups, and cloud-init.</span>
@if (count($this->advancedHetznerOptionsSummary) > 0)
<span class="mt-1 flex flex-wrap gap-1.5">
@foreach ($this->advancedHetznerOptionsSummary as $summaryItem)
<span class="rounded bg-neutral-200 px-2 py-0.5 text-xs text-neutral-700 dark:bg-coolgray-100 dark:text-neutral-300">
{{ $summaryItem }}
</span>
@endforeach
</span>
@endif
</div>
<x-forms.textarea id="cloud_init_script" label=""
helper="Add a cloud-init script to run when the server is created. See Hetzner's documentation for details."
rows="8" />
</x-slot>
<div class="flex items-center gap-2">
<x-forms.checkbox id="save_cloud_init_script" label="Save this script for later use" />
<div class="flex-1">
<x-forms.input id="cloud_init_script_name" label="" placeholder="Script name..." />
<div class="flex w-full flex-col gap-4 p-3">
<div>
<x-forms.datalist label="Extra SSH Keys" id="selectedHetznerSshKeyIds"
helper="Select existing SSH keys from your Hetzner account to add to this server. The Coolify SSH key will be automatically added."
:multiple="true" :disabled="count($hetznerSshKeys) === 0" :placeholder="count($hetznerSshKeys) > 0
? 'Search and select SSH keys...'
: 'No SSH keys found in Hetzner account'">
@foreach ($hetznerSshKeys as $sshKey)
<option value="{{ $sshKey['id'] }}">
{{ $sshKey['name'] }} - {{ substr($sshKey['fingerprint'], 0, 20) }}...
</option>
@endforeach
</x-forms.datalist>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<x-forms.datalist label="Firewalls" id="selectedHetznerFirewallIds"
helper="Optionally apply existing Hetzner firewalls when the server is created."
:multiple="true" :disabled="count($hetznerFirewalls) === 0" :placeholder="count($hetznerFirewalls) > 0
? 'Search and select firewalls...'
: 'No firewalls found in Hetzner account'">
@foreach ($hetznerFirewalls as $firewall)
<option value="{{ $firewall['id'] }}">
{{ $firewall['name'] }}
@if (isset($firewall['rules']))
- {{ count($firewall['rules']) }} rules
@endif
</option>
@endforeach
</x-forms.datalist>
<x-forms.datalist label="Private Networks" id="selectedHetznerNetworkIds"
helper="Optionally attach one or more private networks. Networks are filtered to the selected location's network zone when possible."
:multiple="true" :disabled="count($this->availableNetworks) === 0" :placeholder="count($this->availableNetworks) > 0
? 'Search and select networks...'
: 'No compatible networks found'">
@foreach ($this->availableNetworks as $network)
<option value="{{ $network['id'] }}">
{{ $network['name'] }} - {{ $network['ip_range'] }}
</option>
@endforeach
</x-forms.datalist>
</div>
<div class="grid grid-cols-1 gap-2 md:grid-cols-3">
<x-forms.checkbox id="enable_ipv4" label="Enable IPv4"
helper="Enable public IPv4 address for this server" fullWidth />
<x-forms.checkbox id="enable_ipv6" label="Enable IPv6"
helper="Enable public IPv6 address for this server" fullWidth />
<x-forms.checkbox id="enable_backups" label="Enable Hetzner Backups" fullWidth
helper="Hetzner bills backups at an additional 20% of the server monthly fee{{ $this->selectedServerBackupSurcharge ? ' (about ' . $this->selectedServerBackupSurcharge . '/mo for the selected server type)' : '' }}." />
</div>
<div class="flex flex-col gap-2">
@if (! $show_cloud_init_script && empty($cloud_init_script) && empty($selected_cloud_init_script_id))
<div>
<x-forms.button type="button" wire:click="showCloudInitScript">
Add cloud-init script
</x-forms.button>
</div>
@else
<div class="flex justify-between items-center gap-2">
<label class="text-sm font-medium w-32">Cloud-Init Script</label>
@if ($saved_cloud_init_scripts->count() > 0)
<div class="flex items-center gap-2 flex-1">
<x-forms.select wire:model.live="selected_cloud_init_script_id" label="" helper="">
<option value="">Load saved script...</option>
@foreach ($saved_cloud_init_scripts as $script)
<option value="{{ $script->id }}">{{ $script->name }}</option>
@endforeach
</x-forms.select>
<x-forms.button type="button" wire:click="clearCloudInitScript">
Clear
</x-forms.button>
</div>
@else
<x-forms.button type="button" wire:click="clearCloudInitScript">
Remove
</x-forms.button>
@endif
</div>
<x-forms.textarea id="cloud_init_script" label=""
helper="Add a cloud-init script to run when the server is created. See Hetzner's documentation for details."
rows="8" />
<div class="flex items-center gap-2">
<x-forms.checkbox id="save_cloud_init_script" label="Save this script for later use" />
@if ($save_cloud_init_script)
<div class="flex-1">
<x-forms.input id="cloud_init_script_name" label="" placeholder="Script name..." />
</div>
@endif
</div>
@endif
</div>
</div>
</div>
</x-dropdown>
<div class="flex gap-2 justify-between">
<x-forms.button type="button" wire:click="previousStep">
@@ -201,4 +261,4 @@
@endif
@endif
@endif
</div>
</div>