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); } }