Files
alembic/app/templates/library/track_detail.html
T
andrew 92e5326437 Fix dedup apply lock-hang, mawk-broken tag passes; add track delete, fix button/select CSS
confirm_and_apply no longer marks candidates confirmed before their apply
job actually succeeds (a stuck/skipped_lock run was silently vanishing
confirmed deletes without deleting anything), switches the fuzzy pass to
--apply-pairs to avoid a full rescan on every confirm, and adds a job
timeout so a hung subprocess can't hold the global pipeline lock forever.

dedup-library.sh's Pass 2-4 use gawk-only features (gensub, POSIX interval
regex) but were running under mawk (Debian's default awk) in the deployed
image, throwing silent syntax errors on every run -- switched those
invocations to gawk explicitly and added it to the Dockerfile.

Also: per-track delete button on the library list/detail pages, and two
CSS fixes (the primary button's hover gradient was getting clobbered by
the base .btn:hover rule's plain background, and the select dropdown
arrow had no background-size so it rendered oversized).
2026-07-09 09:12:02 -06:00

63 lines
2.4 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ item.artist }} — {{ item.title }} — alembic{% endblock %}
{% block content %}
<a class="back-link" href="/library">&larr; back to library</a>
<div class="page-header">
<div>
<h1>{{ item.artist }} — {{ item.title }}</h1>
<p class="subtitle muted mono truncate" style="max-width:none;">{{ item.path }}</p>
</div>
</div>
{% if request.query_params.get('changed') %}
<div class="notice success">Updated {{ request.query_params.get('changed') }} field(s).</div>
{% endif %}
<h2>Edit tags</h2>
<div class="panel" style="max-width:560px;">
<form method="post" action="/library/track/{{ item.id }}">
{% for field in editable_fields %}
<div class="field">
<label for="{{ field }}">{{ field }}</label>
<input type="text" id="{{ field }}" name="{{ field }}" value="{{ item.get(field, '') or '' }}">
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
<h2>Set genre for this artist (all their tracks)</h2>
<div class="panel" style="max-width:560px;">
<form method="post" action="/library/track/{{ item.id }}/genre">
<input type="hidden" name="artist" value="{{ item.artist }}">
<div class="field">
<label for="genre">Genre</label>
<input type="text" id="genre" name="genre" required placeholder="IDM; Electronic">
</div>
<button type="submit" class="btn">Set genre</button>
</form>
</div>
<h2>Re-fetch metadata from Spotify/iTunes URL</h2>
<div class="panel" style="max-width:560px;">
<form method="post" action="/library/track/{{ item.id }}/retag">
<div class="field">
<label for="url">URL</label>
<input type="text" id="url" name="url" required>
</div>
<label class="checkbox-field"><input type="checkbox" name="keep_genre" value="true"> Keep existing genre</label>
<button type="submit" class="btn">Retag</button>
</form>
</div>
<h2>Danger zone</h2>
<div class="panel" style="max-width:560px;">
<p class="muted" style="margin-top:0;">Removes this track from beets and deletes the file from disk. Not reversible.</p>
<form method="post" action="/library/track/{{ item.id }}/delete"
onsubmit="return confirm('Delete {{ item.artist }} — {{ item.title }}? This removes the file from disk permanently.')">
<button type="submit" class="btn btn-danger">Delete this track</button>
</form>
</div>
{% endblock %}