diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 628c576..4711cf8 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -278,6 +278,21 @@ def get_artists(dbconn=None): return sqldb.get_artists(dbconn=dbconn) +def get_albums_artist_appears_on(dbconn=None,**keys): + + artist_id = sqldb.get_artist_id(keys['artist'],dbconn=dbconn) + + albums = sqldb.get_albums_artists_appear_on([artist_id],dbconn=dbconn).get(artist_id) or [] + ownalbums = sqldb.get_albums_of_artists([artist_id],dbconn=dbconn).get(artist_id) or [] + + result = { + "own_albums":ownalbums, + "appears_on":[a for a in albums if a not in ownalbums] + } + + return result + + @waitfordb def get_charts_artists(dbconn=None,**keys): (since,to) = keys.get('timerange').timestamps() diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index cd9e31d..aeb9e45 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -368,9 +368,7 @@ def get_track_id(trackdict,create_new=True,update_album=False,dbconn=None): - op = DB['tracks'].select( -# DB['tracks'].c.id - ).where( + op = DB['tracks'].select().where( DB['tracks'].c.title_normalized==ntitle ) result = dbconn.execute(op).all() @@ -418,9 +416,7 @@ def get_artist_id(artistname,create_new=True,dbconn=None): nname = normalize_name(artistname) #print("looking for",nname) - op = DB['artists'].select( -# DB['artists'].c.id - ).where( + op = DB['artists'].select().where( DB['artists'].c.name_normalized==nname ) result = dbconn.execute(op).all() @@ -1114,6 +1110,41 @@ def get_albums_of_artists(artist_ids,dbconn=None): albums.setdefault(row.artist_id,[]).append(album_db_to_dict(row,dbconn=dbconn)) return albums +@cached_wrapper_individual +@connection_provider +# this includes the artists' own albums! +def get_albums_artists_appear_on(artist_ids,dbconn=None): + + jointable1 = sql.join( + DB["trackartists"], + DB["tracks"] + ) + jointable2 = sql.join( + jointable1, + DB["albums"] + ) + + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB["albums"], + DB["trackartists"].c.artist_id + ).select_from(jointable2).where( + DB['trackartists'].c.artist_id.in_(artist_ids) + ) + result = dbconn.execute(op).all() + + albums = {} + # avoid duplicates from multiple tracks in album by same artist + already_done = {} + for row in result: + if row.id in already_done.setdefault(row.artist_id,[]): + pass + else: + albums.setdefault(row.artist_id,[]).append(album_db_to_dict(row,dbconn=dbconn)) + already_done[row.artist_id].append(row.id) + return albums + @cached_wrapper_individual @connection_provider diff --git a/maloja/pkg_global/conf.py b/maloja/pkg_global/conf.py index 7224970..f519dc5 100644 --- a/maloja/pkg_global/conf.py +++ b/maloja/pkg_global/conf.py @@ -191,6 +191,7 @@ malojaconfig = Configuration( "default_range_charts_tracks":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Track Charts", "year"), "default_step_pulse":(tp.Choice({'year':'Year','month':"Month",'week':'Week','day':'Day'}), "Default Pulse Step", "month"), "charts_display_tiles":(tp.Boolean(), "Display Chart Tiles", False), + "album_showcase":(tp.Boolean(), "Display Album Showcase", True, "Display a graphical album showcase for artist overview pages instead of a chart list"), "display_art_icons":(tp.Boolean(), "Display Album/Artist Icons", True), "default_album_artist":(tp.String(), "Default Albumartist", "Various Artists"), "discourage_cpu_heavy_stats":(tp.Boolean(), "Discourage CPU-heavy stats", False, "Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors!"), diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index ba4b99f..f9b5c42 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -91,11 +91,18 @@ {% if info["isalbumartist"] %} -

Top Albums

-{% with amountkeys={"perpage":15,"page":0} %} -{% include 'partials/charts_albums.jinja' %} -{% endwith %} +{% if settings['ALBUM_SHOWCASE'] %} +

Albums

+ {% include 'partials/album_showcase.jinja' %} +{% else %} +

Top Albums

+ + {% with amountkeys={"perpage":15,"page":0} %} + {% include 'partials/charts_albums.jinja' %} + {% endwith %} +{% endif %} + {% endif %} {% if info['scrobbles']>0 %} diff --git a/maloja/web/jinja/partials/album_showcase.jinja b/maloja/web/jinja/partials/album_showcase.jinja new file mode 100644 index 0000000..798ad65 --- /dev/null +++ b/maloja/web/jinja/partials/album_showcase.jinja @@ -0,0 +1,43 @@ +{% import 'snippets/links.jinja' as links %} + +{% set info = dbc.get_albums_artist_appears_on(filterkeys,limitkeys) %} +{% set ownalbums = info.own_albums %} +{% set otheralbums = info.appears_on %} + +
+ + +{% for album in ownalbums %}{% endfor %} +{% if ownalbums and otheralbums%}{% endif %} +{% for album in otheralbums %}{% endfor %} + + + +{% for album in ownalbums %} + +{% endfor %} +{% if ownalbums and otheralbums%}{% endif %} +{% for album in otheralbums %} + +{% endfor %} + + + +{% for album in ownalbums %} + +{% endfor %} +{% if ownalbums and otheralbums%}{% endif %} +{% for album in otheralbums %} + +{% endfor %} + +
Appears on
+ +
+
+
+ +
+
+
{{ album.albumtitle }}{{ album.albumtitle }}
+
diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index a6c3827..d1b7524 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -898,6 +898,39 @@ table.tiles_sub a span { } +div#showcase_scroll_container { + overflow-x: scroll; + overflow-y: show; + margin-top: -15px; +} + +table.album_showcase { + text-align: center; + +} +table.album_showcase tr:nth-child(1) { + opacity: 0.3; +} +table.album_showcase td { + padding: 20px; + padding-bottom:3px; + padding-top:0px; + width: 150px; +} +table.album_showcase td.album_separator_column { + width: 40px; +} + +table.album_showcase td div { + height: 150px; + width: 150px; + + background-size: cover; + background-position: top; + + box-shadow: 0px 0px 10px 10px rgba(3,3,3,0.5); +} + .summary_rank { background-size:cover;