add release credits update UI

Signed-off-by: ari melody <ari@arimelody.me>
This commit is contained in:
ari melody 2024-08-23 23:08:28 +01:00
parent 7914fba52a
commit 34cddcfdb2
27 changed files with 630 additions and 340 deletions

View file

@ -0,0 +1,48 @@
<dialog id="addcredit">
<header>
<h2>Add artist credit</h2>
</header>
<ul>
{{range $Artist := .Artists}}
<li class="new-artist"
data-id="{{$Artist.ID}}"
hx-get="/admin/release/{{$.ReleaseID}}/newcredit/{{$Artist.ID}}"
hx-target="#editcredits ul"
hx-swap="beforeend"
>
<img src="{{$Artist.GetAvatar}}" alt="" width="16" loading="lazy" class="artist-avatar">
<span class="artist-name">{{$Artist.Name}}</span>
<span class="artist-id">({{$Artist.ID}})</span>
</li>
{{end}}
</ul>
{{if not .Artists}}
<p class="empty">There are no more artists to add.</p>
{{end}}
<div class="dialog-actions">
<button id="cancel" type="button">Cancel</button>
</div>
<script type="text/javascript">
(() => {
const newCreditModal = document.getElementById("addcredit")
const editCreditsModal = document.getElementById("editcredits")
const cancelBtn = newCreditModal.querySelector("#cancel");
editCreditsModal.addEventListener("htmx:afterSwap", () => {
newCreditModal.close();
newCreditModal.remove();
});
cancelBtn.addEventListener("click", () => {
newCreditModal.close();
newCreditModal.remove();
});
newCreditModal.showModal();
})();
</script>
</dialog>

View file

@ -0,0 +1,119 @@
<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>

View file

@ -0,0 +1,17 @@
<li class="credit" data-artist="{{.ID}}">
<div>
<img src="{{.GetAvatar}}" alt="" width="64" loading="lazy" class="artist-avatar">
<div class="credit-info">
<p class="artist-name">{{.Name}}</p>
<div class="credit-attribute">
<label for="role">Role:</label>
<input type="text" name="role" value="">
</div>
<div class="credit-attribute">
<label for="primary">Primary:</label>
<input type="checkbox" name="primary">
</div>
</div>
<button type="button" class="delete">Delete</button>
</div>
</li>