arimelody.me/admin/components/tracks/edittracks.html

113 lines
4.1 KiB
HTML
Raw Normal View History

<dialog id="edittracks">
<header>
<h2>Editing: Tracks</h2>
<a id="add-track"
class="button new"
href="/admin/release/{{.ID}}/addtrack"
hx-get="/admin/release/{{.ID}}/addtrack"
hx-target="body"
hx-swap="beforeend"
>Add</a>
</header>
<form action="/api/v1/music/{{.ID}}/tracks">
<ul>
{{range .Tracks}}
<li class="track" data-track="{{.ID}}" data-title="{{.Title}}" data-number="{{.Number}}" draggable="true">
<div>
<p class="track-name">
<span class="track-number">{{.Number}}</span>
{{.Title}}
</p>
<a class="delete">Delete</a>
</div>
</li>
{{end}}
</ul>
<div class="dialog-actions">
<button id="discard" type="button">Discard</button>
<button id="save" type="submit" class="save">Save</button>
</div>
</form>
<script type="module">
import { makeMagicList } from "/admin/static/admin.js";
(() => {
const container = document.getElementById("edittracks");
const form = document.querySelector("#edittracks form");
const trackList = form.querySelector("ul");
const addTrackBtn = document.getElementById("add-track");
const discardBtn = form.querySelector("button#discard");
makeMagicList(trackList, ".track", refreshTrackNumbers);
function rigTrackItem(trackItem) {
const trackID = trackItem.dataset.track;
const trackTitle = trackItem.dataset.title;
const deleteBtn = trackItem.querySelector("a.delete");
deleteBtn.addEventListener("click", e => {
e.preventDefault();
if (!confirm("Are you sure you want to remove " + trackTitle + "?")) return;
trackItem.remove();
refreshTrackNumbers();
});
}
function refreshTrackNumbers() {
trackList.querySelectorAll("li").forEach((trackItem, i) => {
trackItem.querySelector(".track-number").innerText = i + 1;
});
}
trackList.addEventListener("htmx:afterSwap", e => {
const trackItem = trackList.children[trackList.children.length - 1];
trackList.appendChild(trackItem);
trackItem.addEventListener("dragstart", () => { trackItem.classList.add("moving") });
trackItem.addEventListener("dragend", () => { trackItem.classList.remove("moving") });
rigTrackItem(trackItem);
refreshTrackNumbers();
});
trackList.querySelectorAll("li").forEach(trackItem => {
rigTrackItem(trackItem);
});
container.showModal();
container.addEventListener("close", () => {
container.remove();
});
form.addEventListener("submit", e => {
e.preventDefault();
let tracks = [...trackList.querySelectorAll(".track")].map(trackItem => trackItem.dataset.track);
fetch(form.action, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(tracks)
}).then(res => {
if (res.ok) location = location;
else {
res.text().then(err => {
alert(err);
console.error(err);
});
}
}).catch(err => {
alert("Failed to update tracks. Check the console for details.");
console.error(err);
});
});
discardBtn.addEventListener("click", e => {
e.preventDefault();
container.close();
});
})();
</script>
</dialog>