2
0

refactor(ui): fix nested forms in pages image upload UI
Some checks failed
Build and Release / Create Release (push) Successful in 0s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 4m0s
Build and Release / Unit Tests (push) Successful in 4m36s
Build and Release / Lint (push) Successful in 6m23s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Failing after 1s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Failing after 0s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 4m50s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 9h5m21s
Build and Release / Build Binary (linux/arm64) (push) Failing after 15m2s

Move upload/delete forms outside main settings form to avoid invalid nested form HTML. Use form attribute on buttons and inputs to associate with hidden forms. Fixes HTML validation errors and potential browser quirks. Also replaces hardcoded border color with CSS variable for theme consistency. Affects brand logo/favicon and hero image upload sections.
This commit is contained in:
2026-03-16 00:31:13 -04:00
parent 044c65e425
commit fca0461ca4
2 changed files with 48 additions and 36 deletions

View File

@@ -11,29 +11,26 @@
<input name="brand_name" value="{{.Config.Brand.Name}}" placeholder="{{.Repository.Name}}">
<p class="help">{{ctx.Locale.Tr "repo.settings.pages.brand_name_help"}}</p>
</div>
<h5 class="ui dividing header">{{ctx.Locale.Tr "repo.settings.pages.brand_logo"}}</h5>
{{if .Config.Brand.UploadedLogo}}
<div class="field">
<img src="/repo-avatars/{{.Config.Brand.UploadedLogo}}" style="max-width:200px;max-height:100px;border-radius:8px;border:1px solid #ddd;">
<img src="/repo-avatars/{{.Config.Brand.UploadedLogo}}" style="max-width:200px;max-height:100px;border-radius:8px;border:1px solid var(--color-secondary);">
<div class="tw-mt-2">
<form method="post" action="{{.Link}}/delete_logo" class="ignore-dirty" style="display:inline;">
{{$.CsrfTokenHtml}}
<button class="ui mini red button" type="submit">
{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "repo.settings.pages.brand_delete_logo"}}
</button>
</form>
<button class="ui mini red button" type="submit" form="delete-logo-form">
{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "repo.settings.pages.brand_delete_logo"}}
</button>
</div>
</div>
{{else}}
<div class="field">
<label>{{ctx.Locale.Tr "repo.settings.pages.brand_upload_logo"}}</label>
<form method="post" enctype="multipart/form-data" action="{{.Link}}/upload_logo" class="ignore-dirty tw-flex tw-gap-2 tw-items-center">
{{$.CsrfTokenHtml}}
<input type="file" name="brand_logo" accept="image/jpeg,image/png,image/webp,image/gif">
<button class="ui primary button" type="submit">
<div class="tw-flex tw-gap-2 tw-items-center">
<input type="file" name="brand_logo" accept="image/jpeg,image/png,image/webp,image/gif" form="upload-logo-form">
<button class="ui primary button" type="submit" form="upload-logo-form">
{{svg "octicon-upload" 16}} {{ctx.Locale.Tr "repo.settings.pages.brand_upload_btn"}}
</button>
</form>
</div>
<p class="help">{{ctx.Locale.Tr "repo.settings.pages.brand_upload_help"}}</p>
</div>
<div class="ui horizontal divider">{{ctx.Locale.Tr "repo.settings.pages.brand_or"}}</div>
@@ -43,33 +40,31 @@
<p class="help">{{ctx.Locale.Tr "repo.settings.pages.brand_logo_url_help"}}</p>
</div>
{{end}}
<div class="field">
<label>{{ctx.Locale.Tr "repo.settings.pages.brand_tagline"}}</label>
<input name="brand_tagline" value="{{.Config.Brand.Tagline}}" placeholder="Your tagline here">
</div>
<h5 class="ui dividing header">{{ctx.Locale.Tr "repo.settings.pages.brand_favicon"}}</h5>
{{if .Config.Brand.UploadedFavicon}}
<div class="field">
<img src="/repo-avatars/{{.Config.Brand.UploadedFavicon}}" style="max-width:64px;max-height:64px;border-radius:4px;border:1px solid #ddd;">
<img src="/repo-avatars/{{.Config.Brand.UploadedFavicon}}" style="max-width:64px;max-height:64px;border-radius:4px;border:1px solid var(--color-secondary);">
<div class="tw-mt-2">
<form method="post" action="{{.Link}}/delete_favicon" class="ignore-dirty" style="display:inline;">
{{$.CsrfTokenHtml}}
<button class="ui mini red button" type="submit">
{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "repo.settings.pages.brand_delete_favicon"}}
</button>
</form>
<button class="ui mini red button" type="submit" form="delete-favicon-form">
{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "repo.settings.pages.brand_delete_favicon"}}
</button>
</div>
</div>
{{else}}
<div class="field">
<label>{{ctx.Locale.Tr "repo.settings.pages.brand_upload_favicon"}}</label>
<form method="post" enctype="multipart/form-data" action="{{.Link}}/upload_favicon" class="ignore-dirty tw-flex tw-gap-2 tw-items-center">
{{$.CsrfTokenHtml}}
<input type="file" name="brand_favicon" accept="image/jpeg,image/png,image/webp,image/gif,image/x-icon,image/svg+xml">
<button class="ui primary button" type="submit">
<div class="tw-flex tw-gap-2 tw-items-center">
<input type="file" name="brand_favicon" accept="image/jpeg,image/png,image/webp,image/gif,image/x-icon,image/svg+xml" form="upload-favicon-form">
<button class="ui primary button" type="submit" form="upload-favicon-form">
{{svg "octicon-upload" 16}} {{ctx.Locale.Tr "repo.settings.pages.brand_upload_btn"}}
</button>
</form>
</div>
<p class="help">{{ctx.Locale.Tr "repo.settings.pages.brand_favicon_upload_help"}}</p>
</div>
<div class="ui horizontal divider">{{ctx.Locale.Tr "repo.settings.pages.brand_or"}}</div>
@@ -79,10 +74,24 @@
<p class="help">{{ctx.Locale.Tr "repo.settings.pages.brand_favicon_url_help"}}</p>
</div>
{{end}}
<div class="field">
<button class="ui primary button">{{ctx.Locale.Tr "save"}}</button>
</div>
</form>
{{/* Separate forms for upload/delete actions outside the main form to avoid nesting */}}
{{if .Config.Brand.UploadedLogo}}
<form id="delete-logo-form" method="post" action="{{.Link}}/delete_logo" class="tw-hidden">{{.CsrfTokenHtml}}</form>
{{else}}
<form id="upload-logo-form" method="post" enctype="multipart/form-data" action="{{.Link}}/upload_logo" class="tw-hidden">{{.CsrfTokenHtml}}</form>
{{end}}
{{if .Config.Brand.UploadedFavicon}}
<form id="delete-favicon-form" method="post" action="{{.Link}}/delete_favicon" class="tw-hidden">{{.CsrfTokenHtml}}</form>
{{else}}
<form id="upload-favicon-form" method="post" enctype="multipart/form-data" action="{{.Link}}/upload_favicon" class="tw-hidden">{{.CsrfTokenHtml}}</form>
{{end}}
</div>
</div>
{{template "repo/settings/layout_footer" .}}

View File

@@ -15,26 +15,22 @@
<h5 class="ui dividing header">{{ctx.Locale.Tr "repo.settings.pages.hero_image"}}</h5>
{{if .Config.Hero.UploadedImage}}
<div class="field">
<img src="/repo-avatars/{{.Config.Hero.UploadedImage}}" style="max-width:400px;max-height:250px;border-radius:8px;border:1px solid #ddd;">
<img src="/repo-avatars/{{.Config.Hero.UploadedImage}}" style="max-width:400px;max-height:250px;border-radius:8px;border:1px solid var(--color-secondary);">
<div class="tw-mt-2">
<form method="post" action="{{.Link}}/delete_image" class="ignore-dirty" style="display:inline;">
{{$.CsrfTokenHtml}}
<button class="ui mini red button" type="submit">
{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "repo.settings.pages.hero_delete_image"}}
</button>
</form>
<button class="ui mini red button" type="submit" form="delete-hero-form">
{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "repo.settings.pages.hero_delete_image"}}
</button>
</div>
</div>
{{else}}
<div class="field">
<label>{{ctx.Locale.Tr "repo.settings.pages.hero_upload"}}</label>
<form method="post" enctype="multipart/form-data" action="{{.Link}}/upload_image" class="ignore-dirty tw-flex tw-gap-2 tw-items-center">
{{$.CsrfTokenHtml}}
<input type="file" name="hero_image" accept="image/jpeg,image/png,image/webp,image/gif">
<button class="ui primary button" type="submit">
<div class="tw-flex tw-gap-2 tw-items-center">
<input type="file" name="hero_image" accept="image/jpeg,image/png,image/webp,image/gif" form="upload-hero-form">
<button class="ui primary button" type="submit" form="upload-hero-form">
{{svg "octicon-upload" 16}} {{ctx.Locale.Tr "repo.settings.pages.hero_upload_btn"}}
</button>
</form>
</div>
<p class="help">{{ctx.Locale.Tr "repo.settings.pages.hero_upload_help"}}</p>
</div>
<div class="ui horizontal divider">{{ctx.Locale.Tr "repo.settings.pages.hero_or"}}</div>
@@ -78,6 +74,13 @@
<button class="ui primary button">{{ctx.Locale.Tr "save"}}</button>
</div>
</form>
{{/* Separate forms for upload/delete actions outside the main form to avoid nesting */}}
{{if .Config.Hero.UploadedImage}}
<form id="delete-hero-form" method="post" action="{{.Link}}/delete_image" class="tw-hidden">{{.CsrfTokenHtml}}</form>
{{else}}
<form id="upload-hero-form" method="post" enctype="multipart/form-data" action="{{.Link}}/upload_image" class="tw-hidden">{{.CsrfTokenHtml}}</form>
{{end}}
</div>
</div>
{{template "repo/settings/layout_footer" .}}