120 lines
4.5 KiB
HTML
120 lines
4.5 KiB
HTML
<dialog id="editcredits">
|
|
<header>
|
|
<h2>Editing: Credits</h2>
|
|
<a id="add-credit"
|
|
class="button new"
|
|
href="/admin/release/{{.ID}}/addcredit"
|
|
hx-get="/admin/release/{{.ID}}/addcredit"
|
|
hx-target="body"
|
|
hx-swap="beforeend"
|
|
>Add</a>
|
|
</header>
|
|
|
|
<form action="/api/v1/music/{{.ID}}/credits">
|
|
<ul>
|
|
{{range .Credits}}
|
|
<li class="credit" data-artist="{{.Artist.ID}}">
|
|
<div>
|
|
<img src="{{.Artist.GetAvatar}}" alt="" width="64" loading="lazy" class="artist-avatar">
|
|
<div class="credit-info">
|
|
<p class="artist-name">{{.Artist.Name}}</p>
|
|
<div class="credit-attribute">
|
|
<label for="role">Role:</label>
|
|
<input type="text" name="role" value="{{.Role}}">
|
|
</div>
|
|
<div class="credit-attribute">
|
|
<label for="primary">Primary:</label>
|
|
<input type="checkbox" name="primary" {{if .Primary}}checked{{end}}>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="delete">Delete</button>
|
|
</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">
|
|
(() => {
|
|
const container = document.getElementById("editcredits");
|
|
const form = document.querySelector("#editcredits form");
|
|
const creditList = form.querySelector("ul");
|
|
const addCreditBtn = document.getElementById("add-credit");
|
|
const discardBtn = form.querySelector("button#discard");
|
|
|
|
function creditFromElement(el) {
|
|
const artistID = el.dataset.artist;
|
|
const roleInput = el.querySelector(`input[name="role"]`)
|
|
const primaryInput = el.querySelector(`input[name="primary"]`)
|
|
const deleteBtn = el.querySelector("button.delete");
|
|
|
|
let credit = {
|
|
"artist": artistID,
|
|
"role": roleInput.value,
|
|
"primary": primaryInput.checked,
|
|
};
|
|
|
|
roleInput.addEventListener("change", () => {
|
|
credit.role = roleInput.value;
|
|
});
|
|
primaryInput.addEventListener("change", () => {
|
|
credit.primary = primaryInput.checked;
|
|
});
|
|
deleteBtn.addEventListener("click", e => {
|
|
if (!confirm("Are you sure you want to delete " + artistID + "'s credit?")) return;
|
|
el.remove();
|
|
credits = credits.filter(credit => credit.artist != artistID);
|
|
});
|
|
|
|
return credit;
|
|
}
|
|
|
|
let credits = [...form.querySelectorAll(".credit")].map(el => creditFromElement(el));
|
|
|
|
creditList.addEventListener("htmx:afterSwap", e => {
|
|
const el = creditList.children[creditList.children.length - 1];
|
|
const credit = creditFromElement(el);
|
|
credits.push(credit);
|
|
});
|
|
|
|
container.showModal();
|
|
|
|
container.addEventListener("close", () => {
|
|
container.remove();
|
|
});
|
|
|
|
form.addEventListener("submit", e => {
|
|
e.preventDefault();
|
|
fetch(form.action, {
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(credits)
|
|
}).then(res => {
|
|
if (res.ok) location = location;
|
|
else {
|
|
res.text().then(err => {
|
|
alert(err);
|
|
console.error(err);
|
|
});
|
|
}
|
|
}).catch(err => {
|
|
alert("Failed to update credits. Check the console for details");
|
|
console.error(err);
|
|
});
|
|
});
|
|
|
|
discardBtn.addEventListener("click", e => {
|
|
e.preventDefault();
|
|
container.close();
|
|
});
|
|
})();
|
|
</script>
|
|
</dialog>
|