diff --git a/admin/account/accounthttp.go b/admin/account/accounthttp.go index 4595cd4..a826a1b 100644 --- a/admin/account/accounthttp.go +++ b/admin/account/accounthttp.go @@ -20,14 +20,14 @@ func Handler(app *model.AppState) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mux := http.NewServeMux() - mux.Handle("/account/", accountIndexHandler(app)) + mux.Handle("/", accountIndexHandler(app)) - mux.Handle("/account/totp-setup", totpSetupHandler(app)) - mux.Handle("/account/totp-confirm", totpConfirmHandler(app)) - mux.Handle("/account/totp-delete", totpDeleteHandler(app)) + mux.Handle("/totp-setup", totpSetupHandler(app)) + mux.Handle("/totp-confirm", totpConfirmHandler(app)) + mux.Handle("/totp-delete", totpDeleteHandler(app)) - mux.Handle("/account/password", changePasswordHandler(app)) - mux.Handle("/account/delete", deleteAccountHandler(app)) + mux.Handle("/password", changePasswordHandler(app)) + mux.Handle("/delete", deleteAccountHandler(app)) mux.ServeHTTP(w, r) }) diff --git a/admin/blog/blog.go b/admin/blog/blog.go index d1a2922..d03907a 100644 --- a/admin/blog/blog.go +++ b/admin/blog/blog.go @@ -15,8 +15,8 @@ func Handler(app *model.AppState) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mux := http.NewServeMux() - mux.Handle("/blogs/{id}", serveBlogPost(app)) - mux.Handle("/blogs/", serveBlogIndex(app)) + mux.Handle("/{id}", serveBlogPost(app)) + mux.Handle("/", serveBlogIndex(app)) mux.ServeHTTP(w, r) }) diff --git a/admin/http.go b/admin/http.go index e913558..33f017b 100644 --- a/admin/http.go +++ b/admin/http.go @@ -26,10 +26,10 @@ func Handler(app *model.AppState) http.Handler { mux.Handle("/logout", core.RequireAccount(auth.LogoutHandler(app))) mux.Handle("/logs", core.RequireAccount(logs.Handler(app))) - mux.Handle("/music/", core.RequireAccount(music.Handler(app))) - mux.Handle("/blogs/", core.RequireAccount(blog.Handler(app))) + mux.Handle("/music/", core.RequireAccount(http.StripPrefix("/music", music.Handler(app)))) + mux.Handle("/blogs/", core.RequireAccount(http.StripPrefix("/blogs", blog.Handler(app)))) - mux.Handle("/account/", core.RequireAccount(account.Handler(app))) + mux.Handle("/account/", core.RequireAccount(http.StripPrefix("/account", account.Handler(app)))) mux.Handle("/static/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/static/admin.css" { diff --git a/admin/music/musichttp.go b/admin/music/musichttp.go index 562d83f..607026e 100644 --- a/admin/music/musichttp.go +++ b/admin/music/musichttp.go @@ -9,23 +9,17 @@ func Handler(app *model.AppState) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mux := http.NewServeMux() - mux.HandleFunc("/music/releases/{id}/", func(w http.ResponseWriter, r *http.Request) { - serveEditRelease(app, r.PathValue("id")).ServeHTTP(w, r) - }) - mux.HandleFunc("/music/releases/{id}", func(w http.ResponseWriter, r *http.Request) { - serveRelease(app, r.PathValue("id")).ServeHTTP(w, r) - }) - mux.Handle("/music/releases/", serveReleases(app)) + mux.Handle("/releases/", http.StripPrefix("/releases", serveReleases(app))) - mux.HandleFunc("/music/artists/{id}", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/artists/{id}", func(w http.ResponseWriter, r *http.Request) { serveArtist(app, r.PathValue("id")).ServeHTTP(w, r) }) - mux.Handle("/music/artists/", serveArtists(app)) + mux.Handle("/artists/", http.StripPrefix("/artists", serveArtists(app))) - mux.HandleFunc("/music/tracks/{id}", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/tracks/{id}", func(w http.ResponseWriter, r *http.Request) { serveTrack(app, r.PathValue("id")).ServeHTTP(w, r) }) - mux.Handle("/music/tracks/", serveTracks(app)) + mux.Handle("/tracks/", http.StripPrefix("/tracks", serveTracks(app))) mux.ServeHTTP(w, r) }) diff --git a/admin/music/releasehttp.go b/admin/music/releasehttp.go index 741da76..bc41602 100644 --- a/admin/music/releasehttp.go +++ b/admin/music/releasehttp.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "os" + "strings" "arimelody-web/admin/core" "arimelody-web/admin/templates" @@ -12,7 +13,41 @@ import ( ) func serveReleases(app *model.AppState) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + mux := http.NewServeMux() + + mux.HandleFunc("/{id}/", func(w http.ResponseWriter, r *http.Request) { + releaseID := r.PathValue("id") + release, err := controller.GetRelease(app.DB, releaseID, true) + if err != nil { + if strings.Contains(err.Error(), "no rows") { + http.NotFound(w, r) + return + } + fmt.Fprintf(os.Stderr, "WARN: Failed to fetch full release data for %s: %s\n", releaseID, err) + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + mux := http.NewServeMux() + + mux.Handle("/{id}/editcredits", serveEditCredits(release)) + mux.Handle("/{id}/addcredit", serveAddCredit(app, release)) + mux.Handle("/{id}/newcredit", serveNewCredit(app)) + + mux.Handle("/{id}/editlinks", serveEditLinks(release)) + + mux.Handle("/{id}/edittracks", serveEditTracks(release)) + mux.Handle("/{id}/addtrack", serveAddTrack(app, release)) + mux.Handle("/{id}/newtrack", serveNewTrack(app)) + + mux.ServeHTTP(w, r) + }) + + mux.HandleFunc("/{id}", func(w http.ResponseWriter, r *http.Request) { + serveRelease(app, r.PathValue("id")).ServeHTTP(w, r) + }) + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { session := r.Context().Value("session").(*model.Session) type ReleasesData struct { @@ -40,22 +75,24 @@ func serveReleases(app *model.AppState) http.Handler { return } }) + + return mux } func serveRelease(app *model.AppState, releaseID string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + session := r.Context().Value("session").(*model.Session) + release, err := controller.GetRelease(app.DB, releaseID, true) if err != nil { + if strings.Contains(err.Error(), "no rows") { + http.NotFound(w, r) + return + } fmt.Fprintf(os.Stderr, "WARN: Failed to fetch full release data for %s: %s\n", releaseID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } - if release == nil { - http.NotFound(w, r) - return - } - - session := r.Context().Value("session").(*model.Session) type ReleaseResponse struct { core.AdminPageData @@ -75,35 +112,6 @@ func serveRelease(app *model.AppState, releaseID string) http.Handler { }) } -func serveEditRelease(app *model.AppState, releaseID string) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - release, err := controller.GetRelease(app.DB, releaseID, true) - if err != nil { - fmt.Fprintf(os.Stderr, "WARN: Failed to fetch full release data for %s: %s\n", releaseID, err) - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - return - } - if release == nil { - http.NotFound(w, r) - return - } - - mux := http.NewServeMux() - - mux.Handle("GET /music/releases/{id}/editcredits", serveEditCredits(release)) - mux.Handle("GET /music/releases/{id}/addcredit", serveAddCredit(app, release)) - mux.Handle("GET /music/releases/{id}/newcredit/{artistID}", serveNewCredit(app)) - - mux.Handle("GET /music/releases/{id}/editlinks", serveEditLinks(release)) - - mux.Handle("GET /music/releases/{id}/edittracks", serveEditTracks(release)) - mux.Handle("GET /music/releases/{id}/addtrack", serveAddTrack(app, release)) - mux.Handle("GET /music/releases/{id}/newtrack/{trackID}", serveNewTrack(app)) - - mux.ServeHTTP(w, r) - }) -} - func serveEditCredits(release *model.Release) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") @@ -143,7 +151,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 := r.PathValue("artistID") + split := strings.Split(r.URL.Path, "/") + artistID := split[len(split) - 1] artist, err := controller.GetArtist(app.DB, artistID) if err != nil { fmt.Fprintf(os.Stderr, "WARN: Failed to fetch artist %s: %s\n", artistID, err) @@ -219,7 +228,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 := r.PathValue("trackID") + split := strings.Split(r.URL.Path, "/") + trackID := split[len(split) - 1] track, err := controller.GetTrack(app.DB, trackID) if err != nil { fmt.Fprintf(os.Stderr, "WARN: Failed to fetch track %s: %s\n", trackID, err) diff --git a/admin/static/edit-blog.css b/admin/static/edit-blog.css index 77cfc48..5e86b4b 100644 --- a/admin/static/edit-blog.css +++ b/admin/static/edit-blog.css @@ -32,11 +32,6 @@ input[type="text"] { margin-top: 0; } -#blogpost button#set-current-date { - margin: 0 .5em; - padding: .4em .8em; -} - #blogpost h2 { margin: 0; font-size: 2em; diff --git a/admin/static/edit-blog.js b/admin/static/edit-blog.js index 2c5911f..9047ee9 100644 --- a/admin/static/edit-blog.js +++ b/admin/static/edit-blog.js @@ -1,7 +1,6 @@ const blogID = document.getElementById("blogpost").dataset.id; const titleInput = document.getElementById("title"); const publishDateInput = document.getElementById("publish-date"); -const setCurrentDateBtn = document.getElementById("set-current-date"); const descInput = document.getElementById("description"); const mdInput = document.getElementById("markdown"); const blueskyActorInput = document.getElementById("bluesky-actor"); @@ -12,13 +11,6 @@ const visInput = document.getElementById("visibility"); const saveBtn = document.getElementById("save"); const deleteBtn = document.getElementById("delete"); -setCurrentDateBtn.addEventListener("click", () => { - let now = new Date; - now.setMinutes(now.getMinutes() - now.getTimezoneOffset()); - publishDateInput.value = now.toISOString().slice(0, 16); - saveBtn.disabled = false; -}); - saveBtn.addEventListener("click", () => { fetch("/api/v1/blog/" + blogID, { method: "PUT", diff --git a/admin/static/edit-release.css b/admin/static/edit-release.css index 850c1d7..8186f2c 100644 --- a/admin/static/edit-release.css +++ b/admin/static/edit-release.css @@ -465,7 +465,7 @@ dialog div.dialog-actions { } #edittracks .track { - background-color: var(--bg-1); + background-color: var(--bg-2); transition: transform .2s ease-out, opacity .2s; } @@ -488,7 +488,7 @@ dialog div.dialog-actions { } #edittracks .track:nth-child(even) { - background-color: var(--bg-0); + background-color: var(--bg-1); } #edittracks .track-number { @@ -510,17 +510,17 @@ dialog div.dialog-actions { padding: .5em; display: flex; gap: .5em; - background-color: var(--bg-1); + background-color: var(--bg-0); cursor: pointer; transition: background-color .1s ease-out, color .1s ease-out; } #addtrack ul li.new-track:nth-child(even) { - background-color: var(--bg-0); + background: color-mix(in srgb, var(--bg-0) 95%, #fff); } #addtrack ul li.new-track:hover { - background-color: var(--bg-2); + background: color-mix(in srgb, var(--bg-0) 90%, #fff); } @media only screen and (max-width: 1105px) { diff --git a/admin/templates/html/edit-blog.html b/admin/templates/html/edit-blog.html index 4176e85..eba577d 100644 --- a/admin/templates/html/edit-blog.html +++ b/admin/templates/html/edit-blog.html @@ -28,7 +28,6 @@ -