trackslash
TRACK-53 P2

Attachment remove fires both an htmx POST and a JS DELETE, discarding unsaved description edits

0
All issues

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

  1. Open an issue with an attachment.
  2. Click Edit description.
  3. 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

0

Linked issues

0

GitHub

0

No branches or pull requests linked.

Comments

0
No comments.