lyrics

lyrics
git clone git://brookjeynes.dev/bjeynes/lyrics.git
Log | Files | Refs

commit d33195c234281017be8241f8afebb49a400d70b0
parent 894f416af1ede25f0ae161d3ba4c90c0fb4c1c67
Author: brookjeynes <me@brookjeynes.dev>
Date:   Fri, 19 Jun 2026 08:49:19 +1000

ui: style add artist page

Task-id: yqlqrzkxypsltypk
Signed-off-by: brookjeynes <me@brookjeynes.dev>

Diffstat:
Minternal/server/new-artist.go | 27+++++++++++++++++++--------
Minternal/server/ui/partials/similar-artists-list/similar-artists-list.templ | 38+++++++++++++++++++++-----------------
Minternal/server/ui/views/edit-release/edit-release.templ | 2+-
Ainternal/server/ui/views/new-artist/new-artist.css | 16++++++++++++++++
Minternal/server/ui/views/new-artist/new-artist.templ | 67++++++++++++++++++++++++++++++++++++++++---------------------------
Minternal/server/ui/views/new-release/new-release.templ | 2+-
Minternal/server/ui/views/new-song/new-song.templ | 2+-
Mscripts/build-assets.sh | 1+
Rtasks/style_and_improve_ux_for_new_artist_form.txt -> tasks/done/style_and_improve_ux_for_new_artist_form.txt | 0
Atasks/pull_artist_metadata_from_musicbrainz.txt | 7+++++++
10 files changed, 107 insertions(+), 55 deletions(-)

diff --git a/internal/server/new-artist.go b/internal/server/new-artist.go @@ -12,10 +12,11 @@ import ( ) type NewArtistForm struct { - Name string `schema:"artist"` - Bio string `schema:"biography"` - LatinName string `schema:"latin-name"` - Disambiguation string `schema:"disambiguation"` + Name string `schema:"artist"` + Bio string `schema:"biography"` + LatinName string `schema:"latin-name"` + Disambiguation string `schema:"disambiguation"` + MusicBrainzArtistID domain.MusicBrainzID `schema:"musicbrainz-artist-id"` } func parseNewArtistForm(form NewArtistForm) (domain.Artist, error) { @@ -56,11 +57,21 @@ func parseNewArtistForm(form NewArtistForm) (domain.Artist, error) { disambiguation = &form.Disambiguation } + // musicbrainz release id + var musicbrainzArtistID *domain.MusicBrainzID + if form.MusicBrainzArtistID != "" { + if !domain.MusicBrainzIDIsValid(string(form.MusicBrainzArtistID)) { + return artist, fmt.Errorf("'%s' must be a valid MusicBrainz ID", form.MusicBrainzArtistID) + } + musicbrainzArtistID = &form.MusicBrainzArtistID + } + artist = domain.Artist{ - Name: form.Name, - LatinName: latinName, - Bio: bio, - Disambiguation: disambiguation, + Name: form.Name, + LatinName: latinName, + Bio: bio, + Disambiguation: disambiguation, + MusicBrainzArtistID: musicbrainzArtistID, } return artist, nil diff --git a/internal/server/ui/partials/similar-artists-list/similar-artists-list.templ b/internal/server/ui/partials/similar-artists-list/similar-artists-list.templ @@ -1,24 +1,28 @@ package similarartistslist import "fmt" +import "lyrics/internal/server/routes" templ SimilarArtistsList(params SimilarArtistsListParams) { - <ul id="similar-artists"> - for _, artist := range params.Artists { - {{ - value := artist.Name + if len(params.Artists) >= 1 { + <p class="section-label -muted">Similar artists</p> + <ul> + for _, artist := range params.Artists { + {{ + value := artist.Name - if artist.LatinName != nil && artist.Disambiguation != nil { - value = fmt.Sprintf("%s (%s, %s)", artist.Name, *artist.LatinName, *artist.Disambiguation) - } else if artist.LatinName != nil { - value = fmt.Sprintf("%s (%s)", artist.Name, *artist.LatinName) - } else if artist.Disambiguation != nil { - value = fmt.Sprintf("%s (%s)", artist.Name, *artist.Disambiguation) - } - }} - <li title={ value }> - { value } - </li> - } - </ul> + if artist.LatinName != nil && artist.Disambiguation != nil { + value = fmt.Sprintf("%s (%s, %s)", artist.Name, *artist.LatinName, *artist.Disambiguation) + } else if artist.LatinName != nil { + value = fmt.Sprintf("%s (%s)", artist.Name, *artist.LatinName) + } else if artist.Disambiguation != nil { + value = fmt.Sprintf("%s (%s)", artist.Name, *artist.Disambiguation) + } + }} + <li title={ value }> + <a href={ routes.Artist(artist) }>{ value }</a> + </li> + } + </ul> + } } diff --git a/internal/server/ui/views/edit-release/edit-release.templ b/internal/server/ui/views/edit-release/edit-release.templ @@ -210,7 +210,7 @@ templ EditRelease(params EditReleaseParams) { </fieldset> <fieldset> <legend>MusicBrainz</legend> - <label title="External identifier used for metadata lookups such as cover art. This app does not contact MusicBrainz when saving."> + <label title="External identifier used for metadata lookups such as cover art."> Release ID (optional): <input name="musicbrainz-release-id" diff --git a/internal/server/ui/views/new-artist/new-artist.css b/internal/server/ui/views/new-artist/new-artist.css @@ -0,0 +1,16 @@ +.artist-form { + max-width: 42rem; + + fieldset { + margin: 1.5rem 0; + } + + textarea { + min-height: 18rem; + margin-top: 0.5rem; + border: 1px solid var(--dark-gray); + width: 100%; + padding: 0.75rem; + resize: vertical; + } +} diff --git a/internal/server/ui/views/new-artist/new-artist.templ b/internal/server/ui/views/new-artist/new-artist.templ @@ -6,21 +6,23 @@ import ( ) templ NewArtist(params NewArtistParams) { - @base.Base(base.BaseParams{Title: "new artist"}) { + @base.Base(base.BaseParams{Title: "new artist", PageStylesheets: []string{"new-artist.css"}}) { <h1>Add an artist</h1> <form + class="artist-form" hx-post="/artist/new" hx-swap="none" hx-disable-elt="#add-artist-btn" > <fieldset x-data="{ showLatinName: false }"> + <legend>Name</legend> <label title="prefer the artists name in their original language. use the latin name input for english names"> artist: <input hx-get="/artist/search?format=similar" hx-trigger="input changed delay:500ms, load" hx-target="#similar-artists" - hx-swap="outerHTML" + hx-swap="innerHTML" name="artist" type="text" pattern={ domain.NoTrailingOrLeadingSpaceRegex.String() } @@ -38,31 +40,42 @@ templ NewArtist(params NewArtistParams) { /> </label> </fieldset> - <label title="helps users distinguish between artists with identical or similar names, e.g. South Korean singer-songwriter"> - disambiguation: - <input - name="disambiguation" - type="text" - pattern={ domain.NoTrailingOrLeadingSpaceRegex.String() } - title="helps users distinguish between artists with identical or similar names, e.g. South Korean singer-songwriter" - /> - <i data-lucide="info"></i> - </label> - <div> - <span>similar artists</span> - <ul id="similar-artists"></ul> - </div> - <label> - biography: - <textarea - name="biography" - rows="20" - spellcheck - ></textarea> - </label> - <button id="add-artist-btn" type="submit"> - add artist - </button> + <section id="similar-artists" class="similar-artists" aria-label="Similar artists"></section> + <fieldset> + <legend>Disambiguation</legend> + <label title="helps users distinguish between artists with identical or similar names, e.g. South Korean singer-songwriter"> + disambiguation: + <input + name="disambiguation" + type="text" + pattern={ domain.NoTrailingOrLeadingSpaceRegex.String() } + /> + <i data-lucide="info"></i> + </label> + </fieldset> + <fieldset> + <legend>Biography</legend> + <label> + biography: + <textarea name="biography" rows="16" spellcheck></textarea> + </label> + </fieldset> + <fieldset> + <legend>MusicBrainz</legend> + <label title="External identifier used for metadata lookups such as cover art."> + Artist ID (optional): + <input + name="musicbrainz-artist-id" + type="text" + pattern={ domain.IsValidMusicBrainzIDPattern } + placeholder="e32a4ae3-67d1-4541-84d8-de6ab2d7dec1" + /> + <i data-lucide="info"></i> + </label> + </fieldset> + <footer aria-label="Form actions"> + <button class="-primary" id="add-artist-btn" type="submit">add artist</button> + </footer> </form> } } diff --git a/internal/server/ui/views/new-release/new-release.templ b/internal/server/ui/views/new-release/new-release.templ @@ -140,7 +140,7 @@ templ NewRelease(params NewReleaseParams) { </fieldset> <fieldset> <legend>MusicBrainz</legend> - <label title="External identifier used for metadata lookups such as cover art. This app does not contact MusicBrainz when saving."> + <label title="External identifier used for metadata lookups such as cover art."> Release ID (optional): <input name="musicbrainz-release-id" diff --git a/internal/server/ui/views/new-song/new-song.templ b/internal/server/ui/views/new-song/new-song.templ @@ -294,7 +294,7 @@ templ NewSong(params NewSongParams) { </fieldset> <fieldset> <legend>MusicBrainz</legend> - <label title="External identifier used for metadata lookups such as cover art. This app does not contact MusicBrainz when saving."> + <label title="External identifier used for metadata lookups such as cover art."> Recording ID (optional): <input name="musicbrainz-recording-id" diff --git a/scripts/build-assets.sh b/scripts/build-assets.sh @@ -16,6 +16,7 @@ minify internal/server/ui/style.css -o static/files/style.css minify internal/server/toast/toast.css -o static/files/toast.css minify internal/server/ui/views/song/song.css -o static/files/song.css minify internal/server/ui/views/artist/artist.css -o static/files/artist.css +minify internal/server/ui/views/new-artist/new-artist.css -o static/files/new-artist.css minify internal/server/ui/views/release/release.css -o static/files/release.css minify internal/server/ui/views/new-release/new-release.css -o static/files/new-release.css minify internal/server/ui/views/new-song/new-song.css -o static/files/new-song.css diff --git a/tasks/style_and_improve_ux_for_new_artist_form.txt b/tasks/done/style_and_improve_ux_for_new_artist_form.txt diff --git a/tasks/pull_artist_metadata_from_musicbrainz.txt b/tasks/pull_artist_metadata_from_musicbrainz.txt @@ -0,0 +1,7 @@ +pull artist metadata from musicbrainz @feat +artist +id: wznxmyrtuxlplrxu + +we can pull a lot of data from musicbrainz that users might want to see + + $ curl musicbrainz.org/ws/2/artist/<artist-id> \ + -H "Accept: application/json" -H "User-Agent: lyrics/0.1"