1
0
Fork 0
mirror of https://github.com/heyarne/airsonic-ui.git synced 2026-05-07 10:43:39 +02:00

Add alphabetical artist overview

This commit is contained in:
Arne Schlüter 2018-10-16 11:03:31 +02:00
commit c558943946
5 changed files with 76 additions and 11 deletions

View file

@ -1,5 +1,7 @@
(ns airsonic-ui.components.artist.views (ns airsonic-ui.components.artist.views
(:require [airsonic-ui.components.collection.views :as collection] (:require [airsonic-ui.components.collection.views :as collection]
[airsonic-ui.routes :as routes]
[airsonic-ui.components.debug.views :refer [debug]]
[clojure.string :as str])) [clojure.string :as str]))
(defn link-button [attrs children] (defn link-button [attrs children]
@ -19,6 +21,14 @@
(let [href (str "https://musicbrainz.org/artist/" (:musicBrainzId artist-info))] (let [href (str "https://musicbrainz.org/artist/" (:musicBrainzId artist-info))]
[link-button {:href href} "See on musicbrainz"])) [link-button {:href href} "See on musicbrainz"]))
(defn artist-links [artist-info]
(when-not (empty? (select-keys artist-info [:lastFmUrl :musicBrainzId]))
[:div.field.is-grouped
(when (:lastFmUrl artist-info)
[lastfm-link artist-info])
(when (:musicBrainzId artist-info)
[musicbrainz-link artist-info])]))
(defn detail (defn detail
"Creates a nice artist page displaying the artist's name, bio (if available and "Creates a nice artist page displaying the artist's name, bio (if available and
listing) their albums." listing) their albums."
@ -26,13 +36,37 @@
[:div [:div
[:section.hero>div.hero-body [:section.hero>div.hero-body
[:div.container [:div.container
[:h2.title (:name artist)] [:h1.title (:name artist)]
[:div.content [:div.content
[lastfm-bio artist-info] [lastfm-bio artist-info]
(when-not (empty? (select-keys artist-info [:lastFmUrl :musicBrainzId])) [artist-links artist-info]]]]
[:div.field.is-grouped
(when (:lastFmUrl artist-info)
[lastfm-link artist-info])
(when (:musicBrainzId artist-info)
[musicbrainz-link artist-info])])]]]
[:section.section>div.container [collection/listing (:album artist)]]]) [:section.section>div.container [collection/listing (:album artist)]]])
(defn alphabetical-listing
[artists]
[:div.alphabetical-list
(for [group artists]
^{:key (:name group)}
[:div.group
[:h1.subtitle.is-4 (:name group)]
[:ol.artist-links
(for [artist (:artist group)]
(let [href (routes/url-for ::routes/artist.detail (select-keys artist [:id]))]
^{:key (:id artist)} [:li [:a {:href href} (:name artist)]]))]])])
(defn overview
"Displays the alphabetical listing of all artists along with some additional
information about the collection"
[{:keys [artists]}]
(let [artists (:index artists)
;; TODO: Calculations in views should be avoided
artists-count (count (mapcat :artist artists))
album-count (->> (mapcat :artist artists)
(map :albumCount)
(reduce +))]
[:div
[:section.hero.is-small>div.hero-body
[:div.container
[:h1.title "Artists"]
[:p.subtitle.is-5.has-text-grey [:strong artists-count] " artists in your collection with " [:strong album-count] " albums"]]]
[:section.section>div.container [alphabetical-listing artists]]]))

View file

@ -9,7 +9,8 @@
(r/router [["/" ::login] (r/router [["/" ::login]
["/library" ::library] ["/library" ::library]
["/library/:criteria" ::library] ["/library/:criteria" ::library]
["/artist/:id" ::artist.detail] ["/artists" ::artist.overview]
["/artists/:id" ::artist.detail]
["/album/:id" ::album.detail] ["/album/:id" ::album.detail]
["/search" ::search] ["/search" ::search]
["/podcast" ::podcast.overview] ["/podcast" ::podcast.overview]
@ -24,8 +25,9 @@
([k params query] (str "#" (r/resolve router k params query)))) ([k params query] (str "#" (r/resolve router k params query))))
;; which routes need valid login credentials? ;; which routes need valid login credentials?
(def protected-routes #{::library ::artist.detail ::album.detail ::search (def protected-routes
::podcast.overview ::podcast.detail}) #{::library ::artist.overview ::artist.detail ::album.detail ::search
::podcast.overview ::podcast.detail})
;; which data should be requested for which route? can either be a vector or a function returning a vector ;; which data should be requested for which route? can either be a vector or a function returning a vector
@ -46,6 +48,10 @@
[:api/request "getAlbumList2" {:type criteria, :size 20, :offset (* 20 (dec page))}]] [:api/request "getAlbumList2" {:type criteria, :size 20, :offset (* 20 (dec page))}]]
[:routes/do-navigation [route-id {:criteria "recent"} {:page 1}]])) [:routes/do-navigation [route-id {:criteria "recent"} {:page 1}]]))
(defmethod -route-events ::artist.overview
[route-id params query]
[:api/request "getArtists"])
(defmethod -route-events ::artist.detail (defmethod -route-events ::artist.detail
[route-id params query] [route-id params query]
(let [params (select-keys params [:id])] (let [params (select-keys params [:id])]

View file

@ -73,7 +73,8 @@
[navbar-dropdown "Library" [navbar-dropdown "Library"
[[{:href (url-for ::routes/library {:criteria "recent"})} "Recently played"] [[{:href (url-for ::routes/library {:criteria "recent"})} "Recently played"]
[{:href (url-for ::routes/library {:criteria "newest"})} "Newest additions"] [{:href (url-for ::routes/library {:criteria "newest"})} "Newest additions"]
[{:href (url-for ::routes/library {:criteria "starred"})} "Starred"]]]) [{:href (url-for ::routes/library {:criteria "starred"})} "Starred"]
[{:href (url-for ::routes/artist.overview)} "By artist"]]])
(when podcast-role (when podcast-role
#_(let [podcast-url (url-for ::routes/podcast.overview)] #_(let [podcast-url (url-for ::routes/podcast.overview)]
[navbar-dropdown "Podcast" {:href podcast-url} [navbar-dropdown "Podcast" {:href podcast-url}
@ -111,6 +112,7 @@
[breadcrumbs route content] [breadcrumbs route content]
(case route-id (case route-id
::routes/library [library/main route content] ::routes/library [library/main route content]
::routes/artist.overview [artist/overview content]
::routes/artist.detail [artist/detail content] ::routes/artist.detail [artist/detail content]
::routes/album.detail [collection/detail content] ::routes/album.detail [collection/detail content]
::routes/search [search/results content] ::routes/search [search/results content]

View file

@ -20,12 +20,17 @@
(def start [(url-for ::routes/library) "Start"]) (def start [(url-for ::routes/library) "Start"])
(defmethod breadcrumbs ::routes/artist.overview [_ _]
[bulma-breadcrumbs start "Artists"])
(defmethod breadcrumbs ::routes/artist.detail [_ {:keys [artist]}] (defmethod breadcrumbs ::routes/artist.detail [_ {:keys [artist]}]
[bulma-breadcrumbs start [bulma-breadcrumbs start
[(url-for ::routes/artist.overview) "Artists"]
(:name artist)]) (:name artist)])
(defmethod breadcrumbs ::routes/album.detail [_ {:keys [album]}] (defmethod breadcrumbs ::routes/album.detail [_ {:keys [album]}]
[bulma-breadcrumbs start [bulma-breadcrumbs start
[(url-for ::routes/artist.overview) "Artists"]
[(url-for ::routes/artist.detail {:id (:artistId album)}) (:artist album)] [(url-for ::routes/artist.detail {:id (:artistId album)}) (:artist album)]
(:name album)]) (:name album)])

View file

@ -150,6 +150,24 @@
.missing-cover .missing-cover
display: inline-block display: inline-block
.artist.overview
.alphabetical-list
column-count: 2
column-gap: 1.2rem
ol
list-style: none
+tablet
column-count: 3
+widescreen
column-count: 4
.group
margin-bottom: 1.5rem
.subtitle.is-4
margin-bottom: 1rem
.album.detail .album.detail
.collection-info .collection-info
list-style: none list-style: none