From 03f3952d1ac65cdbf55be7bb69f850a0a5bf8314 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 24 May 2023 16:05:15 +0200 Subject: [PATCH 1/7] Turned tiles from table into grid --- maloja/web/jinja/icons/nodata.jinja | 4 +- .../jinja/partials/charts_albums_tiles.jinja | 54 +++---- .../jinja/partials/charts_artists_tiles.jinja | 54 +++---- .../jinja/partials/charts_tracks_tiles.jinja | 53 +++---- maloja/web/static/css/maloja.css | 140 +++++++++--------- 5 files changed, 130 insertions(+), 175 deletions(-) diff --git a/maloja/web/jinja/icons/nodata.jinja b/maloja/web/jinja/icons/nodata.jinja index dde0cbb..8ddb3d1 100644 --- a/maloja/web/jinja/icons/nodata.jinja +++ b/maloja/web/jinja/icons/nodata.jinja @@ -1,7 +1,7 @@ - +

No scrobbles yet! - +
diff --git a/maloja/web/jinja/partials/charts_albums_tiles.jinja b/maloja/web/jinja/partials/charts_albums_tiles.jinja index 400d68b..86f7ba2 100644 --- a/maloja/web/jinja/partials/charts_albums_tiles.jinja +++ b/maloja/web/jinja/partials/charts_albums_tiles.jinja @@ -6,40 +6,26 @@ {% endif %} {% set charts_14 = charts | fixlength(14) %} -{% set charts_cycler = cycler(*charts_14) %} - - -{% for segment in range(3) %} - {% if charts_14[0] is none and loop.first %} - {% include 'icons/nodata.jinja' %} - {% else %} - +
+ {% if charts_14[0] is none %} + {% include 'icons/nodata.jinja' %} {% endif %} -{% endfor %} -
- {% set segmentsize = segment+1 %} - - {% for row in range(segmentsize) -%} - - {% for col in range(segmentsize) %} - {% set entry = charts_cycler.next() %} - {% if entry is not none %} - {% set album = entry.album %} - {% set rank = entry.rank %} - - {% else -%} - - {%- endif -%} - {%- endfor -%} - - {%- endfor -%} -
- -
- #{{ rank }} {{ album.albumtitle }} -
-
-
-
+ {% for entry in charts_14 %} + {% if entry is not none %} + {% set album = entry.album %} + {% set rank = entry.rank %} +
+ +
+ #{{ rank }} {{ album.albumtitle }} +
+
+
+ {% else %} +
+ {% endif %} + {% endfor %} + + diff --git a/maloja/web/jinja/partials/charts_artists_tiles.jinja b/maloja/web/jinja/partials/charts_artists_tiles.jinja index 23ac18e..ef97ede 100644 --- a/maloja/web/jinja/partials/charts_artists_tiles.jinja +++ b/maloja/web/jinja/partials/charts_artists_tiles.jinja @@ -6,40 +6,26 @@ {% endif %} {% set charts_14 = charts | fixlength(14) %} -{% set charts_cycler = cycler(*charts_14) %} - - -{% for segment in range(3) %} - {% if charts_14[0] is none and loop.first %} - {% include 'icons/nodata.jinja' %} - {% else %} - +
+ {% if charts_14[0] is none %} + {% include 'icons/nodata.jinja' %} {% endif %} -{% endfor %} -
- {% set segmentsize = segment+1 %} - - {% for row in range(segmentsize) -%} - - {% for col in range(segmentsize) %} - {% set entry = charts_cycler.next() %} - {% if entry is not none %} - {% set artist = entry.artist %} - {% set rank = entry.rank %} - - {% else -%} - - {%- endif -%} - {%- endfor -%} - - {%- endfor -%} -
- -
- #{{ rank }} {{ artist }} -
-
-
-
+ {% for entry in charts_14 %} + {% if entry is not none %} + {% set artist = entry.artist %} + {% set rank = entry.rank %} +
+ +
+ #{{ rank }} {{ artist }} +
+
+
+ {% else %} +
+ {% endif %} + {% endfor %} + + diff --git a/maloja/web/jinja/partials/charts_tracks_tiles.jinja b/maloja/web/jinja/partials/charts_tracks_tiles.jinja index ba66a10..6b238a6 100644 --- a/maloja/web/jinja/partials/charts_tracks_tiles.jinja +++ b/maloja/web/jinja/partials/charts_tracks_tiles.jinja @@ -6,39 +6,26 @@ {% endif %} {% set charts_14 = charts | fixlength(14) %} -{% set charts_cycler = cycler(*charts_14) %} - -{% for segment in range(3) %} - {% if charts_14[0] is none and loop.first %} - {% include 'icons/nodata.jinja' %} - {% else %} - +
+ {% if charts_14[0] is none %} + {% include 'icons/nodata.jinja' %} {% endif %} -{% endfor %} -
- {% set segmentsize = segment+1 %} - - {% for row in range(segmentsize) -%} - - {% for col in range(segmentsize) %} - {% set entry = charts_cycler.next() %} - {% if entry is not none %} - {% set track = entry.track %} - {% set rank = entry.rank %} - - {% else -%} - - {%- endif %} - {%- endfor -%} - - {%- endfor %} -
- -
- #{{ rank }} {{ track.title }} -
-
-
-
+ {% for entry in charts_14 %} + {% if entry is not none %} + {% set track = entry.track %} + {% set rank = entry.rank %} +
+ +
+ #{{ rank }} {{ track.title }} +
+
+
+ {% else %} +
+ {% endif %} + {% endfor %} + + diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index 239b44a..3c838db 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -800,53 +800,76 @@ table.misc td { +div.tiles { + display: grid; + grid-template-columns: repeat(18, 50px); + grid-template-rows: repeat(6, 50px); + grid-auto-flow: row dense; - - - -table.tiles_top td { - padding:0px; - border:0px; } -table.tiles_top:hover td td { +div.tiles div { + height: 100%; + width: 100%; + background-size: cover; + background-position:top center; + overflow: hidden; +} + +div.tiles:hover div { opacity:0.5; filter: grayscale(80%); } -table.tiles_top:hover td td:hover { +div.tiles:hover div:hover { opacity:1; filter: grayscale(0%); } -table.tiles_top, table.tiles_sub { - border-collapse: collapse; +div.tiles div.tile:nth-child(1) { + grid-column: span 6; + grid-row: span 6; + + font-size:100% +} + +div.tiles div.tile:nth-child(2), +div.tiles div.tile:nth-child(3), +div.tiles div.tile:nth-child(4), +div.tiles div.tile:nth-child(5) { + grid-column: span 3; + grid-row: span 3; + + font-size:80% +} + +div.tiles div.tile:nth-child(2), +div.tiles div.tile:nth-child(4) { + grid-column-start: 7; + grid-column-end: span 3; +} +div.tiles div.tile:nth-child(3), +div.tiles div.tile:nth-child(5) { + grid-column-start: 10; + grid-column-end: span 3; +} + +div.tiles div.tile:nth-child(6), +div.tiles div.tile:nth-child(7), +div.tiles div.tile:nth-child(8), +div.tiles div.tile:nth-child(9), +div.tiles div.tile:nth-child(10), +div.tiles div.tile:nth-child(11), +div.tiles div.tile:nth-child(12), +div.tiles div.tile:nth-child(13), +div.tiles div.tile:nth-child(14) { + grid-column: span 2; + grid-row: span 2; + + font-size:60% } - -table.tiles_top>tbody>tr>td { - height:300px; - width:300px; -} - - -table.tiles_sub { - height:100%; - width:100%; -} - -table.tiles_sub div { - height:100%; - width:100%; -} - -table.tiles_top td div { - background-size:cover; - background-position:top center; - vertical-align:bottom; -} - -table.tiles_top td span { +div.tiles span { background-color:rgba(0,0,0,0.7); display: inline-block; margin-top:2%; @@ -854,48 +877,21 @@ table.tiles_top td span { max-width: 67%; vertical-align: text-top; } -table.tiles_top td a:hover { +div.tiles span { + overflow-wrap: anywhere; +} + +div.tiles a:hover { text-decoration: none; } -table.tiles_1x1 td { - height:100%; - width:100%; - font-size:100% -} -table.tiles_2x2 td { - height:50%; - width:50%; - font-size:80% -} -table.tiles_3x3 td { - height:33.333%; - width:33.333%; - font-size:60% -} -table.tiles_4x4 td { - font-size:50% -} -table.tiles_5x5 td { - font-size:40% -} -/* Safari fix */ -table.tiles_sub.tiles_3x3 td div { - min-height: 100px; - min-width: 100px; -} -table.tiles_sub.tiles_2x2 td div { - min-height: 150px; - min-width: 150px; -} -table.tiles_sub.tiles_1x1 td div { - min-height: 300px; - min-width: 300px; -} -table.tiles_sub a span { - overflow-wrap: anywhere; -} + + + + + + div#showcase_container { From 75c0ab385bbf4c405a8e2481da501b88ac75c8aa Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 24 May 2023 16:26:35 +0200 Subject: [PATCH 2/7] Fixed track image fetch without album info --- maloja/images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maloja/images.py b/maloja/images.py index e6ffec7..ab668dc 100644 --- a/maloja/images.py +++ b/maloja/images.py @@ -136,7 +136,7 @@ def resolve_track_image(track_id): if malojaconfig["USE_ALBUM_ARTWORK_FOR_TRACKS"]: track = database.sqldb.get_track(track_id) - if "album" in track: + if track.get("album"): album_id = database.sqldb.get_album_id(track["album"]) albumart = resolve_album_image(album_id) if albumart: From 6ff7aa2ee035eb81e61b85b28ba2f7cbb55130f5 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 24 May 2023 17:44:50 +0200 Subject: [PATCH 3/7] Experimental start page redesign --- maloja/pkg_global/conf.py | 3 +- maloja/web/jinja/partials/info_album.jinja | 45 +++++++ maloja/web/jinja/partials/info_artist.jinja | 59 +++++++++ maloja/web/jinja/partials/info_track.jinja | 48 +++++++ maloja/web/jinja/snippets/links.jinja | 2 +- maloja/web/jinja/start.jinja | 121 ++++-------------- .../startpage_modules/charts_albums.jinja | 19 +++ .../startpage_modules/charts_artists.jinja | 19 +++ .../startpage_modules/charts_tracks.jinja | 19 +++ .../jinja/startpage_modules/featured.jinja | 58 +++++++++ .../startpage_modules/lastscrobbles.jinja | 15 +++ .../web/jinja/startpage_modules/pulse.jinja | 17 +++ maloja/web/static/css/maloja.css | 38 +----- maloja/web/static/css/startpage.css | 49 +++++++ maloja/web/static/js/rangeselect.js | 21 +-- 15 files changed, 386 insertions(+), 147 deletions(-) create mode 100644 maloja/web/jinja/partials/info_album.jinja create mode 100644 maloja/web/jinja/partials/info_artist.jinja create mode 100644 maloja/web/jinja/partials/info_track.jinja create mode 100644 maloja/web/jinja/startpage_modules/charts_albums.jinja create mode 100644 maloja/web/jinja/startpage_modules/charts_artists.jinja create mode 100644 maloja/web/jinja/startpage_modules/charts_tracks.jinja create mode 100644 maloja/web/jinja/startpage_modules/featured.jinja create mode 100644 maloja/web/jinja/startpage_modules/lastscrobbles.jinja create mode 100644 maloja/web/jinja/startpage_modules/pulse.jinja create mode 100644 maloja/web/static/css/startpage.css diff --git a/maloja/pkg_global/conf.py b/maloja/pkg_global/conf.py index a9be47b..f8c61f4 100644 --- a/maloja/pkg_global/conf.py +++ b/maloja/pkg_global/conf.py @@ -189,8 +189,7 @@ malojaconfig = Configuration( "parse_remix_artists":(tp.Boolean(), "Parse Remix Artists", False) }, "Web Interface":{ - "default_range_charts_artists":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Artist Charts", "year"), - "default_range_charts_tracks":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Track Charts", "year"), + "default_range_startpage":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range for Startpage Stats", "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"), diff --git a/maloja/web/jinja/partials/info_album.jinja b/maloja/web/jinja/partials/info_album.jinja new file mode 100644 index 0000000..95a9ca9 --- /dev/null +++ b/maloja/web/jinja/partials/info_album.jinja @@ -0,0 +1,45 @@ +{% import 'snippets/links.jinja' as links %} +{% import 'partials/awards_album.jinja' as awards %} + +{% set album = filterkeys.album %} +{% set info = dbc.album_info({'album':album}) %} + +{% set encodedalbum = mlj_uri.uriencode({'album':album}) %} + + + + + + + +
+ {% if adminmode %} +
+ {% else %} +
+
+ {% endif %} +
+ {{ links.links(album.artists) }}
+

{{ info.album.albumtitle | e }}

+ {# awards.certs(album) #} + #{{ info.position }} +
+ +

+ {{ info['scrobbles'] }} Scrobbles +

+ + + + + + {{ awards.medals(info) }} + {{ awards.topweeks(info) }} + + +
diff --git a/maloja/web/jinja/partials/info_artist.jinja b/maloja/web/jinja/partials/info_artist.jinja new file mode 100644 index 0000000..f3308a9 --- /dev/null +++ b/maloja/web/jinja/partials/info_artist.jinja @@ -0,0 +1,59 @@ +{% import 'snippets/links.jinja' as links %} +{% import 'partials/awards_artist.jinja' as awards %} + + +{% set artist = filterkeys.artist %} +{% set info = db.artist_info(artist=artist) %} + +{% set credited = info.get('replace') %} +{% set included = info.get('associated') %} + +{% if credited is not none %} + {% set competes = false %} +{% else %} + {% set credited = artist %} + {% set competes = true %} +{% endif %} + + + + + + + +
+ {% if adminmode %} +
+ {% else %} +
+
+ {% endif %} +
+

{{ info.artist | e }}

+ {% if competes and info['scrobbles']>0 %}#{{ info.position }}{% endif %} +
+ {% if competes and included %} + associated: {{ links.links(included) }} + {% elif not competes %} + Competing under {{ links.link(credited) }} (#{{ info.position }}) + {% endif %} + +

+ {{ info['scrobbles'] }} Scrobbles +

+ + + + + {% if competes %} + {{ awards.medals(info) }} + {{ awards.topweeks(info) }} + {% endif %} + {{ awards.certs(artist) }} + + +
diff --git a/maloja/web/jinja/partials/info_track.jinja b/maloja/web/jinja/partials/info_track.jinja new file mode 100644 index 0000000..f46e342 --- /dev/null +++ b/maloja/web/jinja/partials/info_track.jinja @@ -0,0 +1,48 @@ +{% import 'snippets/links.jinja' as links %} + +{% set track = filterkeys.track %} +{% set info = dbc.track_info({'track':track}) %} + +{% import 'partials/awards_track.jinja' as awards %} + + + + + + + +
+ {% if adminmode %} +
+ {% else %} +
+
+ {% endif %} +
+ {{ links.links(track.artists) }}
+

{{ info.track.title | e }}

+ {{ awards.certs(track) }} + #{{ info.position }} +
+ {% if info.track.album %} + from {{ links.link(info.track.album) }}
+ {% endif %} + +

+ {% if adminmode %}{% endif %} + {{ info['scrobbles'] }} Scrobbles +

+ + + + + + {{ awards.medals(info) }} + {{ awards.topweeks(info) }} + + +
diff --git a/maloja/web/jinja/snippets/links.jinja b/maloja/web/jinja/snippets/links.jinja index 3b5c29d..f90a535 100644 --- a/maloja/web/jinja/snippets/links.jinja +++ b/maloja/web/jinja/snippets/links.jinja @@ -1,5 +1,5 @@ {% macro link(entity) -%} - {% if entity is mapping and 'title' in entity or 'albumtitle' in entity %} + {% if entity is mapping and ('title' in entity or 'albumtitle' in entity) %} {% set name = entity.title or entity.albumtitle %} {% else %} {% set name = entity %} diff --git a/maloja/web/jinja/start.jinja b/maloja/web/jinja/start.jinja index f8240da..eb22b37 100644 --- a/maloja/web/jinja/start.jinja +++ b/maloja/web/jinja/start.jinja @@ -3,109 +3,44 @@ {% block scripts %} - - + + + + {% endblock %} {% block content -%} - - -

Top Artists

- - {% for r in xcurrent -%} - - {{ r.localisation }} - - {{ "|" if not loop.last }} - {%- endfor %} - -

+
- {% for r in xcurrent -%} - - {%- endfor %} + {% for module in ['charts_artists','charts_tracks','charts_albums','pulse','lastscrobbles','featured'] %} +
+ + + {% include 'startpage_modules/' + module + '.jinja' %} + +
+ {% endfor %} +
- -

Top Tracks

- - {% for r in xcurrent -%} - - {{ r.localisation }} - - {{ "|" if not loop.last }} - {%- endfor %} - -

- - - {% for r in xcurrent -%} - - {%- endfor %} - - -
- - -

Last Scrobbles

- - {% for range in xcurrent %} - {{ range.localisation }} - {{ dbc.get_scrobbles_num({'timerange':range.range}) }} - {% endfor %} -

- - - - - {%- with amountkeys = {"perpage":12,"page":0}, shortTimeDesc=True -%} - {% include 'partials/scrobbles.jinja' %} - {%- endwith -%} - - - -
- - - - - -

Pulse

- - {% for range in xranges -%} - - {{ range.localisation }} - - {{ "|" if not loop.last }} - {%- endfor %} -

- - {% for range in xranges -%} - - {%- endfor %} - - -
{%- endblock %} diff --git a/maloja/web/jinja/startpage_modules/charts_albums.jinja b/maloja/web/jinja/startpage_modules/charts_albums.jinja new file mode 100644 index 0000000..671fe10 --- /dev/null +++ b/maloja/web/jinja/startpage_modules/charts_albums.jinja @@ -0,0 +1,19 @@ +

Top Albums

+ +{% for r in xcurrent -%} + + {{ r.localisation }} + + {{ "|" if not loop.last }} +{%- endfor %} + +

+ + +{% for r in xcurrent -%} + +{%- endfor %} diff --git a/maloja/web/jinja/startpage_modules/charts_artists.jinja b/maloja/web/jinja/startpage_modules/charts_artists.jinja new file mode 100644 index 0000000..0c78c89 --- /dev/null +++ b/maloja/web/jinja/startpage_modules/charts_artists.jinja @@ -0,0 +1,19 @@ +

Top Artists

+ +{% for r in xcurrent -%} + + {{ r.localisation }} + + {{ "|" if not loop.last }} +{%- endfor %} + +

+ + +{% for r in xcurrent -%} + +{%- endfor %} diff --git a/maloja/web/jinja/startpage_modules/charts_tracks.jinja b/maloja/web/jinja/startpage_modules/charts_tracks.jinja new file mode 100644 index 0000000..4ae6e4c --- /dev/null +++ b/maloja/web/jinja/startpage_modules/charts_tracks.jinja @@ -0,0 +1,19 @@ +

Top Tracks

+ +{% for r in xcurrent -%} + + {{ r.localisation }} + + {{ "|" if not loop.last }} +{%- endfor %} + +

+ + +{% for r in xcurrent -%} + +{%- endfor %} diff --git a/maloja/web/jinja/startpage_modules/featured.jinja b/maloja/web/jinja/startpage_modules/featured.jinja new file mode 100644 index 0000000..1c96ea2 --- /dev/null +++ b/maloja/web/jinja/startpage_modules/featured.jinja @@ -0,0 +1,58 @@ +

Featured

+ + +{% set entitytypes = [ + {'identifier':'artist','localisation':"Artist", 'template':"info_artist.jinja", 'filterkeys':{"artist":"Blackpink"} }, + {'identifier':'track','localisation':"Track", 'template':"info_track.jinja", 'filterkeys':{"track": {"artists": ["Red Velvet"], "title": "Russian Roulette"}} }, + {'identifier':'album','localisation':"Album", 'template':"info_album.jinja", 'filterkeys':{"album": {"artists": ["TWICE"], "albumtitle": "The Story Begins"}} } +] %} + + +{% for t in entitytypes -%} + + {{ t.localisation }} + + {{ "|" if not loop.last }} +{%- endfor %} + +


+ + +{% for t in entitytypes -%} + +{%- endfor %} + + + + + diff --git a/maloja/web/jinja/startpage_modules/lastscrobbles.jinja b/maloja/web/jinja/startpage_modules/lastscrobbles.jinja new file mode 100644 index 0000000..ae0da70 --- /dev/null +++ b/maloja/web/jinja/startpage_modules/lastscrobbles.jinja @@ -0,0 +1,15 @@ +

Last Scrobbles

+ +{% for range in xcurrent %} + {{ range.localisation }} + {{ dbc.get_scrobbles_num({'timerange':range.range}) }} +{% endfor %} +

+ + + + + {%- with amountkeys = {"perpage":12,"page":0}, shortTimeDesc=True -%} + {% include 'partials/scrobbles.jinja' %} + {%- endwith -%} + diff --git a/maloja/web/jinja/startpage_modules/pulse.jinja b/maloja/web/jinja/startpage_modules/pulse.jinja new file mode 100644 index 0000000..5efdc00 --- /dev/null +++ b/maloja/web/jinja/startpage_modules/pulse.jinja @@ -0,0 +1,17 @@ +

Pulse

+ +{% for range in xranges -%} + + {{ range.localisation }} + + {{ "|" if not loop.last }} +{%- endfor %} +

+ +{% for range in xranges -%} + +{%- endfor %} diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index 3c838db..95c17c1 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -802,10 +802,12 @@ table.misc td { div.tiles { display: grid; - grid-template-columns: repeat(18, 50px); - grid-template-rows: repeat(6, 50px); + grid-template-columns: repeat(18, calc(100% / 18)); + grid-template-rows: repeat(6, calc(100% / 6)); grid-auto-flow: row dense; + aspect-ratio: 3 / 1; + } div.tiles div { @@ -982,35 +984,3 @@ span.stat_module_pulse, span.stat_module_topartists, span.stat_module_toptracks display: inline-block; vertical-align: top; } - -/* -** -** -** SIDE LIST ON START PAGE -** -** -*/ - - -@media (min-width: 1600px) { -div.sidelist { - position:absolute; - right:0px; - top:0px; - width:40%; - height:100%; - --current-bg-color: var(--base-color-light); /* drag this information through inheritances */ - background-color: var(--current-bg-color); - padding-left:30px; - padding-right:30px; -} -} - -div.sidelist table { - width:100%; - table-layout:fixed; -} - -div.sidelist table.list td.time { - width:17%; -} diff --git a/maloja/web/static/css/startpage.css b/maloja/web/static/css/startpage.css new file mode 100644 index 0000000..2d3fe9b --- /dev/null +++ b/maloja/web/static/css/startpage.css @@ -0,0 +1,49 @@ +div#startpage { + display: grid; + justify-content: center; + + display: fixed; + grid-column-gap: 25px; + grid-row-gap: 25px; +} + + +@media (min-width: 2201px) { + div#startpage { + grid-template-columns: 30vw 30vw 30vw; + grid-template-rows: 45vh 45vh; + + grid-template-areas: + "charts_artists charts_tracks charts_albums" + "lastscrobbles featured pulse"; + } +} + +@media (min-width: 1401px) and (max-width: 2200px) { + div#startpage { + grid-template-columns: 45vw 45vw; + grid-template-rows: 45vh 45vh 45vh; + + grid-template-areas: + "charts_artists lastscrobbles" + "charts_tracks pulse" + "charts_albums featured"; + } +} + +@media (max-width: 1400px) { + div#startpage { + grid-template-columns: 90vw; + + grid-template-areas: + "charts_artists" + "charts_tracks" + "charts_albums" + "lastscrobbles" + "pulse"; + } + + #start_page_module_featured { + display: none; + } +} diff --git a/maloja/web/static/js/rangeselect.js b/maloja/web/static/js/rangeselect.js index f42d789..2561a69 100644 --- a/maloja/web/static/js/rangeselect.js +++ b/maloja/web/static/js/rangeselect.js @@ -2,7 +2,7 @@ localStorage = window.localStorage; function showRange(identifier,unit) { // Make all modules disappear - modules = document.getElementsByClassName("stat_module_" + identifier); + var modules = document.getElementsByClassName("stat_module_" + identifier); for (var i=0;i Date: Fri, 11 Aug 2023 17:16:14 +0200 Subject: [PATCH 4/7] Added featured module to startpage --- maloja/database/__init__.py | 12 ++++++++++++ maloja/web/jinja/startpage_modules/featured.jinja | 10 +++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 8969ea1..974b1cb 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -574,6 +574,18 @@ def album_info(dbconn=None,**keys): } + +### TODO: FIND COOL ALGORITHM TO SELECT FEATURED STUFF +@waitfordb +def get_featured(dbconn=None): + # temporary stand-in + result = { + "artist": get_charts_artists(timerange=alltime())[0]['artist'], + "album": get_charts_albums(timerange=alltime())[0]['album'], + "track": get_charts_tracks(timerange=alltime())[0]['track'] + } + return result + def get_predefined_rulesets(dbconn=None): validchars = "-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" diff --git a/maloja/web/jinja/startpage_modules/featured.jinja b/maloja/web/jinja/startpage_modules/featured.jinja index 1c96ea2..bfc2bcb 100644 --- a/maloja/web/jinja/startpage_modules/featured.jinja +++ b/maloja/web/jinja/startpage_modules/featured.jinja @@ -1,10 +1,13 @@ + +

Featured

+{% set featured = dbc.get_featured() %} {% set entitytypes = [ - {'identifier':'artist','localisation':"Artist", 'template':"info_artist.jinja", 'filterkeys':{"artist":"Blackpink"} }, - {'identifier':'track','localisation':"Track", 'template':"info_track.jinja", 'filterkeys':{"track": {"artists": ["Red Velvet"], "title": "Russian Roulette"}} }, - {'identifier':'album','localisation':"Album", 'template':"info_album.jinja", 'filterkeys':{"album": {"artists": ["TWICE"], "albumtitle": "The Story Begins"}} } + {'identifier':'artist','localisation':"Artist", 'template':"info_artist.jinja", 'filterkeys':{"artist": featured.artist } }, + {'identifier':'track','localisation':"Track", 'template':"info_track.jinja", 'filterkeys':{"track": featured.track } }, + {'identifier':'album','localisation':"Album", 'template':"info_album.jinja", 'filterkeys':{"album": featured.album } } ] %} @@ -21,6 +24,7 @@ {% for t in entitytypes -%} From f189be23098a023da1a88fffaf08b32d5ad6684c Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 11 Aug 2023 17:37:32 +0200 Subject: [PATCH 5/7] Added icons for track association --- maloja/web/jinja/album.jinja | 1 + maloja/web/jinja/artist.jinja | 1 + maloja/web/jinja/icons/add_album.jinja | 6 ++++++ maloja/web/jinja/icons/add_album_confirm.jinja | 5 +++++ maloja/web/jinja/icons/add_artist.jinja | 5 +++++ maloja/web/jinja/icons/add_artist_confirm.jinja | 5 +++++ maloja/web/jinja/track.jinja | 2 ++ 7 files changed, 25 insertions(+) create mode 100644 maloja/web/jinja/icons/add_album.jinja create mode 100644 maloja/web/jinja/icons/add_album_confirm.jinja create mode 100644 maloja/web/jinja/icons/add_artist.jinja create mode 100644 maloja/web/jinja/icons/add_artist_confirm.jinja diff --git a/maloja/web/jinja/album.jinja b/maloja/web/jinja/album.jinja index 6a16da3..b697b07 100644 --- a/maloja/web/jinja/album.jinja +++ b/maloja/web/jinja/album.jinja @@ -23,6 +23,7 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} + {% include 'icons/add_album_confirm.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index 29d8879..ccde8a2 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -33,6 +33,7 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} + {% include 'icons/add_artist_confirm.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/jinja/icons/add_album.jinja b/maloja/web/jinja/icons/add_album.jinja new file mode 100644 index 0000000..1a3d942 --- /dev/null +++ b/maloja/web/jinja/icons/add_album.jinja @@ -0,0 +1,6 @@ +
+ + + + +
diff --git a/maloja/web/jinja/icons/add_album_confirm.jinja b/maloja/web/jinja/icons/add_album_confirm.jinja new file mode 100644 index 0000000..2d50fb2 --- /dev/null +++ b/maloja/web/jinja/icons/add_album_confirm.jinja @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/maloja/web/jinja/icons/add_artist.jinja b/maloja/web/jinja/icons/add_artist.jinja new file mode 100644 index 0000000..a86e973 --- /dev/null +++ b/maloja/web/jinja/icons/add_artist.jinja @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/maloja/web/jinja/icons/add_artist_confirm.jinja b/maloja/web/jinja/icons/add_artist_confirm.jinja new file mode 100644 index 0000000..44bad86 --- /dev/null +++ b/maloja/web/jinja/icons/add_artist_confirm.jinja @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index 3fbc909..cad536b 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -28,6 +28,8 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} + {% include 'icons/add_artist.jinja' %} + {% include 'icons/add_album.jinja' %} {% endif %} {% endblock %} From d645707ff1ccc3ff2d5f9126ddc41129aea6dcaa Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 11 Aug 2023 18:57:27 +0200 Subject: [PATCH 6/7] Implemented client logic for association, GH-227 --- maloja/web/jinja/album.jinja | 4 +- maloja/web/jinja/artist.jinja | 2 +- maloja/web/jinja/icons/add_album.jinja | 2 +- maloja/web/jinja/icons/add_artist.jinja | 2 +- .../web/jinja/icons/association_cancel.jinja | 7 + maloja/web/jinja/icons/association_mark.jinja | 5 + maloja/web/jinja/track.jinja | 4 +- maloja/web/static/js/edit.js | 128 ++++++++++++++++++ 8 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 maloja/web/jinja/icons/association_cancel.jinja create mode 100644 maloja/web/jinja/icons/association_mark.jinja diff --git a/maloja/web/jinja/album.jinja b/maloja/web/jinja/album.jinja index b697b07..3142c9c 100644 --- a/maloja/web/jinja/album.jinja +++ b/maloja/web/jinja/album.jinja @@ -23,7 +23,9 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} - {% include 'icons/add_album_confirm.jinja' %} + {% include 'icons/add_album.jinja' %} + {% include 'icons/association_mark.jinja' %} + {% include 'icons/association_cancel.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index ccde8a2..189005e 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -33,7 +33,7 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} - {% include 'icons/add_artist_confirm.jinja' %} + {% include 'icons/add_artist.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/jinja/icons/add_album.jinja b/maloja/web/jinja/icons/add_album.jinja index 1a3d942..11d2d67 100644 --- a/maloja/web/jinja/icons/add_album.jinja +++ b/maloja/web/jinja/icons/add_album.jinja @@ -1,4 +1,4 @@ -
+
diff --git a/maloja/web/jinja/icons/add_artist.jinja b/maloja/web/jinja/icons/add_artist.jinja index a86e973..07a958f 100644 --- a/maloja/web/jinja/icons/add_artist.jinja +++ b/maloja/web/jinja/icons/add_artist.jinja @@ -1,4 +1,4 @@ -
+
diff --git a/maloja/web/jinja/icons/association_cancel.jinja b/maloja/web/jinja/icons/association_cancel.jinja new file mode 100644 index 0000000..a8d9615 --- /dev/null +++ b/maloja/web/jinja/icons/association_cancel.jinja @@ -0,0 +1,7 @@ +
+ + + + + +
diff --git a/maloja/web/jinja/icons/association_mark.jinja b/maloja/web/jinja/icons/association_mark.jinja new file mode 100644 index 0000000..6b68dae --- /dev/null +++ b/maloja/web/jinja/icons/association_mark.jinja @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index cad536b..f1c084a 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -28,8 +28,8 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} - {% include 'icons/add_artist.jinja' %} - {% include 'icons/add_album.jinja' %} + {% include 'icons/association_mark.jinja' %} + {% include 'icons/association_cancel.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index e25f9c9..c9369b4 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -190,6 +190,8 @@ function doneEditing() { // MERGING function showValidMergeIcons() { + + // merge const lcst = window.sessionStorage; var key = "marked_for_merge_" + entity_type; var current_stored = (lcst.getItem(key) || '').split(","); @@ -218,6 +220,74 @@ function showValidMergeIcons() { } } + // mark for association + if ((entity_type == 'track') || (entity_type == 'album')) { + const lcst = window.sessionStorage; + var key = "marked_for_associate_" + entity_type; + var current_stored = (lcst.getItem(key) || '').split(","); + current_stored = current_stored.filter((x)=>x).map((x)=>parseInt(x)); + + var associationmarkicon = document.getElementById('associationmarkicon'); + var associationcancelicon = document.getElementById('associationcancelicon'); + + associationmarkicon.classList.add('hide'); + associationcancelicon.classList.add('hide'); + + + if (current_stored.length == 0) { + associationmarkicon.classList.remove('hide'); + } + else { + associationcancelicon.classList.remove('hide'); + + if (current_stored.includes(entity_id)) { + + } + else { + associationmarkicon.classList.remove('hide'); + } + } + } + + + + // association confirm + if ((entity_type == 'artist') || (entity_type == 'album')) { + var target_entity_types = {artist:['album','track'], album:['track']}; + var to_associate = {}; + var to_associate_all = []; + for (var target_entity_type of target_entity_types[entity_type]) { + const lcst = window.sessionStorage; + var key = "marked_for_associate_" + target_entity_type; + var current_stored = (lcst.getItem(key) || '').split(","); + to_associate[target_entity_type] = current_stored.filter((x)=>x).map((x)=>parseInt(x)); + to_associate_all = to_associate_all.concat(to_associate[target_entity_type]); + } + + var associateicon = document.getElementById('associate' + entity_type + 'icon'); + + associateicon.classList.add('hide'); + + + if (to_associate_all.length == 0) { + + } + else { + associateicon.classList.remove('hide'); + if (entity_type == 'artist') { + associateicon.title = "Add this artist to " + to_associate['album'].length + " albums and " + to_associate['track'].length + " tracks"; + } + else { + associateicon.title = "Add " + to_associate['track'].length + " tracks to this album"; + } + + } + } + + + + + } @@ -233,6 +303,19 @@ function markForMerge() { showValidMergeIcons(); } +function markForAssociate() { + const lcst = window.sessionStorage; + var key = "marked_for_associate_" + entity_type; + var current_stored = (lcst.getItem(key) || '').split(","); + current_stored = current_stored.filter((x)=>x).map((x)=>parseInt(x)); + current_stored.push(entity_id); + current_stored = [...new Set(current_stored)]; + lcst.setItem(key,current_stored); //this already formats it correctly + var whattoadd = ((entity_type == 'track') ? "Artists or Album" : "Artists") + notify("Marked " + entity_name + " to add " + whattoadd,"Currently " + current_stored.length + " marked!") + showValidMergeIcons(); +} + function merge() { const lcst = window.sessionStorage; var key = "marked_for_merge_" + entity_type; @@ -262,6 +345,44 @@ function merge() { lcst.removeItem(key); } + + +function associate() { + const lcst = window.sessionStorage; + var target_entity_types = {artist:['album','track'], album:['track']}; + for (var target_entity_type of target_entity_types[entity_type]) { + var key = "marked_for_associate_" + target_entity_type; + console.log('get',key); + var current_stored = (lcst.getItem(key) || '').split(","); + current_stored = current_stored.filter((x)=>x).map((x)=>parseInt(x)); + + callback_func = function(req){ + if (req.status == 200) { + //window.location.reload(); + showValidMergeIcons(); + notifyCallback(req); + } + else { + notifyCallback(req); + } + }; + + neo.xhttpreq( + "/apis/mlj_1/associate_" + target_entity_type + "s_to_" + entity_type, + data={ + 'source_ids':current_stored, + 'target_id':entity_id + }, + method="POST", + callback=callback_func, + json=true + ); + + lcst.removeItem(key); + } + +} + function cancelMerge() { const lcst = window.sessionStorage; var key = "marked_for_merge_" + entity_type; @@ -269,3 +390,10 @@ function cancelMerge() { showValidMergeIcons(); notify("Cancelled merge!","") } +function cancelAssociate() { + const lcst = window.sessionStorage; + var key = "marked_for_associate_" + entity_type; + lcst.setItem(key,[]); + showValidMergeIcons(); + notify("Cancelled association!","") +} From 0032d0b70a1d68f471bae3989f618dff77d3ea0a Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 11 Aug 2023 19:46:27 +0200 Subject: [PATCH 7/7] Implemented server logic for association, fix GH-227 --- maloja/apis/native_v1.py | 34 +++++++++++++++++++++ maloja/database/__init__.py | 37 +++++++++++++++++++++++ maloja/database/sqldb.py | 35 ++++++++++++++++++++- maloja/web/static/css/maloja.css | 2 +- maloja/web/static/js/edit.js | 52 +++++++++++++++++++------------- 5 files changed, 137 insertions(+), 23 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 0975bf3..31e0bc9 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -767,6 +767,40 @@ def merge_artists(target_id,source_ids): "status":"success" } +@api.post("associate_albums_to_artist") +@authenticated_function(api=True) +@catch_exceptions +def associate_albums_to_artist(target_id,source_ids): + result = database.associate_albums_to_artist(target_id,source_ids) + if result: + return { + "status":"success", + "desc":f"{result['target']} was added as album artist of {', '.join(src['albumtitle'] for src in result['sources'])}" + } + +@api.post("associate_tracks_to_artist") +@authenticated_function(api=True) +@catch_exceptions +def associate_tracks_to_artist(target_id,source_ids): + result = database.associate_tracks_to_artist(target_id,source_ids) + if result: + return { + "status":"success", + "desc":f"{result['target']} was added as artist for {', '.join(src['title'] for src in result['sources'])}" + } + +@api.post("associate_tracks_to_album") +@authenticated_function(api=True) +@catch_exceptions +def associate_tracks_to_album(target_id,source_ids): + result = database.associate_tracks_to_album(target_id,source_ids) + if result: + return { + "status":"success", + "desc":f"{', '.join(src['title'] for src in result['sources'])} were added to {result['target']['albumtitle']}" + } + + @api.post("reparse_scrobble") @authenticated_function(api=True) @catch_exceptions diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 974b1cb..aa57c4e 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -265,6 +265,43 @@ def merge_albums(target_id,source_ids): +@waitfordb +def associate_albums_to_artist(target_id,source_ids): + sources = [sqldb.get_album(id) for id in source_ids] + target = sqldb.get_artist(target_id) + log(f"Adding {sources} into {target}") + sqldb.add_artists_to_albums(artist_ids=[target_id],album_ids=source_ids) + result = {'sources':sources,'target':target} + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() + + return result + +@waitfordb +def associate_tracks_to_artist(target_id,source_ids): + sources = [sqldb.get_track(id) for id in source_ids] + target = sqldb.get_artist(target_id) + log(f"Adding {sources} into {target}") + sqldb.add_artists_to_tracks(artist_ids=[target_id],track_ids=source_ids) + result = {'sources':sources,'target':target} + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() + + return result + +@waitfordb +def associate_tracks_to_album(target_id,source_ids): + sources = [sqldb.get_track(id) for id in source_ids] + target = sqldb.get_album(target_id) + log(f"Adding {sources} into {target}") + sqldb.add_tracks_to_albums({src:target_id for src in source_ids}) + result = {'sources':sources,'target':target} + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() + + return result + + @waitfordb def get_scrobbles(dbconn=None,**keys): diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 5be84e6..ca98479 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -555,7 +555,7 @@ def edit_scrobble(scrobble_id,scrobbleupdatedict,dbconn=None): dbconn.execute(op) - +# edit function only for primary db information (not linked fields) @connection_provider def edit_artist(id,artistupdatedict,dbconn=None): @@ -578,6 +578,7 @@ def edit_artist(id,artistupdatedict,dbconn=None): return True +# edit function only for primary db information (not linked fields) @connection_provider def edit_track(id,trackupdatedict,dbconn=None): @@ -600,6 +601,7 @@ def edit_track(id,trackupdatedict,dbconn=None): return True +# edit function only for primary db information (not linked fields) @connection_provider def edit_album(id,albumupdatedict,dbconn=None): @@ -623,6 +625,37 @@ def edit_album(id,albumupdatedict,dbconn=None): return True +### Edit associations + +@connection_provider +def add_artists_to_tracks(track_ids,artist_ids,dbconn=None): + + op = DB['trackartists'].insert().values([ + {'track_id':track_id,'artist_id':artist_id} + for track_id in track_ids for artist_id in artist_ids + ]) + + result = dbconn.execute(op) + clean_db(dbconn=dbconn) + + return True + + +@connection_provider +def add_artists_to_albums(album_ids,artist_ids,dbconn=None): + + op = DB['albumartists'].insert().values([ + {'album_id':album_id,'artist_id':artist_id} + for album_id in album_ids for artist_id in artist_ids + ]) + + result = dbconn.execute(op) + clean_db(dbconn=dbconn) + + return True + + + ### Merge @connection_provider diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index 95c17c1..f46bc1e 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -209,7 +209,7 @@ div#notification_area { div#notification_area div.notification { background-color:white; width:400px; - height:50px; + min-height:50px; margin-bottom:7px; padding:9px; opacity:0.4; diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index c9369b4..501ae7b 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -247,6 +247,13 @@ function showValidMergeIcons() { associationmarkicon.classList.remove('hide'); } } + + if (entity_type == 'track') { + associationmarkicon.title = "Mark this track to add to album or add artist"; + } + else { + associationmarkicon.title = "Mark this album to add artist"; + } } @@ -356,29 +363,32 @@ function associate() { var current_stored = (lcst.getItem(key) || '').split(","); current_stored = current_stored.filter((x)=>x).map((x)=>parseInt(x)); - callback_func = function(req){ - if (req.status == 200) { - //window.location.reload(); - showValidMergeIcons(); - notifyCallback(req); - } - else { - notifyCallback(req); - } - }; + if (current_stored.length != 0) { + callback_func = function(req){ + if (req.status == 200) { + //window.location.reload(); + showValidMergeIcons(); + notifyCallback(req); + } + else { + notifyCallback(req); + } + }; - neo.xhttpreq( - "/apis/mlj_1/associate_" + target_entity_type + "s_to_" + entity_type, - data={ - 'source_ids':current_stored, - 'target_id':entity_id - }, - method="POST", - callback=callback_func, - json=true - ); + neo.xhttpreq( + "/apis/mlj_1/associate_" + target_entity_type + "s_to_" + entity_type, + data={ + 'source_ids':current_stored, + 'target_id':entity_id + }, + method="POST", + callback=callback_func, + json=true + ); + + lcst.removeItem(key); + } - lcst.removeItem(key); } }