home to your local SPACEGIRL 💫 arimelody.space
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

admin dashboard: mobile support!

+201 -56
+2 -8
admin/releasehttp.go
··· 193 193 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 194 194 w.Header().Set("Content-Type", "text/html") 195 195 196 - type editTracksData struct { 197 - Release *model.Release 198 - Add func(a int, b int) int 199 - } 196 + type editTracksData struct { Release *model.Release } 200 197 201 - err := templates.EditTracksTemplate.Execute(w, editTracksData{ 202 - Release: release, 203 - Add: func(a, b int) int { return a + b }, 204 - }) 198 + err := templates.EditTracksTemplate.Execute(w, editTracksData{ Release: release }) 205 199 if err != nil { 206 200 fmt.Printf("WARN: Failed to serve edit tracks component for %s: %s\n", release.ID, err) 207 201 http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
+91 -12
admin/static/admin.css
··· 193 193 border-bottom: 1px solid var(--fg-0); 194 194 } 195 195 nav .section-label { 196 - margin: 8px 0 2px 15px; 197 - font-size: 10px; 196 + margin: .6em 0 .1em 1.6em; 197 + font-size: .6em; 198 198 text-transform: uppercase; 199 199 font-weight: 600; 200 200 } 201 + #toggle-nav { 202 + position: fixed; 203 + top: 16px; 204 + left: 16px; 205 + padding: 8px; 206 + width: 48px; 207 + height: 48px; 208 + display: none; 209 + justify-content: center; 210 + align-items: center; 211 + z-index: 1; 212 + } 213 + #toggle-nav img { 214 + width: 100%; 215 + height: 100%; 216 + object-fit: cover; 217 + transform: translate(1px, 1px); 218 + } 219 + #toggle-nav img:hover { 220 + filter: invert(.9); 221 + } 222 + @media (prefers-color-scheme: dark) { 223 + #toggle-nav img { 224 + filter: invert(.9); 225 + } 226 + #toggle-nav img:hover { 227 + filter: none; 228 + } 229 + } 201 230 202 231 main { 203 - width: min(calc(100% - 16px), 720px); 232 + width: 720px; 233 + max-width: calc(100% - 2em); 204 234 height: fit-content; 205 235 min-height: calc(100vh - 2em); 206 236 margin: 0 auto; ··· 213 243 a { 214 244 color: inherit; 215 245 text-decoration: none; 246 + overflow: hidden; 247 + text-overflow: ellipsis; 248 + white-space: nowrap; 216 249 transition: color .1s ease-out, background-color .1s ease-out; 217 250 } 218 251 ··· 296 329 gap: 1em; 297 330 } 298 331 299 - @media screen and (max-width: 520px) { 300 - body { 301 - font-size: 12px; 302 - } 303 - } 304 - 305 332 306 333 307 334 #message, ··· 387 414 margin: 1rem 0 .5rem 0; 388 415 display: block; 389 416 } 390 - form input { 391 - min-width: 20rem; 392 - max-width: calc(100% - 1em)); 417 + form input[type="text"], 418 + form input[type="password"] { 419 + width: 16em; 420 + max-width: 100%; 393 421 margin: .5em 0; 394 422 padding: .3em .5em; 395 423 display: block; ··· 404 432 opacity: .5; 405 433 cursor: not-allowed; 406 434 } 435 + 436 + @media screen and (max-width: 720px) { 437 + main { 438 + padding-top: 0; 439 + } 440 + 441 + body { 442 + width: 100%; 443 + margin: 0; 444 + font-size: 16px; 445 + } 446 + 447 + nav { 448 + width: 100%; 449 + left: -100%; 450 + font-size: 24px; 451 + z-index: 1; 452 + transition: transform .2s cubic-bezier(.2,0,.5,1); 453 + } 454 + nav.open { 455 + transform: translateX(100%); 456 + } 457 + 458 + #toggle-nav { 459 + display: flex; 460 + } 461 + 462 + main > h1:first-of-type { 463 + margin-left: 68px; 464 + overflow: hidden; 465 + white-space: nowrap; 466 + text-overflow: ellipsis; 467 + } 468 + main > header { 469 + margin-left: 68px; 470 + } 471 + main > header h1 { 472 + display: flex; 473 + flex-direction: column; 474 + font-size: 1.5em; 475 + } 476 + 477 + .card { 478 + flex-basis: 100%; 479 + max-width: calc(100vw - 4em); 480 + } 481 + 482 + .artists-group { 483 + grid-template-columns: repeat(3, 1fr); 484 + } 485 + }
+8
admin/static/admin.js
··· 86 86 })); 87 87 }); 88 88 } 89 + 90 + document.addEventListener("readystatechange", () => { 91 + const navbar = document.getElementById("navbar"); 92 + document.getElementById("toggle-nav").addEventListener("click", event => { 93 + event.preventDefault(); 94 + navbar.classList.toggle("open"); 95 + }) 96 + });
+4
admin/static/artists.css
··· 21 21 object-fit: cover; 22 22 border-radius: 8px; 23 23 } 24 + 25 + .artist .artist-name { 26 + display: block; 27 + }
+11 -2
admin/static/edit-account.css
··· 13 13 } 14 14 form#change-password input, 15 15 form#delete-account input { 16 - width: min(20rem, calc(100% - 1rem)); 16 + width: 20em; 17 + min-width: auto; 18 + max-width: calc(100% - 1em - 2px); 17 19 margin: .5rem 0; 18 20 padding: .3rem .5rem; 19 21 display: block; ··· 51 53 } 52 54 53 55 .mfa-device form input { 54 - display: none; 56 + display: none !important; 57 + } 58 + 59 + .mfa-actions { 60 + display: flex; 61 + flex-direction: row; 62 + gap: .5em; 63 + flex-wrap: wrap; 55 64 }
+6
admin/static/edit-artist.css
··· 101 101 border-radius: 4px; 102 102 } 103 103 104 + .credit-info { 105 + overflow: hidden; 106 + } 104 107 .credit-info h3, 105 108 .credit-info p { 106 109 margin: 0; 107 110 font-size: .9em; 111 + white-space: nowrap; 112 + overflow: hidden; 113 + text-overflow: ellipsis; 108 114 }
+16 -2
admin/static/edit-release.css
··· 207 207 opacity: .66; 208 208 } 209 209 210 + #credits .credit .credit-info { 211 + overflow: hidden; 212 + } 213 + 214 + #credits .credit .credit-info :is(h3, p) { 215 + white-space: nowrap; 216 + overflow: hidden; 217 + text-overflow: ellipsis; 218 + } 219 + 220 + 221 + 210 222 #editcredits ul { 211 223 margin: 0; 212 224 padding: 0; ··· 487 499 padding: .5em; 488 500 display: flex; 489 501 gap: .5em; 502 + background-color: var(--bg-0); 490 503 cursor: pointer; 504 + transition: background-color .1s ease-out, color .1s ease-out; 491 505 } 492 506 493 507 #addtrack ul li.new-track:nth-child(even) { 494 - background: #f0f0f0; 508 + background: color-mix(in srgb, var(--bg-0) 95%, #fff); 495 509 } 496 510 497 511 #addtrack ul li.new-track:hover { 498 - background: #e0e0e0; 512 + background: color-mix(in srgb, var(--bg-0) 90%, #fff); 499 513 } 500 514 501 515 @media only screen and (max-width: 1105px) {
+9
admin/static/logs.css
··· 46 46 47 47 #logs { 48 48 width: 100%; 49 + overflow: scroll; 50 + } 51 + @media screen and (max-width: 720px) { 52 + #logs { 53 + font-size: 12px; 54 + } 55 + } 56 + 57 + #logs table{ 49 58 border-collapse: collapse; 50 59 } 51 60
+7
admin/static/releases.css
··· 15 15 .release h3, 16 16 .release p { 17 17 margin: 0; 18 + overflow: hidden; 19 + white-space: nowrap; 20 + text-overflow: ellipsis; 18 21 } 19 22 20 23 .release .release-artwork { ··· 32 35 .release .release-artwork img { 33 36 width: 100%; 34 37 aspect-ratio: 1; 38 + } 39 + 40 + .release .release-info { 41 + max-width: calc(100% - 96px - 1em); 35 42 } 36 43 37 44 .release .release-title small {
-1
admin/templates/html/artists.html
··· 22 22 {{end}} 23 23 </main> 24 24 25 - <script type="module" src="/admin/static/admin.js"></script> 26 25 <script type="module" src="/admin/static/artists.js"></script> 27 26 {{end}}
+1 -1
admin/templates/html/edit-account.html
··· 57 57 <p>You have no MFA devices.</p> 58 58 {{end}} 59 59 60 - <div> 60 + <div class="mfa-actions"> 61 61 <button type="submit" class="save" id="enable-email" disabled>Enable Email TOTP</button> 62 62 <a class="button new" id="add-totp-device" href="/admin/account/totp-setup">Add TOTP Device</a> 63 63 </div>
-1
admin/templates/html/index.html
··· 56 56 57 57 </main> 58 58 59 - <script type="module" src="/admin/static/admin.js"></script> 60 59 <script type="module" src="/admin/static/artists.js"></script> 61 60 <script type="module" src="/admin/static/index.js"></script> 62 61 {{end}}
+5 -1
admin/templates/html/layout.html
··· 10 10 {{block "head" .}}{{end}} 11 11 12 12 <link rel="stylesheet" href="/admin/static/admin.css"> 13 + <script type="module" src="/admin/static/admin.js"></script> 13 14 <script type="module" src="/script/vendor/htmx.min.js"></script> 14 15 </head> 15 16 16 17 <body> 17 18 <header> 18 - <nav> 19 + <nav id="navbar"> 19 20 <a href="/" class="nav icon" aria-label="ari melody" title="Return to Home"> 20 21 <img src="/img/favicon.png" alt="" width="64" height="64"> 21 22 </a> ··· 57 58 </div> 58 59 {{end}} 59 60 </nav> 61 + <button type="button" id="toggle-nav" aria-label="Navigation toggle"> 62 + <img src="/img/hamburger.svg" alt=""> 63 + </button> 60 64 </header> 61 65 62 66 {{block "content" .}}{{end}}
+9 -2
admin/templates/html/login-totp.html
··· 17 17 margin-top: 1rem; 18 18 } 19 19 20 - input { 21 - width: calc(100% - 1rem - 2px); 20 + form input { 21 + width: calc(100% - 1rem - 2px) !important; 22 + } 23 + 24 + @media screen and (max-width: 720px) { 25 + h1 { 26 + margin-top: 3em; 27 + text-align: center; 28 + } 22 29 } 23 30 </style> 24 31 {{end}}
+9 -2
admin/templates/html/login.html
··· 2 2 <title>Login - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 4 <style> 5 + @media screen and (max-width: 720px) { 6 + h1 { 7 + margin-top: 3em; 8 + text-align: center; 9 + } 10 + } 11 + 5 12 form#login { 6 13 width: 100%; 7 14 display: flex; ··· 17 24 margin-top: 1rem; 18 25 } 19 26 20 - input { 21 - width: calc(100% - 1rem - 2px); 27 + form input { 28 + width: calc(100% - 1rem - 2px) !important; 22 29 } 23 30 </style> 24 31 {{end}}
+22 -20
admin/templates/html/logs.html
··· 43 43 44 44 <hr> 45 45 46 - <table id="logs"> 47 - <thead> 48 - <tr> 49 - <th class="log-time">Time</th> 50 - <th class="log-level">Level</th> 51 - <th class="log-type">Type</th> 52 - <th class="log-content">Message</th> 53 - </tr> 54 - </thead> 55 - <tbody> 56 - {{range .Logs}} 57 - <tr class="log {{toLower (parseLevel .Level)}}"> 58 - <td class="log-time">{{prettyTime .CreatedAt}}</td> 59 - <td class="log-level">{{parseLevel .Level}}</td> 60 - <td class="log-type">{{titleCase .Type}}</td> 61 - <td class="log-content">{{.Content}}</td> 62 - </tr> 63 - {{end}} 64 - </tbody> 65 - </table> 46 + <div id="logs"> 47 + <table> 48 + <thead> 49 + <tr> 50 + <th class="log-time">Time</th> 51 + <th class="log-level">Level</th> 52 + <th class="log-type">Type</th> 53 + <th class="log-content">Message</th> 54 + </tr> 55 + </thead> 56 + <tbody> 57 + {{range .Logs}} 58 + <tr class="log {{toLower (parseLevel .Level)}}"> 59 + <td class="log-time">{{prettyTime .CreatedAt}}</td> 60 + <td class="log-level">{{parseLevel .Level}}</td> 61 + <td class="log-type">{{titleCase .Type}}</td> 62 + <td class="log-content">{{.Content}}</td> 63 + </tr> 64 + {{end}} 65 + </tbody> 66 + </table> 67 + </div> 66 68 </main> 67 69 {{end}}
-2
admin/templates/html/releases.html
··· 21 21 <p>There are no releases.</p> 22 22 {{end}} 23 23 </main> 24 - 25 - <script type="module" src="/admin/static/admin.js"></script> 26 24 {{end}}
-2
admin/templates/html/tracks.html
··· 31 31 {{end}} 32 32 </div> 33 33 </main> 34 - 35 - <script type="module" src="/admin/static/admin.js"></script> 36 34 {{end}}
+1
public/img/hamburger.svg
··· 1 + <?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="15.36" height="15.36" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><path d="M13.44,7.68c0,0.53 -0.43,0.96 -0.96,0.96l-9.6,0c-0.53,0 -0.96,-0.43 -0.96,-0.96c-0,-0.53 0.43,-0.96 0.96,-0.96l9.6,-0c0.53,-0 0.96,0.43 0.96,0.96Z"/><path d="M13.44,11.52c0,0.53 -0.43,0.96 -0.96,0.96l-9.6,0c-0.53,0 -0.96,-0.43 -0.96,-0.96c-0,-0.53 0.43,-0.96 0.96,-0.96l9.6,0c0.53,0 0.96,0.43 0.96,0.96Z"/><path d="M13.44,3.84c0,0.53 -0.43,0.96 -0.96,0.96l-9.6,0c-0.53,0 -0.96,-0.43 -0.96,-0.96c-0,-0.53 0.43,-0.96 0.96,-0.96l9.6,0c0.53,0 0.96,0.43 0.96,0.96Z"/></g></svg>