fix: move base directory path normalization to frontend

Change wire:model.blur to wire:model.defer to prevent backend requests
during form navigation. Add Alpine.js path normalization functions that
run on blur, fixing tab focus issues while keeping path validation
purely on the frontend.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai 2025-12-01 13:51:21 +01:00
parent b55aaf34d3
commit 981fc127b5
5 changed files with 77 additions and 45 deletions

View file

@ -75,16 +75,6 @@ public function mount()
$this->github_apps = GithubApp::private();
}
public function updatedBaseDirectory()
{
if ($this->base_directory) {
$this->base_directory = rtrim($this->base_directory, '/');
if (! str($this->base_directory)->startsWith('/')) {
$this->base_directory = '/'.$this->base_directory;
}
}
}
public function updatedBuildPack()
{
if ($this->build_pack === 'nixpacks') {

View file

@ -107,26 +107,6 @@ public function mount()
$this->query = request()->query();
}
public function updatedBaseDirectory()
{
if ($this->base_directory) {
$this->base_directory = rtrim($this->base_directory, '/');
if (! str($this->base_directory)->startsWith('/')) {
$this->base_directory = '/'.$this->base_directory;
}
}
}
public function updatedDockerComposeLocation()
{
if ($this->docker_compose_location) {
$this->docker_compose_location = rtrim($this->docker_compose_location, '/');
if (! str($this->docker_compose_location)->startsWith('/')) {
$this->docker_compose_location = '/'.$this->docker_compose_location;
}
}
}
public function updatedBuildPack()
{
if ($this->build_pack === 'nixpacks') {

View file

@ -61,12 +61,33 @@ class="loading loading-xs dark:text-warning loading-spinner"></span>
@endif
</div>
@if ($build_pack === 'dockercompose')
<div x-data="{ baseDir: '{{ $base_directory }}', composeLocation: '{{ $docker_compose_location }}' }" class="gap-2 flex flex-col">
<x-forms.input placeholder="/" wire:model.blur="base_directory" label="Base Directory"
helper="Directory to use as root. Useful for monorepos." x-model="baseDir" />
<x-forms.input placeholder="/docker-compose.yaml" wire:model.blur="docker_compose_location"
<div x-data="{
baseDir: '{{ $base_directory }}',
composeLocation: '{{ $docker_compose_location }}',
normalizePath(path) {
if (!path || path.trim() === '') return '/';
path = path.trim();
// Remove trailing slashes
path = path.replace(/\/+$/, '');
// Ensure leading slash
if (!path.startsWith('/')) {
path = '/' + path;
}
return path;
},
normalizeBaseDir() {
this.baseDir = this.normalizePath(this.baseDir);
},
normalizeComposeLocation() {
this.composeLocation = this.normalizePath(this.composeLocation);
}
}" class="gap-2 flex flex-col">
<x-forms.input placeholder="/" wire:model.defer="base_directory" label="Base Directory"
helper="Directory to use as root. Useful for monorepos." x-model="baseDir"
@blur="normalizeBaseDir()" />
<x-forms.input placeholder="/docker-compose.yaml" wire:model.defer="docker_compose_location"
label="Docker Compose Location" helper="It is calculated together with the Base Directory."
x-model="composeLocation" />
x-model="composeLocation" @blur="normalizeComposeLocation()" />
<div class="pt-2">
<span>
Compose file location in your repository: </span><span class='dark:text-warning'

View file

@ -95,15 +95,35 @@
@endif
</div>
@if ($build_pack === 'dockercompose')
<div x-data="{ baseDir: '{{ $base_directory }}', composeLocation: '{{ $docker_compose_location }}' }" class="gap-2 flex flex-col">
<x-forms.input placeholder="/" wire:model.blur="base_directory"
<div x-data="{
baseDir: '{{ $base_directory }}',
composeLocation: '{{ $docker_compose_location }}',
normalizePath(path) {
if (!path || path.trim() === '') return '/';
path = path.trim();
// Remove trailing slashes
path = path.replace(/\/+$/, '');
// Ensure leading slash
if (!path.startsWith('/')) {
path = '/' + path;
}
return path;
},
normalizeBaseDir() {
this.baseDir = this.normalizePath(this.baseDir);
},
normalizeComposeLocation() {
this.composeLocation = this.normalizePath(this.composeLocation);
}
}" class="gap-2 flex flex-col">
<x-forms.input placeholder="/" wire:model.defer="base_directory"
label="Base Directory"
helper="Directory to use as root. Useful for monorepos."
x-model="baseDir" />
x-model="baseDir" @blur="normalizeBaseDir()" />
<x-forms.input placeholder="/docker-compose.yaml"
wire:model.blur="docker_compose_location" label="Docker Compose Location"
wire:model.defer="docker_compose_location" label="Docker Compose Location"
helper="It is calculated together with the Base Directory."
x-model="composeLocation" />
x-model="composeLocation" @blur="normalizeComposeLocation()" />
<div class="pt-2">
<span>
Compose file location in your repository: </span><span

View file

@ -52,12 +52,33 @@
@endif
</div>
@if ($build_pack === 'dockercompose')
<div x-data="{ baseDir: '{{ $base_directory }}', composeLocation: '{{ $docker_compose_location }}' }" class="gap-2 flex flex-col">
<x-forms.input placeholder="/" wire:model.blur="base_directory" label="Base Directory"
helper="Directory to use as root. Useful for monorepos." x-model="baseDir" />
<x-forms.input placeholder="/docker-compose.yaml" wire:model.blur="docker_compose_location"
<div x-data="{
baseDir: '{{ $base_directory }}',
composeLocation: '{{ $docker_compose_location }}',
normalizePath(path) {
if (!path || path.trim() === '') return '/';
path = path.trim();
// Remove trailing slashes
path = path.replace(/\/+$/, '');
// Ensure leading slash
if (!path.startsWith('/')) {
path = '/' + path;
}
return path;
},
normalizeBaseDir() {
this.baseDir = this.normalizePath(this.baseDir);
},
normalizeComposeLocation() {
this.composeLocation = this.normalizePath(this.composeLocation);
}
}" class="gap-2 flex flex-col">
<x-forms.input placeholder="/" wire:model.defer="base_directory" label="Base Directory"
helper="Directory to use as root. Useful for monorepos." x-model="baseDir"
@blur="normalizeBaseDir()" />
<x-forms.input placeholder="/docker-compose.yaml" wire:model.defer="docker_compose_location"
label="Docker Compose Location" helper="It is calculated together with the Base Directory."
x-model="composeLocation" />
x-model="composeLocation" @blur="normalizeComposeLocation()" />
<div class="pt-2">
<span>
Compose file location in your repository: </span><span class='dark:text-warning'