diff --git a/.air.toml b/.air.toml index 62548ed..a87ab82 100644 --- a/.air.toml +++ b/.air.toml @@ -14,7 +14,7 @@ exclude_unchanged = false follow_symlink = false full_bin = "" include_dir = [] -include_ext = ["go", "tpl", "tmpl", "html", "gohtml"] +include_ext = ["go", "tpl", "tmpl", "html", "gohtml", "css", "js"] include_file = [] kill_delay = "0s" log = "build-errors.log" @@ -48,5 +48,5 @@ enabled = false proxy_port = 0 [screen] -clear_on_rebuild = false +clear_on_rebuild = true keep_scroll = true diff --git a/cmd/handlers.go b/cmd/handlers.go index d07d0b5..12175b5 100644 --- a/cmd/handlers.go +++ b/cmd/handlers.go @@ -50,9 +50,9 @@ func home(database *db.DB, pg *pages.Pages) http.HandlerFunc { } } -func handleLinkLastfmForm(database *db.DB) http.HandlerFunc { +func handleLinkLastfmForm(database *db.DB, pg *pages.Pages) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - userID, _ := session.GetUserID(r.Context()) + userID, authenticated := session.GetUserID(r.Context()) if r.Method == http.MethodPost { if err := r.ParseForm(); err != nil { http.Error(w, "Failed to parse form", http.StatusBadRequest) @@ -87,34 +87,21 @@ func handleLinkLastfmForm(database *db.DB) http.HandlerFunc { } w.Header().Set("Content-Type", "text/html") - fmt.Fprintf(w, ` - - Link Last.fm Account - - - - -

Link Your Last.fm Account

-

Enter your Last.fm username to start tracking your scrobbles.

-
- - - -
- - `, currentUsername) + + pageParams := struct { + NavBar pages.NavBar + CurrentUsername string + }{ + NavBar: pages.NavBar{ + IsLoggedIn: authenticated, + LastFMUsername: currentUsername, + }, + CurrentUsername: currentUsername, + } + err = pg.Execute("lastFMForm", w, pageParams) + if err != nil { + log.Printf("Error executing template: %v", err) + } } } diff --git a/cmd/main.go b/cmd/main.go index 7c412f6..4ae62dc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -116,9 +116,6 @@ func main() { lastfmInterval = 30 * time.Second } - //if err := spotifyService.LoadAllUsers(); err != nil { - // log.Printf("Warning: Failed to preload Spotify users: %v", err) - //} go spotifyService.StartListeningTracker(trackerInterval) go lastfmService.StartListeningTracker(lastfmInterval) diff --git a/cmd/routes.go b/cmd/routes.go index 644edc4..1e153d1 100644 --- a/cmd/routes.go +++ b/cmd/routes.go @@ -10,13 +10,9 @@ import ( func (app *application) routes() http.Handler { mux := http.NewServeMux() - // Redirect /static to /static/ so it doesn't fall through to "/" handler + + //Handles static file routes mux.Handle("/static/{file_name}", app.pages.Static()) - //mux.HandleFunc("/static/{file_name}", func(w http.ResponseWriter, r *http.Request) { - // w.Header().Set("Content-Type", "text/html") - // - // w.Write([]byte("Static files are served from /static/")) - //}) mux.HandleFunc("/", session.WithPossibleAuth(home(app.database, app.pages), app.sessionManager)) @@ -30,8 +26,8 @@ func (app *application) routes() http.Handler { mux.HandleFunc("/current-track", session.WithAuth(app.spotifyService.HandleCurrentTrack, app.sessionManager)) mux.HandleFunc("/history", session.WithAuth(app.spotifyService.HandleTrackHistory, app.sessionManager)) mux.HandleFunc("/api-keys", session.WithAuth(app.apiKeyService.HandleAPIKeyManagement(app.database, app.pages), app.sessionManager)) - mux.HandleFunc("/link-lastfm", session.WithAuth(handleLinkLastfmForm(app.database), app.sessionManager)) // GET form - mux.HandleFunc("/link-lastfm/submit", session.WithAuth(handleLinkLastfmSubmit(app.database), app.sessionManager)) // POST submit - Changed route slightly + mux.HandleFunc("/link-lastfm", session.WithAuth(handleLinkLastfmForm(app.database, app.pages), app.sessionManager)) // GET form + mux.HandleFunc("/link-lastfm/submit", session.WithAuth(handleLinkLastfmSubmit(app.database), app.sessionManager)) // POST submit - Changed route slightly mux.HandleFunc("/logout", app.sessionManager.HandleLogout) mux.HandleFunc("/debug/", session.WithAuth(app.sessionManager.HandleDebug, app.sessionManager)) diff --git a/pages/pages.go b/pages/pages.go index 16bc24b..c9eb6b9 100644 --- a/pages/pages.go +++ b/pages/pages.go @@ -119,25 +119,20 @@ func (p *Pages) parseBase(top string) (*template.Template, error) { } func (p *Pages) Static() http.Handler { - //if p.dev { - // return http.StripPrefix("/static/", http.FileServer(http.Dir("appview/pages/static"))) - //} sub, err := fs.Sub(Files, "static") if err != nil { - //p.logger.Error("no static dir found? that's crazy", "err", err) panic(err) } - return http.StripPrefix("/static/", http.FileServer(http.FS(sub))) - // Custom handler to apply Cache-Control headers for font files - //return http.FileServer(http.FS(sub)) - //return http.FileServer(http.FS(sub)) + + return Cache(http.StripPrefix("/static/", http.FileServer(http.FS(sub)))) } func Cache(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { path := strings.Split(r.URL.Path, "?")[0] - + + //We may want to change these, just took what tangled has and allows browser side caching if strings.HasSuffix(path, ".css") { // on day for css files w.Header().Set("Cache-Control", "public, max-age=86400") diff --git a/pages/static/style.css b/pages/static/style.css deleted file mode 100644 index 3005160..0000000 --- a/pages/static/style.css +++ /dev/null @@ -1,32 +0,0 @@ -body { - font-family: Arial, sans-serif; - max-width: 800px; - margin: 0 auto; - padding: 20px; - line-height: 1.6; -} -h1 { - color: #1DB954; /* Spotify green */ -} -.nav { - display: flex; - flex-wrap: wrap; /* Allow wrapping on smaller screens */ - margin-bottom: 20px; -} -.nav a { - margin-right: 15px; - margin-bottom: 5px; /* Add spacing below links */ - text-decoration: none; - color: #1DB954; - font-weight: bold; -} -.card { - border: 1px solid #ddd; - border-radius: 8px; - padding: 20px; - margin-bottom: 20px; -} -.service-status { - font-style: italic; - color: #555; -} \ No newline at end of file diff --git a/pages/static/styles.css b/pages/static/styles.css new file mode 100644 index 0000000..8cb6b87 --- /dev/null +++ b/pages/static/styles.css @@ -0,0 +1,124 @@ +body { + font-family: Arial, sans-serif; + max-width: 800px; + margin: 0 auto; + padding: 20px; + line-height: 1.6; +} + + +h1 { + color: #1DB954; /* Spotify green */ +} + +.nav { + display: flex; + flex-wrap: wrap; /* Allow wrapping on smaller screens */ + margin-bottom: 20px; +} + +.nav a { + margin-right: 15px; + margin-bottom: 5px; /* Add spacing below links */ + text-decoration: none; + color: #1DB954; + font-weight: bold; +} + +.card { + border: 1px solid #ddd; + border-radius: 8px; + padding: 20px; + margin-bottom: 20px; +} + +.service-status { + font-style: italic; + color: #555; +} + + +label, input { + display: block; + margin-bottom: 10px; +} + +input[type='text'] { + width: 95%; + padding: 8px; +} + +/* Corrected width */ +input[type='submit'] { + padding: 10px 15px; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.last-fm-input { + background-color: #d51007; +} + +.teal-input { + background-color: #1DB954; +} + +.error { + color: red; + margin-bottom: 10px; +} + +.lastfm-form { + max-width: 600px; + margin: 20px auto; + padding: 20px; + border: 1px solid #ddd; + border-radius: 8px; +} + +.card { + border: 1px solid #ddd; + border-radius: 8px; + padding: 20px; + margin-bottom: 20px; +} +table { + width: 100%; + border-collapse: collapse; +} +table th, table td { + padding: 8px; + text-align: left; + border-bottom: 1px solid #ddd; +} +.key-value { + font-family: monospace; + padding: 10px; + background-color: #f5f5f5; + border: 1px solid #ddd; + border-radius: 4px; + word-break: break-all; +} +.new-key-alert { + background-color: #f8f9fa; + border-left: 4px solid #1DB954; + padding: 15px; + margin-bottom: 20px; +} +.btn { + padding: 8px 16px; + background-color: #1DB954; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} +.btn-danger { + background-color: #dc3545; +} + +.teal-header { + color: #1DB954; +} \ No newline at end of file diff --git a/pages/templates/apiKeys.gohtml b/pages/templates/apiKeys.gohtml index 1a81b0f..9d9d757 100644 --- a/pages/templates/apiKeys.gohtml +++ b/pages/templates/apiKeys.gohtml @@ -7,7 +7,7 @@

API Key Management

-

Create New API Key

+

Create New API Key

API keys allow programmatic access to your Piper account data.

@@ -20,7 +20,7 @@ {{if .NewKeyID}}
-

Your new API key (ID: {{.NewKeyID}}) has been created

+

Your new API key (ID: {{.NewKeyID}}) has been created

Important: If this is an ID, ensure you have copied the actual key if it was displayed previously. For keys generated via the API, the key is returned in the API response.

@@ -28,7 +28,7 @@ {{end}}
-

Your API Keys

+

Your API Keys

{{if .Keys}} @@ -60,7 +60,7 @@
-

API Usage

+

API Usage

To use your API key, include it in the Authorization header of your HTTP requests:

Authorization: Bearer YOUR_API_KEY

Or include it as a query parameter (less secure for the key itself):

diff --git a/pages/templates/home.gohtml b/pages/templates/home.gohtml index ff90e4a..1a9e617 100644 --- a/pages/templates/home.gohtml +++ b/pages/templates/home.gohtml @@ -2,23 +2,8 @@ {{ define "content" }}

Piper - Multi-User Spotify & Last.fm Tracker via ATProto

- + {{ template "components/navBar" .NavBar }} +

Welcome to Piper

@@ -53,7 +38,7 @@ - + diff --git a/pages/templates/lastFMForm.gohtml b/pages/templates/lastFMForm.gohtml index fb7a0e1..63ccfb3 100644 --- a/pages/templates/lastFMForm.gohtml +++ b/pages/templates/lastFMForm.gohtml @@ -1,10 +1,14 @@ {{ define "content" }} -

Link Your Last.fm Account

-

Enter your Last.fm username to start tracking your scrobbles.

-
- - - - + {{ template "components/navBar" .NavBar }} + +
+

Link Your Last.fm Account

+

Enter your Last.fm username to start tracking your scrobbles.

+
+ + + + +
{{ end }} \ No newline at end of file diff --git a/pages/templates/layouts/base.gohtml b/pages/templates/layouts/base.gohtml index bf4ac58..f8a1ad8 100644 --- a/pages/templates/layouts/base.gohtml +++ b/pages/templates/layouts/base.gohtml @@ -3,41 +3,7 @@ Piper - Spotify & Last.fm Tracker - - + {{ block "content" . }}{{ end }}