more admin dashboard polish, some code cleanup
This commit is contained in:
parent
65f277b3f2
commit
a66460be19
23 changed files with 163 additions and 231 deletions
|
|
@ -157,7 +157,8 @@ func serveAddCredit(app *model.AppState, release *model.Release) http.Handler {
|
|||
|
||||
func serveNewCredit(app *model.AppState) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
artistID := strings.Split(r.URL.Path, "/")[3]
|
||||
split := strings.Split(r.URL.Path, "/")
|
||||
artistID := split[len(split) - 1]
|
||||
artist, err := controller.GetArtist(app.DB, artistID)
|
||||
if err != nil {
|
||||
fmt.Printf("WARN: Failed to fetch artist %s: %s\n", artistID, err)
|
||||
|
|
@ -231,7 +232,8 @@ func serveAddTrack(app *model.AppState, release *model.Release) http.Handler {
|
|||
|
||||
func serveNewTrack(app *model.AppState) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
trackID := strings.Split(r.URL.Path, "/")[3]
|
||||
split := strings.Split(r.URL.Path, "/")
|
||||
trackID := split[len(split) - 1]
|
||||
track, err := controller.GetTrack(app.DB, trackID)
|
||||
if err != nil {
|
||||
fmt.Printf("WARN: Failed to fetch track %s: %s\n", trackID, err)
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ body {
|
|||
font-family: "Inter", sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--fg-0);
|
||||
background: var(--bg-0);
|
||||
background-color: var(--bg-0);
|
||||
|
||||
transition: background .1s ease-out, color .1s ease-out;
|
||||
}
|
||||
|
|
@ -252,12 +252,6 @@ a {
|
|||
transition: color .1s ease-out, background-color .1s ease-out;
|
||||
}
|
||||
|
||||
/*
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
*/
|
||||
|
||||
img.icon {
|
||||
height: .8em;
|
||||
transition: filter .1s ease-out;
|
||||
|
|
@ -283,7 +277,7 @@ code {
|
|||
.card {
|
||||
flex-basis: 40em;
|
||||
padding: 1em;
|
||||
background: var(--bg-1);
|
||||
background-color: var(--bg-1);
|
||||
border-radius: 16px;
|
||||
box-shadow: var(--shadow-lg);
|
||||
|
||||
|
|
@ -361,7 +355,7 @@ a.delete:not(.button) {
|
|||
font-size: inherit;
|
||||
|
||||
color: inherit;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
border: none;
|
||||
border-radius: 10em;
|
||||
box-shadow: var(--shadow-sm);
|
||||
|
|
@ -380,27 +374,27 @@ button:active, .button:active {
|
|||
|
||||
.button.new, button.new {
|
||||
color: var(--col-on-new);
|
||||
background: var(--col-new);
|
||||
background-color: var(--col-new);
|
||||
}
|
||||
.button.save, button.save {
|
||||
color: var(--col-on-save);
|
||||
background: var(--col-save);
|
||||
background-color: var(--col-save);
|
||||
}
|
||||
.button.delete, button.delete {
|
||||
color: var(--col-on-delete);
|
||||
background: var(--col-delete);
|
||||
background-color: var(--col-delete);
|
||||
}
|
||||
.button:hover, button:hover {
|
||||
color: var(--bg-3);
|
||||
background: var(--fg-3);
|
||||
background-color: var(--fg-3);
|
||||
}
|
||||
.button:active, button:active {
|
||||
color: var(--bg-2);
|
||||
background: var(--fg-0);
|
||||
background-color: var(--fg-0);
|
||||
}
|
||||
.button[disabled], button[disabled] {
|
||||
color: var(--fg-0) !important;
|
||||
background: var(--bg-3) !important;
|
||||
background-color: var(--bg-3) !important;
|
||||
opacity: .5;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
padding: .5em;
|
||||
|
||||
color: var(--fg-3);
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
|
||||
.artist:hover {
|
||||
background: var(--bg-1);
|
||||
background-color: var(--bg-1);
|
||||
text-decoration: hover;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,4 +4,29 @@ document.addEventListener("readystatechange", () => {
|
|||
document.querySelectorAll(".artists-group .artist").forEach(el => {
|
||||
hijackClickEvent(el, el.querySelector("a.artist-name"))
|
||||
});
|
||||
|
||||
const newArtistBtn = document.getElementById("create-artist");
|
||||
if (newArtistBtn) newArtistBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
const id = prompt("Enter an ID for this artist:");
|
||||
if (id == null || id == "") return;
|
||||
|
||||
fetch("/api/v1/artist", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({id})
|
||||
}).then(res => {
|
||||
res.text().then(text => {
|
||||
if (res.ok) {
|
||||
location = "/admin/artists/" + id;
|
||||
} else {
|
||||
alert(text);
|
||||
console.error(text);
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
alert("Failed to create artist. Check the console for details.");
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ form#delete-account input {
|
|||
justify-content: space-between;
|
||||
|
||||
color: var(--fg-3);
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
gap: 1.2em;
|
||||
|
||||
border-radius: 16px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
|
|
@ -50,18 +50,11 @@ input[type="text"] {
|
|||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
background: var(--bg-0);
|
||||
background-color: var(--bg-0);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
outline: none;
|
||||
}
|
||||
input[type="text"]:hover {
|
||||
border-color: #80808080;
|
||||
}
|
||||
input[type="text"]:active,
|
||||
input[type="text"]:focus {
|
||||
border-color: #808080;
|
||||
}
|
||||
|
||||
.artist-actions {
|
||||
margin-top: auto;
|
||||
|
|
@ -84,7 +77,7 @@ input[type="text"]:focus {
|
|||
align-items: center;
|
||||
|
||||
border-radius: 16px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
cursor: pointer;
|
||||
|
|
@ -92,7 +85,7 @@ input[type="text"]:focus {
|
|||
}
|
||||
|
||||
.credit:hover {
|
||||
background: var(--bg-1);
|
||||
background-color: var(--bg-1);
|
||||
}
|
||||
|
||||
.release-artwork {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ input[type="text"] {
|
|||
gap: 1.2em;
|
||||
|
||||
border-radius: 8px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
transition: background .1s ease-out, color .1s ease-out;
|
||||
|
|
@ -33,7 +33,7 @@ input[type="text"] {
|
|||
.release-artwork #remove-artwork {
|
||||
margin-top: .5em;
|
||||
padding: .3em .6em;
|
||||
background: var(--bg-3);
|
||||
background-color: var(--bg-3);
|
||||
}
|
||||
|
||||
.release-info {
|
||||
|
|
@ -62,13 +62,13 @@ input[type="text"] {
|
|||
}
|
||||
|
||||
#title:hover {
|
||||
background: var(--bg-3);
|
||||
background-color: var(--bg-3);
|
||||
border-color: var(--fg-0);
|
||||
}
|
||||
|
||||
#title:active,
|
||||
#title:focus {
|
||||
background: var(--bg-3);
|
||||
background-color: var(--bg-3);
|
||||
}
|
||||
|
||||
.release-title small {
|
||||
|
|
@ -93,7 +93,7 @@ input[type="text"] {
|
|||
.release-info table tr td:not(:first-child) select:hover,
|
||||
.release-info table tr td:not(:first-child) input:hover,
|
||||
.release-info table tr td:not(:first-child) textarea:hover {
|
||||
background: var(--bg-3);
|
||||
background-color: var(--bg-3);
|
||||
cursor: pointer;
|
||||
}
|
||||
.release-info table td select,
|
||||
|
|
@ -127,7 +127,7 @@ input[type="text"] {
|
|||
.release-actions button,
|
||||
.release-actions .button {
|
||||
color: var(--fg-2);
|
||||
background: var(--bg-3);
|
||||
background-color: var(--bg-3);
|
||||
}
|
||||
|
||||
dialog {
|
||||
|
|
@ -234,7 +234,7 @@ dialog div.dialog-actions {
|
|||
gap: 1em;
|
||||
|
||||
border-radius: 8px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ dialog div.dialog-actions {
|
|||
border: none;
|
||||
border-radius: 4px;
|
||||
color: var(--fg-2);
|
||||
background: var(--bg-0);
|
||||
background-color: var(--bg-0);
|
||||
}
|
||||
#editcredits .credit .credit-info .credit-attribute input[type="checkbox"] {
|
||||
margin: 0 .3em;
|
||||
|
|
@ -299,6 +299,7 @@ dialog div.dialog-actions {
|
|||
#editcredits .credit .delete {
|
||||
margin-right: .5em;
|
||||
cursor: pointer;
|
||||
overflow: visible;
|
||||
}
|
||||
#editcredits .credit .delete:hover {
|
||||
text-decoration: underline;
|
||||
|
|
@ -315,14 +316,17 @@ dialog div.dialog-actions {
|
|||
display: flex;
|
||||
gap: .5em;
|
||||
cursor: pointer;
|
||||
background-color: var(--bg-2);
|
||||
}
|
||||
|
||||
#addcredit ul li.new-artist:nth-child(even) {
|
||||
background: #f0f0f0;
|
||||
background-color: var(--bg-1);
|
||||
}
|
||||
|
||||
#addcredit ul li.new-artist:hover {
|
||||
background: #e0e0e0;
|
||||
background-color: var(--bg-2);
|
||||
}
|
||||
|
||||
#addcredit .new-artist .artist-id {
|
||||
|
|
@ -375,6 +379,8 @@ dialog div.dialog-actions {
|
|||
|
||||
#editlinks tr {
|
||||
display: flex;
|
||||
background-color: var(--bg-1);
|
||||
transition: background-color .1s ease-out;
|
||||
}
|
||||
|
||||
#editlinks th {
|
||||
|
|
@ -385,7 +391,7 @@ dialog div.dialog-actions {
|
|||
}
|
||||
|
||||
#editlinks tr:nth-child(odd) {
|
||||
background: #f8f8f8;
|
||||
background-color: var(--bg-2);
|
||||
}
|
||||
|
||||
#editlinks tr th,
|
||||
|
|
@ -416,6 +422,11 @@ dialog div.dialog-actions {
|
|||
width: 1em;
|
||||
pointer-events: none;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#editlinks tr .grabber img {
|
||||
filter: invert();
|
||||
}
|
||||
}
|
||||
#editlinks tr .link-name {
|
||||
width: 8em;
|
||||
}
|
||||
|
|
@ -454,6 +465,7 @@ dialog div.dialog-actions {
|
|||
}
|
||||
|
||||
#edittracks .track {
|
||||
background-color: var(--bg-2);
|
||||
transition: transform .2s ease-out, opacity .2s;
|
||||
}
|
||||
|
||||
|
|
@ -476,7 +488,7 @@ dialog div.dialog-actions {
|
|||
}
|
||||
|
||||
#edittracks .track:nth-child(even) {
|
||||
background: #f0f0f0;
|
||||
background-color: var(--bg-1);
|
||||
}
|
||||
|
||||
#edittracks .track-number {
|
||||
|
|
@ -492,7 +504,6 @@ dialog div.dialog-actions {
|
|||
#addtrack ul {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
#addtrack ul li.new-track {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
gap: 1.2em;
|
||||
|
||||
border-radius: 16px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
|
|
@ -45,25 +45,13 @@
|
|||
font-weight: inherit;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
background: var(--bg-0);
|
||||
background-color: var(--bg-0);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.track-info input[type="text"]:hover,
|
||||
.track-info textarea:hover {
|
||||
border-color: #80808080;
|
||||
}
|
||||
|
||||
.track-info input[type="text"]:active,
|
||||
.track-info textarea:active,
|
||||
.track-info input[type="text"]:focus,
|
||||
.track-info textarea:focus {
|
||||
border-color: #808080;
|
||||
}
|
||||
|
||||
.track-actions {
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
const newReleaseBtn = document.getElementById("create-release");
|
||||
const newArtistBtn = document.getElementById("create-artist");
|
||||
const newTrackBtn = document.getElementById("create-track");
|
||||
|
||||
newReleaseBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
const id = prompt("Enter an ID for this release:");
|
||||
if (id == null || id == "") return;
|
||||
|
||||
fetch("/api/v1/music", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({id})
|
||||
}).then(res => {
|
||||
if (res.ok) location = "/admin/releases/" + id;
|
||||
else {
|
||||
res.text().then(err => {
|
||||
alert("Request failed: " + err);
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
alert("Failed to create release. Check the console for details.");
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
newArtistBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
const id = prompt("Enter an ID for this artist:");
|
||||
if (id == null || id == "") return;
|
||||
|
||||
fetch("/api/v1/artist", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({id})
|
||||
}).then(res => {
|
||||
res.text().then(text => {
|
||||
if (res.ok) {
|
||||
location = "/admin/artists/" + id;
|
||||
} else {
|
||||
alert("Request failed: " + text);
|
||||
console.error(text);
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
alert("Failed to create artist. Check the console for details.");
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
newTrackBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
const title = prompt("Enter an title for this track:");
|
||||
if (title == null || title == "") return;
|
||||
|
||||
fetch("/api/v1/track", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({title})
|
||||
}).then(res => {
|
||||
res.text().then(text => {
|
||||
if (res.ok) {
|
||||
location = "/admin/tracks/" + text;
|
||||
} else {
|
||||
alert("Request failed: " + text);
|
||||
console.error(text);
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
alert("Failed to create track. Check the console for details.");
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
|
@ -8,7 +8,7 @@ form#search-form {
|
|||
padding: 1em;
|
||||
border-radius: 16px;
|
||||
color: var(--fg-0);
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ div#search {
|
|||
border: none;
|
||||
border-radius: 16px;
|
||||
color: var(--fg-1);
|
||||
background: var(--bg-0);
|
||||
background-color: var(--bg-0);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
|
|
@ -100,8 +100,8 @@ td.log-content {
|
|||
|
||||
#logs .log.warn {
|
||||
color: var(--col-on-warn);
|
||||
background: var(--col-warn);
|
||||
background-color: var(--col-warn);
|
||||
}
|
||||
#logs .log.warn:hover {
|
||||
background: var(--col-warn-hover);
|
||||
background-color: var(--col-warn-hover);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
gap: 1em;
|
||||
|
||||
border-radius: 16px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
transition: background .1s ease-out, color .1s ease-out;
|
||||
|
|
@ -67,14 +67,14 @@
|
|||
display: inline-block;
|
||||
|
||||
border-radius: 4px;
|
||||
background: var(--bg-3);
|
||||
background-color: var(--bg-3);
|
||||
box-shadow: var(--shadow-sm);
|
||||
|
||||
transition: color .1s ease-out, background .1s ease-out;
|
||||
}
|
||||
|
||||
.release .release-actions a:hover {
|
||||
background: var(--bg-0);
|
||||
background-color: var(--bg-0);
|
||||
color: var(--fg-3);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
|
|||
25
admin/static/releases.js
Normal file
25
admin/static/releases.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
document.addEventListener('readystatechange', () => {
|
||||
const newReleaseBtn = document.getElementById("create-release");
|
||||
if (newReleaseBtn) newReleaseBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
const id = prompt("Enter an ID for this release:");
|
||||
if (id == null || id == "") return;
|
||||
|
||||
fetch("/api/v1/music", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({id})
|
||||
}).then(res => {
|
||||
if (res.ok) location = "/admin/releases/" + id;
|
||||
else {
|
||||
res.text().then(err => {
|
||||
alert(err);
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
alert("Failed to create release. Check the console for details.");
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
gap: .5em;
|
||||
|
||||
border-radius: 16px;
|
||||
background: var(--bg-2);
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
transition: background .1s ease-out, color .1s ease-out;
|
||||
|
|
@ -44,11 +44,6 @@
|
|||
opacity: .5;
|
||||
}
|
||||
|
||||
#tracks .track-album.empty {
|
||||
color: #ff2020;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#tracks .track-description {
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
@ -67,61 +62,4 @@
|
|||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
/*
|
||||
justify-content: space-between;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
.track {
|
||||
margin-bottom: 1em;
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5em;
|
||||
|
||||
border-radius: 8px;
|
||||
background-color: var(--bg-2);
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
transition: color .1s ease-out, background-color .1s ease-out;
|
||||
}
|
||||
|
||||
.track p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.track-id {
|
||||
width: fit-content;
|
||||
font-family: "Monaspace Argon", monospace;
|
||||
font-size: .8em;
|
||||
font-style: italic;
|
||||
line-height: 1em;
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
.track-album {
|
||||
margin-left: auto;
|
||||
font-style: italic;
|
||||
font-size: .75em;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.track-album.empty {
|
||||
color: #ff2020;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.track-description {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.track-lyrics {
|
||||
max-height: 10em;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.track .empty {
|
||||
opacity: 0.75;
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
24
admin/static/tracks.js
Normal file
24
admin/static/tracks.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
const newTrackBtn = document.getElementById("create-track");
|
||||
if (newTrackBtn) newTrackBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
const title = prompt("Enter an title for this track:");
|
||||
if (title == null || title == "") return;
|
||||
|
||||
fetch("/api/v1/track", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({title})
|
||||
}).then(res => {
|
||||
res.text().then(text => {
|
||||
if (res.ok) {
|
||||
location = "/admin/tracks/" + text;
|
||||
} else {
|
||||
alert(text);
|
||||
console.error(text);
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
alert("Failed to create track. Check the console for details.");
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
|
@ -49,7 +49,6 @@
|
|||
|
||||
deleteBtn.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
if (!confirm("Are you sure you want to remove " + trackTitle + "?")) return;
|
||||
trackItem.remove();
|
||||
refreshTrackNumbers();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" id="credits">
|
||||
<div id="credits" class="card">
|
||||
<div class="card-header">
|
||||
<h2>Credits <small>({{len .Release.Credits}} total)</small></h2>
|
||||
<a class="button edit"
|
||||
|
|
@ -110,6 +110,7 @@
|
|||
hx-swap="beforeend"
|
||||
>Edit</a>
|
||||
</div>
|
||||
|
||||
{{range .Release.Credits}}
|
||||
<div class="credit">
|
||||
<img src="{{.Artist.GetAvatar}}" alt="" width="64" loading="lazy" class="artist-avatar">
|
||||
|
|
@ -125,13 +126,13 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{if not .Release.Credits}}
|
||||
<p>There are no credits.</p>
|
||||
<p>This release has no credits.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="card" id="links">
|
||||
<div id="links" class="card">
|
||||
<div class="card-header">
|
||||
<h2>Links ({{len .Release.Links}})</h2>
|
||||
<h2>Links <small>({{len .Release.Links}} total)</small></h2>
|
||||
<a class="button edit"
|
||||
href="/admin/releases/{{.Release.ID}}/editlinks"
|
||||
hx-get="/admin/releases/{{.Release.ID}}/editlinks"
|
||||
|
|
@ -139,16 +140,21 @@
|
|||
hx-swap="beforeend"
|
||||
>Edit</a>
|
||||
</div>
|
||||
|
||||
{{if .Release.Links}}
|
||||
<ul>
|
||||
{{range .Release.Links}}
|
||||
<a href="{{.URL}}" target="_blank" class="button" data-name="{{.Name}}">{{.Name}} <img class="icon" src="/img/external-link.svg"/></a>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>This release has no links.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="card" id="tracks">
|
||||
<div class="card-header" id="tracks">
|
||||
<h2>Tracklist ({{len .Release.Tracks}})</h2>
|
||||
<div id="tracks" class="card">
|
||||
<div class="card-header">
|
||||
<h2>Tracks <small>({{len .Release.Tracks}} total)</small></h2>
|
||||
<a class="button edit"
|
||||
href="/admin/releases/{{.Release.ID}}/edittracks"
|
||||
hx-get="/admin/releases/{{.Release.ID}}/edittracks"
|
||||
|
|
@ -156,9 +162,13 @@
|
|||
hx-swap="beforeend"
|
||||
>Edit</a>
|
||||
</div>
|
||||
|
||||
{{range $i, $track := .Release.Tracks}}
|
||||
{{block "track" .}}{{end}}
|
||||
{{end}}
|
||||
{{if not .Release.Tracks}}
|
||||
<p>This release has no tracks.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="card" id="danger">
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
|
||||
</main>
|
||||
|
||||
<script type="module" src="/admin/static/releases.js"></script>
|
||||
<script type="module" src="/admin/static/artists.js"></script>
|
||||
<script type="module" src="/admin/static/index.js"></script>
|
||||
<script type="module" src="/admin/static/tracks.js"></script>
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,6 @@
|
|||
<p>There are no releases.</p>
|
||||
{{end}}
|
||||
</main>
|
||||
|
||||
<script type="module" src="/admin/static/releases.js"></script>
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -12,22 +12,8 @@
|
|||
</header>
|
||||
|
||||
<div id="tracks">
|
||||
{{range $Track := .Tracks}}
|
||||
<div class="track">
|
||||
<h2 class="track-title">
|
||||
<a href="/admin/tracks/{{$Track.ID}}">{{$Track.Title}}</a>
|
||||
</h2>
|
||||
{{if $Track.Description}}
|
||||
<p class="track-description">{{$Track.GetDescriptionHTML}}</p>
|
||||
{{else}}
|
||||
<p class="track-description empty">No description provided.</p>
|
||||
{{end}}
|
||||
{{if $Track.Lyrics}}
|
||||
<p class="track-lyrics">{{$Track.GetLyricsHTML}}</p>
|
||||
{{else}}
|
||||
<p class="track-lyrics empty">There are no lyrics.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
{{range .Tracks}}
|
||||
{{block "track" .}}{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue