Attachment remove fires both an htmx POST and a JS DELETE, discarding unsaved description edits
Description
The attachment remove button carries both htmx attributes and a data- hook handled by app.js. Both fire; preventDefault() cannot cancel htmx because htmx is bound directly on the button.
internal/server/templates/description_components.html:63:
<button type="button" data-attachment-remove data-attachment-delete-url="{{.DeleteJSONHref}}"
hx-post="{{.DeleteHref}}" hx-target="#main" hx-push-url="false" ...>
The competing delegated listener is internal/server/static/app.js:1121-1136, which calls event.preventDefault() and issues fetch(..., {method: "DELETE"}) when the list is in editing mode (data-attachment-editing, set at description_components.html:31 from ui_description_attachments.go:38).
The htmx handler hits uiDeleteIssueAttachment (internal/server/issue_attachments.go:111-125), which rebuilds the panel with EditDescription unset and renders issue-panel into #main. Same shape in project_attachments.go:117, sprint_attachments.go:115, context_attachments.go:106.
Steps to reproduce
- Open an issue with an attachment.
- Click Edit description.
- With the editor open, click the trash icon on an attachment.
Actual
The description editor is torn down and replaced by the read-only panel, losing unsaved edits. A second, redundant DELETE fires against the already-deleted attachment, 404s, and is silently swallowed by if (!res.ok) return;.
Expected
One request. In editing mode the JS path should own the click and the editor should stay open.
Fix
Omit hx-post/hx-target from the button when Editing is true so only one mechanism is bound, and assert in a template test that the two are mutually exclusive.
Sub-issues
0Linked issues
0GitHub
0No branches or pull requests linked.