New DB Schema

Rearrange DB Schema for Album Centric Plan
pull/6/head
Qstick 7 years ago
parent db62c15c17
commit 0f3c355381

@ -71,7 +71,7 @@ namespace NzbDrone.Api.Music
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace()); PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace()); PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
PostValidator.RuleFor(s => s.SpotifyId).NotEqual("").SetValidator(artistExistsValidator); PostValidator.RuleFor(s => s.ForeignArtistId).NotEqual("").SetValidator(artistExistsValidator);
PutValidator.RuleFor(s => s.Path).IsValidPath(); PutValidator.RuleFor(s => s.Path).IsValidPath();
} }

@ -18,8 +18,8 @@ namespace NzbDrone.Api.Music
//View Only //View Only
public string ArtistName { get; set; } public string Name { get; set; }
public string SpotifyId { get; set; } public string ForeignArtistId { get; set; }
public string Overview { get; set; } public string Overview { get; set; }
public int AlbumCount public int AlbumCount
@ -59,7 +59,7 @@ namespace NzbDrone.Api.Music
public DateTime Added { get; set; } public DateTime Added { get; set; }
public AddSeriesOptions AddOptions { get; set; } public AddSeriesOptions AddOptions { get; set; }
public Ratings Ratings { get; set; } public Ratings Ratings { get; set; }
public string ArtistSlug { get; internal set; } public string NameSlug { get; set; }
} }
public static class ArtistResourceMapper public static class ArtistResourceMapper
@ -72,7 +72,7 @@ namespace NzbDrone.Api.Music
{ {
Id = model.Id, Id = model.Id,
ArtistName = model.ArtistName, Name = model.Name,
//AlternateTitles //AlternateTitles
//SortTitle = resource.SortTitle, //SortTitle = resource.SortTitle,
@ -94,7 +94,6 @@ namespace NzbDrone.Api.Music
Path = model.Path, Path = model.Path,
ProfileId = model.ProfileId, ProfileId = model.ProfileId,
ArtistFolder = model.ArtistFolder,
Monitored = model.Monitored, Monitored = model.Monitored,
//UseSceneNumbering = resource.UseSceneNumbering, //UseSceneNumbering = resource.UseSceneNumbering,
@ -105,8 +104,8 @@ namespace NzbDrone.Api.Music
//FirstAired = resource.FirstAired, //FirstAired = resource.FirstAired,
//LastInfoSync = resource.LastInfoSync, //LastInfoSync = resource.LastInfoSync,
//SeriesType = resource.SeriesType, //SeriesType = resource.SeriesType,
SpotifyId = model.SpotifyId, ForeignArtistId = model.ForeignArtistId,
ArtistSlug = model.ArtistSlug, NameSlug = model.NameSlug,
RootFolderPath = model.RootFolderPath, RootFolderPath = model.RootFolderPath,
Genres = model.Genres, Genres = model.Genres,
@ -125,7 +124,7 @@ namespace NzbDrone.Api.Music
{ {
Id = resource.Id, Id = resource.Id,
ArtistName = resource.ArtistName, Name = resource.Name,
//AlternateTitles //AlternateTitles
//SortTitle = resource.SortTitle, //SortTitle = resource.SortTitle,
@ -147,11 +146,10 @@ namespace NzbDrone.Api.Music
Path = resource.Path, Path = resource.Path,
ProfileId = resource.ProfileId, ProfileId = resource.ProfileId,
ArtistFolder = resource.ArtistFolder,
Monitored = resource.Monitored, Monitored = resource.Monitored,
//LastInfoSync = resource.LastInfoSync, //LastInfoSync = resource.LastInfoSync,
SpotifyId = resource.SpotifyId, ForeignArtistId = resource.ForeignArtistId,
ArtistSlug = resource.ArtistSlug, NameSlug = resource.NameSlug,
RootFolderPath = resource.RootFolderPath, RootFolderPath = resource.RootFolderPath,
Genres = resource.Genres, Genres = resource.Genres,

@ -12,64 +12,91 @@ namespace NzbDrone.Core.Datastore.Migration
{ {
protected override void MainDbUpgrade() protected override void MainDbUpgrade()
{ {
Create.TableForModel("Artist") Create.TableForModel("Artists")
.WithColumn("SpotifyId").AsString().Nullable().Unique() .WithColumn("ForeignArtistId").AsString().Unique()
.WithColumn("ArtistName").AsString().Unique() .WithColumn("MBId").AsString().Nullable()
.WithColumn("ArtistSlug").AsString().Nullable() //.Unique() .WithColumn("AMId").AsString().Nullable()
.WithColumn("CleanTitle").AsString().Nullable() // Do we need this? .WithColumn("TADBId").AsInt32().Nullable()
.WithColumn("Monitored").AsBoolean() .WithColumn("DiscogsId").AsInt32().Nullable()
.WithColumn("Name").AsString()
.WithColumn("NameSlug").AsString().Nullable().Unique()
.WithColumn("CleanName").AsString().Indexed()
.WithColumn("Status").AsInt32()
.WithColumn("Overview").AsString().Nullable() .WithColumn("Overview").AsString().Nullable()
.WithColumn("AlbumFolder").AsBoolean().Nullable() .WithColumn("Images").AsString()
.WithColumn("ArtistFolder").AsBoolean().Nullable() .WithColumn("Path").AsString().Indexed()
.WithColumn("Monitored").AsBoolean()
.WithColumn("AlbumFolder").AsBoolean()
.WithColumn("LastInfoSync").AsDateTime().Nullable() .WithColumn("LastInfoSync").AsDateTime().Nullable()
.WithColumn("LastDiskSync").AsDateTime().Nullable() .WithColumn("LastDiskSync").AsDateTime().Nullable()
.WithColumn("Status").AsInt32().Nullable() .WithColumn("DateFormed").AsDateTime().Nullable()
.WithColumn("Path").AsString() .WithColumn("Members").AsString().Nullable()
.WithColumn("Images").AsString().Nullable() .WithColumn("Ratings").AsString().Nullable()
.WithColumn("QualityProfileId").AsInt32().Nullable()
.WithColumn("RootFolderPath").AsString().Nullable()
.WithColumn("Added").AsDateTime().Nullable()
.WithColumn("ProfileId").AsInt32().Nullable() // This is either ProfileId or Profile
.WithColumn("Genres").AsString().Nullable() .WithColumn("Genres").AsString().Nullable()
.WithColumn("Albums").AsString().Nullable() .WithColumn("SortName").AsString().Nullable()
.WithColumn("ProfileId").AsInt32().Nullable()
.WithColumn("Tags").AsString().Nullable() .WithColumn("Tags").AsString().Nullable()
.WithColumn("AddOptions").AsString().Nullable() .WithColumn("Added").AsDateTime().Nullable()
; .WithColumn("AddOptions").AsString().Nullable();
Create.TableForModel("Albums") Create.TableForModel("Albums")
.WithColumn("AlbumId").AsString().Unique() .WithColumn("ForeignArtistId").AsString().Unique()
.WithColumn("ArtistId").AsInt32() // Should this be artistId (string) .WithColumn("ArtistId").AsInt32()
.WithColumn("MBId").AsString().Indexed()
.WithColumn("AMId").AsString().Nullable()
.WithColumn("TADBId").AsInt32().Indexed()
.WithColumn("DiscogsId").AsInt32().Nullable()
.WithColumn("Title").AsString() .WithColumn("Title").AsString()
.WithColumn("Year").AsInt32() .WithColumn("TitleSlug").AsString().Nullable().Unique()
.WithColumn("Image").AsInt32() .WithColumn("CleanTitle").AsString().Indexed()
.WithColumn("TrackCount").AsInt32() .WithColumn("Status").AsInt32()
.WithColumn("DiscCount").AsInt32() .WithColumn("Overview").AsString().Nullable()
.WithColumn("Images").AsString()
.WithColumn("Path").AsString().Indexed()
.WithColumn("Monitored").AsBoolean() .WithColumn("Monitored").AsBoolean()
.WithColumn("Overview").AsString(); .WithColumn("LastInfoSync").AsDateTime().Nullable()
.WithColumn("LastDiskSync").AsDateTime().Nullable()
.WithColumn("ReleaseDate").AsDateTime().Nullable()
.WithColumn("Ratings").AsString().Nullable()
.WithColumn("Genres").AsString().Nullable()
.WithColumn("Label").AsString().Nullable()
.WithColumn("SortTitle").AsString().Nullable()
.WithColumn("ProfileId").AsInt32().Nullable()
.WithColumn("Tags").AsString().Nullable()
.WithColumn("Added").AsDateTime().Nullable()
.WithColumn("AlbumType").AsString()
.WithColumn("AddOptions").AsString().Nullable();
Create.TableForModel("Tracks") Create.TableForModel("Tracks")
.WithColumn("SpotifyTrackId").AsString().Nullable() // This shouldn't be nullable, but TrackRepository won't behave. Someone please fix this. .WithColumn("ArtistId").AsInt32().Indexed()
.WithColumn("AlbumId").AsString() .WithColumn("AlbumId").AsInt32()
.WithColumn("ArtistId").AsString() // This may be a list of Ids in future for compilations .WithColumn("MBId").AsString().Indexed()
.WithColumn("ArtistSpotifyId").AsString()
.WithColumn("Compilation").AsBoolean()
.WithColumn("TrackNumber").AsInt32() .WithColumn("TrackNumber").AsInt32()
.WithColumn("Title").AsString().Nullable() .WithColumn("Title").AsString().Nullable()
.WithColumn("Ignored").AsBoolean().Nullable() .WithColumn("Explicit").AsBoolean()
.WithColumn("Explict").AsBoolean() .WithColumn("DiscNumber").AsInt32().Nullable()
.WithColumn("TrackFileId").AsInt32().Nullable().Indexed()
.WithColumn("Monitored").AsBoolean() .WithColumn("Monitored").AsBoolean()
.WithColumn("TrackFileId").AsInt32().Nullable() .WithColumn("Ratings").AsString().Nullable();
.WithColumn("ReleaseDate").AsDateTime().Nullable();
Create.Index().OnTable("Tracks").OnColumn("ArtistId").Ascending()
.OnColumn("AlbumId").Ascending()
.OnColumn("TrackNumber").Ascending();
Create.TableForModel("TrackFiles") Create.TableForModel("TrackFiles")
.WithColumn("ArtistId").AsInt32() .WithColumn("ArtistId").AsInt32().Indexed()
.WithColumn("Path").AsString().Unique() .WithColumn("AlbumId").AsInt32().Indexed()
.WithColumn("Quality").AsString() .WithColumn("Quality").AsString()
.WithColumn("Size").AsInt64() .WithColumn("Size").AsInt64()
.WithColumn("DateAdded").AsDateTime() .WithColumn("DateAdded").AsDateTime()
.WithColumn("AlbumId").AsInt32(); // How does this impact stand alone tracks? .WithColumn("SceneName").AsString().Nullable()
.WithColumn("ReleaseGroup").AsString().Nullable()
.WithColumn("MediaInfo").AsString().Nullable()
.WithColumn("RelativePath").AsString().Nullable();
Alter.Table("NamingConfig")
.AddColumn("ArtistFolderFormat").AsString().Nullable()
.AddColumn("AlbumFolderFormat").AsString().Nullable();
} }
} }

@ -1,15 +0,0 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(112)]
public class add_music_fields_to_namingconfig : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("NamingConfig").AddColumn("ArtistFolderFormat").AsAnsiString().Nullable();
Alter.Table("NamingConfig").AddColumn("AlbumFolderFormat").AsAnsiString().Nullable();
}
}
}

@ -92,11 +92,13 @@ namespace NzbDrone.Core.Datastore
.Relationship() .Relationship()
.HasOne(episode => episode.EpisodeFile, episode => episode.EpisodeFileId); .HasOne(episode => episode.EpisodeFile, episode => episode.EpisodeFileId);
Mapper.Entity<Artist>().RegisterModel("Artist") Mapper.Entity<Artist>().RegisterModel("Artists")
.Ignore(s => s.RootFolderPath) .Ignore(s => s.RootFolderPath)
.Relationship() .Relationship()
.HasOne(a => a.Profile, a => a.ProfileId); .HasOne(a => a.Profile, a => a.ProfileId);
Mapper.Entity<Album>().RegisterModel("Album");
Mapper.Entity<TrackFile>().RegisterModel("TrackFiles") Mapper.Entity<TrackFile>().RegisterModel("TrackFiles")
.Ignore(f => f.Path) .Ignore(f => f.Path)
.Relationships.AutoMapICollectionOrComplexProperties() .Relationships.AutoMapICollectionOrComplexProperties()

@ -0,0 +1,17 @@
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download
{
public class AlbumGrabbedEvent : IEvent
{
public RemoteAlbum Album { get; private set; }
public string DownloadClient { get; set; }
public string DownloadId { get; set; }
public AlbumGrabbedEvent(RemoteAlbum album)
{
Album = album;
}
}
}

@ -5,9 +5,9 @@ using System.Text;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{ {
public class AlbumInfoResource public class AlbumResource
{ {
public AlbumInfoResource() public AlbumResource()
{ {
} }

@ -5,47 +5,20 @@ using System.Text;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{ {
public class AristResultResource
{
public AristResultResource()
{
}
public List<ArtistInfoResource> Items { get; set; }
public int Count { get; set; }
}
public class AlbumResultResource
{
public AlbumResultResource()
{
}
public List<AlbumInfoResource> Items { get; set; }
public int Count { get; set; }
}
public class TrackResultResource
{
public TrackResultResource()
{
}
public List<TrackInfoResource> Items { get; set; }
public int Count { get; set; }
}
public class ArtistResource public class ArtistResource
{ {
public ArtistResource() public ArtistResource() {
{ Albums = new List<AlbumResource>();
Tracks = new List<TrackResource>();
} }
public AristResultResource Artists { get; set; } public List<string> Genres { get; set; }
public AristResultResource Albums { get; set; } public string AristUrl { get; set; }
public string Overview { get; set; }
public string Id { get; set; }
public List<ImageResource> Images { get; set; }
public string ArtistName { get; set; }
public List<AlbumResource> Albums { get; set; }
public List<TrackResource> Tracks { get; set; }
} }
} }

@ -5,9 +5,9 @@ using System.Text;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{ {
public class TrackInfoResource public class TrackResource
{ {
public TrackInfoResource() public TrackResource()
{ {
} }

@ -108,92 +108,96 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
} }
// It is safe to assume an id will only return one Artist back // It is safe to assume an id will only return one Artist back
Artist artist = new Artist(); var albums = httpResponse.Resource.Albums.Select(MapAlbum);
artist.ArtistName = httpResponse.Resource.Artists.Items[0].ArtistName; var tracks = httpResponse.Resource.Tracks.Select(MapTrack);
artist.SpotifyId = httpResponse.Resource.Artists.Items[0].Id; var artist = MapArtist(httpResponse.Resource);
artist.Genres = httpResponse.Resource.Artists.Items[0].Genres;
var albumRet = MapAlbums(artist);
artist = albumRet.Item1;
return new Tuple<Artist, List<Track>>(albumRet.Item1, albumRet.Item2);
}
private Tuple<Artist, List<Track>> MapAlbums(Artist artist)
{
// Find all albums for the artist and all tracks for said album
///v1/artists/{id}/albums
var httpRequest = _requestBuilder.Create()
.SetSegment("route", "artists/" + artist.SpotifyId + "/albums")
.Build();
httpRequest.AllowAutoRedirect = true;
httpRequest.SuppressHttpError = true;
var httpResponse = _httpClient.Get<AlbumResultResource>(httpRequest); //artist.Name = httpResponse.Resource.Artists.Items[0].ArtistName;
if (httpResponse.HasHttpError) //artist.ForeignArtistId = httpResponse.Resource.Artists.Items[0].Id;
{ //artist.Genres = httpResponse.Resource.Artists.Items[0].Genres;
throw new HttpException(httpRequest, httpResponse);
}
List<Track> masterTracks = new List<Track>();
List<Album> albums = new List<Album>();
foreach(var albumResource in httpResponse.Resource.Items)
{
Album album = new Album();
album.AlbumId = albumResource.Id;
album.Title = albumResource.AlbumName;
album.ArtworkUrl = albumResource.Images.Count > 0 ? albumResource.Images[0].Url : "";
album.Tracks = MapTracksToAlbum(album);
masterTracks.InsertRange(masterTracks.Count, album.Tracks);
albums.Add(album);
}
// TODO: We now need to get all tracks for each album //var albumRet = MapAlbums(artist);
//artist = albumRet.Item1;
artist.Albums = albums; return new Tuple<Artist, List<Track>>(artist, tracks.ToList());
return new Tuple<Artist, List<Track>>(artist, masterTracks);
} }
private List<Track> MapTracksToAlbum(Album album)
{
var httpRequest = _requestBuilder.Create()
.SetSegment("route", "albums/" + album.AlbumId + "/tracks")
.Build();
httpRequest.AllowAutoRedirect = true;
httpRequest.SuppressHttpError = true;
var httpResponse = _httpClient.Get<TrackResultResource>(httpRequest);
if (httpResponse.HasHttpError) //private Tuple<Artist, List<Track>> MapAlbums(Artist artist)
{ //{
throw new HttpException(httpRequest, httpResponse);
}
List<Track> tracks = new List<Track>(); // // Find all albums for the artist and all tracks for said album
foreach(var trackResource in httpResponse.Resource.Items) // ///v1/artists/{id}/albums
{ // var httpRequest = _requestBuilder.Create()
Track track = new Track(); // .SetSegment("route", "artists/" + artist.ForeignArtistId + "/albums")
track.AlbumId = album.AlbumId; // .Build();
//track.Album = album; // This will cause infinite loop when trying to serialize. // httpRequest.AllowAutoRedirect = true;
// TODO: Implement more track mapping // httpRequest.SuppressHttpError = true;
//track.Artist = trackResource.Artists
//track.ArtistId = album. // var httpResponse = _httpClient.Get<AlbumResultResource>(httpRequest);
track.SpotifyTrackId = trackResource.Id;
track.ArtistSpotifyId = trackResource.Artists.Count > 0 ? trackResource.Artists[0].Id : null; // if (httpResponse.HasHttpError)
track.Explict = trackResource.Explicit; // {
track.Compilation = trackResource.Artists.Count > 1; // throw new HttpException(httpRequest, httpResponse);
track.TrackNumber = trackResource.TrackNumber; // }
track.Title = trackResource.TrackName;
tracks.Add(track); // List<Track> masterTracks = new List<Track>();
} // List<Album> albums = new List<Album>();
// foreach(var albumResource in httpResponse.Resource.Items)
// {
// Album album = new Album();
// album.AlbumId = albumResource.Id;
// album.Title = albumResource.AlbumName;
// album.ArtworkUrl = albumResource.Images.Count > 0 ? albumResource.Images[0].Url : "";
// album.Tracks = MapTracksToAlbum(album);
// masterTracks.InsertRange(masterTracks.Count, album.Tracks);
// albums.Add(album);
// }
// // TODO: We now need to get all tracks for each album
// artist.Albums = albums;
// return new Tuple<Artist, List<Track>>(artist, masterTracks);
//}
return tracks; //private List<Track> MapTracksToAlbum(Album album)
} //{
// var httpRequest = _requestBuilder.Create()
// .SetSegment("route", "albums/" + album.AlbumId + "/tracks")
// .Build();
// httpRequest.AllowAutoRedirect = true;
// httpRequest.SuppressHttpError = true;
// var httpResponse = _httpClient.Get<TrackResultResource>(httpRequest);
// if (httpResponse.HasHttpError)
// {
// throw new HttpException(httpRequest, httpResponse);
// }
// List<Track> tracks = new List<Track>();
// foreach(var trackResource in httpResponse.Resource.Items)
// {
// Track track = new Track();
// track.AlbumId = album.AlbumId;
// //track.Album = album; // This will cause infinite loop when trying to serialize.
// // TODO: Implement more track mapping
// //track.Artist = trackResource.Artists
// //track.ArtistId = album.
// track.SpotifyTrackId = trackResource.Id;
// track.ArtistSpotifyId = trackResource.Artists.Count > 0 ? trackResource.Artists[0].Id : null;
// track.Explict = trackResource.Explicit;
// track.Compilation = trackResource.Artists.Count > 1;
// track.TrackNumber = trackResource.TrackNumber;
// track.Title = trackResource.TrackName;
// tracks.Add(track);
// }
// return tracks;
//}
public List<Artist> SearchForNewArtist(string title) public List<Artist> SearchForNewArtist(string title)
@ -230,12 +234,26 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
var httpResponse = _httpClient.Get<ArtistResource>(httpRequest); var httpResponse = _httpClient.Get<List<ArtistResource>>(httpRequest);
return httpResponse.Resource.SelectList(MapArtist);
//List<Artist> artists = MapArtists(httpResponse.Resource);
//List<Artist> artists = new List<Artist>();
//foreach (var artistResource in httpResponse.Resource.Artists.Items)
//{
// Artist artist = new Artist();
// artist.Name = artistResource.ArtistName;
// artist.ForeignArtistId = artistResource.Id; // TODO: Rename spotifyId to LidarrId
// artist.Genres = artistResource.Genres;
// artist.NameSlug = Parser.Parser.CleanArtistTitle(artist.Name);
// artist.CleanName = Parser.Parser.CleanArtistTitle(artist.Name);
//artist.Images = artistResource.Images;
// artists.Add(artist);
//}
List<Artist> artists = MapArtists(httpResponse.Resource);
return artists; //return artists;
} }
catch (HttpException) catch (HttpException)
{ {
@ -248,27 +266,37 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
} }
} }
private List<Artist> MapArtists(ArtistResource resource) private static Album MapAlbum(AlbumResource resource)
{
Album album = new Album();
return album;
}
private static Track MapTrack(TrackResource resource)
{
Track track = new Track();
return track;
}
private static Artist MapArtist(ArtistResource resource)
{ {
Artist artist = new Artist();
artist.Name = resource.ArtistName;
artist.ForeignArtistId = resource.Id; // TODO: Rename spotifyId to LidarrId
artist.Genres = resource.Genres;
artist.Overview = resource.Overview;
artist.NameSlug = Parser.Parser.CleanArtistTitle(artist.Name);
artist.CleanName = Parser.Parser.CleanArtistTitle(artist.Name);
//artist.Images = resource.Artists.Items[0].Images;
List<Artist> artists = new List<Artist>();
foreach(var artistResource in resource.Artists.Items)
{
Artist artist = new Artist();
artist.ArtistName = artistResource.ArtistName;
artist.SpotifyId = artistResource.Id; // TODO: Rename spotifyId to LidarrId
artist.Genres = artistResource.Genres;
artist.ArtistSlug = Parser.Parser.CleanArtistTitle(artist.ArtistName);
//artist.Images = artistResource.Images;
artists.Add(artist);
}
// Maybe? Get all the albums for said artist // Maybe? Get all the albums for said artist
return artists; return artist;
} }
//private Album MapAlbum(AlbumResource albumQuery) //private Album MapAlbum(AlbumResource albumQuery)

@ -48,11 +48,11 @@ namespace NzbDrone.Core.Music
if (string.IsNullOrWhiteSpace(newArtist.Path)) if (string.IsNullOrWhiteSpace(newArtist.Path))
{ {
var folderName = newArtist.ArtistName;// TODO: _fileNameBuilder.GetArtistFolder(newArtist); var folderName = newArtist.Name;// TODO: _fileNameBuilder.GetArtistFolder(newArtist);
newArtist.Path = Path.Combine(newArtist.RootFolderPath, folderName); newArtist.Path = Path.Combine(newArtist.RootFolderPath, folderName);
} }
newArtist.CleanTitle = newArtist.ArtistName.CleanSeriesTitle(); newArtist.CleanName = newArtist.Name.CleanSeriesTitle();
//newArtist.SortTitle = ArtistNameNormalizer.Normalize(newArtist.ArtistName, newArtist.ItunesId); // There is no Sort Title //newArtist.SortTitle = ArtistNameNormalizer.Normalize(newArtist.ArtistName, newArtist.ItunesId); // There is no Sort Title
newArtist.Added = DateTime.UtcNow; newArtist.Added = DateTime.UtcNow;
@ -75,15 +75,15 @@ namespace NzbDrone.Core.Music
try try
{ {
tuple = _artistInfo.GetArtistInfo(newArtist.SpotifyId); tuple = _artistInfo.GetArtistInfo(newArtist.ForeignArtistId);
} }
catch (ArtistNotFoundException) catch (ArtistNotFoundException)
{ {
_logger.Error("SpotifyId {1} was not found, it may have been removed from Spotify.", newArtist.SpotifyId); _logger.Error("SpotifyId {1} was not found, it may have been removed from Spotify.", newArtist.ForeignArtistId);
throw new ValidationException(new List<ValidationFailure> throw new ValidationException(new List<ValidationFailure>
{ {
new ValidationFailure("SpotifyId", "An artist with this ID was not found", newArtist.SpotifyId) new ValidationFailure("SpotifyId", "An artist with this ID was not found", newArtist.ForeignArtistId)
}); });
} }

@ -28,7 +28,7 @@ namespace NzbDrone.Core.Music
.SetValidator(droneFactoryValidator) .SetValidator(droneFactoryValidator)
.SetValidator(seriesAncestorValidator); .SetValidator(seriesAncestorValidator);
RuleFor(c => c.ArtistSlug).SetValidator(artistTitleSlugValidator);// TODO: Check if we are going to use a slug or artistName RuleFor(c => c.NameSlug).SetValidator(artistTitleSlugValidator);// TODO: Check if we are going to use a slug or artistName
} }
} }
} }

@ -7,7 +7,7 @@ using System.Text;
namespace NzbDrone.Core.Music namespace NzbDrone.Core.Music
{ {
public class Album : IEmbeddedDocument public class Album : ModelBase
{ {
public Album() public Album()
{ {

@ -22,21 +22,19 @@ namespace NzbDrone.Core.Music
} }
public string SpotifyId { get; set; } public string ForeignArtistId { get; set; }
public string ArtistName { get; set; } public string Name { get; set; }
public string ArtistSlug { get; set; } public string NameSlug { get; set; }
public string CleanTitle { get; set; } public string CleanName { get; set; }
public string Overview { get; set; } public string Overview { get; set; }
public bool Monitored { get; set; } public bool Monitored { get; set; }
public bool AlbumFolder { get; set; } public bool AlbumFolder { get; set; }
public bool ArtistFolder { get; set; }
public DateTime? LastInfoSync { get; set; } public DateTime? LastInfoSync { get; set; }
public DateTime? LastDiskSync { get; set; } public DateTime? LastDiskSync { get; set; }
public int Status { get; set; } // TODO: Figure out what this is, do we need it? public int Status { get; set; } // TODO: Figure out what this is, do we need it?
public string Path { get; set; } public string Path { get; set; }
public List<MediaCover.MediaCover> Images { get; set; } public List<MediaCover.MediaCover> Images { get; set; }
public List<string> Genres { get; set; } public List<string> Genres { get; set; }
public int QualityProfileId { get; set; }
public string RootFolderPath { get; set; } public string RootFolderPath { get; set; }
public DateTime Added { get; set; } public DateTime Added { get; set; }
public LazyLoaded<Profile> Profile { get; set; } public LazyLoaded<Profile> Profile { get; set; }
@ -47,16 +45,16 @@ namespace NzbDrone.Core.Music
public override string ToString() public override string ToString()
{ {
return string.Format("[{0}][{1}]", SpotifyId, ArtistName.NullSafe()); return string.Format("[{0}][{1}]", ForeignArtistId, Name.NullSafe());
} }
public void ApplyChanges(Artist otherArtist) public void ApplyChanges(Artist otherArtist)
{ {
SpotifyId = otherArtist.SpotifyId; ForeignArtistId = otherArtist.ForeignArtistId;
ArtistName = otherArtist.ArtistName; Name = otherArtist.Name;
ArtistSlug = otherArtist.ArtistSlug; NameSlug = otherArtist.NameSlug;
CleanTitle = otherArtist.CleanTitle; CleanName = otherArtist.CleanName;
Monitored = otherArtist.Monitored; Monitored = otherArtist.Monitored;
AlbumFolder = otherArtist.AlbumFolder; AlbumFolder = otherArtist.AlbumFolder;
LastInfoSync = otherArtist.LastInfoSync; LastInfoSync = otherArtist.LastInfoSync;
@ -69,7 +67,6 @@ namespace NzbDrone.Core.Music
ProfileId = otherArtist.ProfileId; ProfileId = otherArtist.ProfileId;
Albums = otherArtist.Albums; Albums = otherArtist.Albums;
Tags = otherArtist.Tags; Tags = otherArtist.Tags;
ArtistFolder = otherArtist.ArtistFolder;
AddOptions = otherArtist.AddOptions; AddOptions = otherArtist.AddOptions;
Albums = otherArtist.Albums; Albums = otherArtist.Albums;

@ -24,16 +24,16 @@ namespace NzbDrone.Core.Music
return Query.Where(c => c.Path == path).Any(); return Query.Where(c => c.Path == path).Any();
} }
public Artist FindById(string spotifyId) public Artist FindById(string foreignArtistId)
{ {
return Query.Where(s => s.SpotifyId == spotifyId).SingleOrDefault(); return Query.Where(s => s.ForeignArtistId == foreignArtistId).SingleOrDefault();
} }
public Artist FindByName(string cleanName) public Artist FindByName(string cleanName)
{ {
cleanName = cleanName.ToLowerInvariant(); cleanName = cleanName.ToLowerInvariant();
return Query.Where(s => s.CleanTitle == cleanName) return Query.Where(s => s.CleanName == cleanName)
.SingleOrDefault(); .SingleOrDefault();
} }
} }

@ -114,7 +114,7 @@ namespace NzbDrone.Core.Music
if (storedAlbum != null && album.Monitored != storedAlbum.Monitored) if (storedAlbum != null && album.Monitored != storedAlbum.Monitored)
{ {
_trackService.SetTrackMonitoredByAlbum(artist.SpotifyId, album.AlbumId, album.Monitored); _trackService.SetTrackMonitoredByAlbum(artist.ForeignArtistId, album.AlbumId, album.Monitored);
} }
} }
@ -129,17 +129,17 @@ namespace NzbDrone.Core.Music
_logger.Debug("Updating {0} artist", artist.Count); _logger.Debug("Updating {0} artist", artist.Count);
foreach (var s in artist) foreach (var s in artist)
{ {
_logger.Trace("Updating: {0}", s.ArtistName); _logger.Trace("Updating: {0}", s.Name);
if (!s.RootFolderPath.IsNullOrWhiteSpace()) if (!s.RootFolderPath.IsNullOrWhiteSpace())
{ {
var folderName = new DirectoryInfo(s.Path).Name; var folderName = new DirectoryInfo(s.Path).Name;
s.Path = Path.Combine(s.RootFolderPath, folderName); s.Path = Path.Combine(s.RootFolderPath, folderName);
_logger.Trace("Changing path for {0} to {1}", s.ArtistName, s.Path); _logger.Trace("Changing path for {0} to {1}", s.Name, s.Path);
} }
else else
{ {
_logger.Trace("Not changing path for: {0}", s.ArtistName); _logger.Trace("Not changing path for: {0}", s.Name);
} }
} }

@ -23,7 +23,7 @@ namespace NzbDrone.Core.Music
dynamic instance = context.ParentContext.InstanceToValidate; dynamic instance = context.ParentContext.InstanceToValidate;
var instanceId = (int)instance.Id; var instanceId = (int)instance.Id;
return !_artistService.GetAllArtists().Exists(s => s.ArtistSlug.Equals(context.PropertyValue.ToString()) && s.Id != instanceId); return !_artistService.GetAllArtists().Exists(s => s.NameSlug.Equals(context.PropertyValue.ToString()) && s.Id != instanceId);
} }
} }
} }

@ -45,33 +45,33 @@ namespace NzbDrone.Core.Music
private void RefreshArtistInfo(Artist artist) private void RefreshArtistInfo(Artist artist)
{ {
_logger.ProgressInfo("Updating Info for {0}", artist.ArtistName); _logger.ProgressInfo("Updating Info for {0}", artist.Name);
Tuple<Artist, List<Track>> tuple; Tuple<Artist, List<Track>> tuple;
try try
{ {
tuple = _artistInfo.GetArtistInfo(artist.SpotifyId); tuple = _artistInfo.GetArtistInfo(artist.ForeignArtistId);
} }
catch (ArtistNotFoundException) catch (ArtistNotFoundException)
{ {
_logger.Error("Artist '{0}' (SpotifyId {1}) was not found, it may have been removed from Spotify.", artist.ArtistName, artist.SpotifyId); _logger.Error("Artist '{0}' (SpotifyId {1}) was not found, it may have been removed from Spotify.", artist.Name, artist.ForeignArtistId);
return; return;
} }
var artistInfo = tuple.Item1; var artistInfo = tuple.Item1;
if (artist.SpotifyId != artistInfo.SpotifyId) if (artist.ForeignArtistId != artistInfo.ForeignArtistId)
{ {
_logger.Warn("Artist '{0}' (SpotifyId {1}) was replaced with '{2}' (SpotifyId {3}), because the original was a duplicate.", artist.ArtistName, artist.SpotifyId, artistInfo.ArtistName, artistInfo.SpotifyId); _logger.Warn("Artist '{0}' (SpotifyId {1}) was replaced with '{2}' (SpotifyId {3}), because the original was a duplicate.", artist.Name, artist.ForeignArtistId, artistInfo.Name, artistInfo.ForeignArtistId);
artist.SpotifyId = artistInfo.SpotifyId; artist.ForeignArtistId = artistInfo.ForeignArtistId;
} }
artist.ArtistName = artistInfo.ArtistName; artist.Name = artistInfo.Name;
artist.ArtistSlug = artistInfo.ArtistSlug; artist.NameSlug = artistInfo.NameSlug;
artist.Overview = artistInfo.Overview; artist.Overview = artistInfo.Overview;
artist.Status = artistInfo.Status; artist.Status = artistInfo.Status;
artist.CleanTitle = artistInfo.CleanTitle; artist.CleanName = artistInfo.CleanName;
artist.LastInfoSync = DateTime.UtcNow; artist.LastInfoSync = DateTime.UtcNow;
artist.Images = artistInfo.Images; artist.Images = artistInfo.Images;
artist.Genres = artistInfo.Genres; artist.Genres = artistInfo.Genres;
@ -91,7 +91,7 @@ namespace NzbDrone.Core.Music
_artistService.UpdateArtist(artist); _artistService.UpdateArtist(artist);
_refreshTrackService.RefreshTrackInfo(artist, tuple.Item2); _refreshTrackService.RefreshTrackInfo(artist, tuple.Item2);
_logger.Debug("Finished artist refresh for {0}", artist.ArtistName); _logger.Debug("Finished artist refresh for {0}", artist.Name);
_eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist)); _eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
} }
@ -112,7 +112,7 @@ namespace NzbDrone.Core.Music
// continue; // continue;
//} //}
_logger.Debug("New album ({0}) for artist: [{1}] {2}, setting monitored to true", album.Title, artist.SpotifyId, artist.ArtistName); _logger.Debug("New album ({0}) for artist: [{1}] {2}, setting monitored to true", album.Title, artist.ForeignArtistId, artist.Name);
album.Monitored = true; album.Monitored = true;
} }
@ -136,7 +136,7 @@ namespace NzbDrone.Core.Music
} }
else else
{ {
var allArtists = _artistService.GetAllArtists().OrderBy(c => c.ArtistName).ToList(); var allArtists = _artistService.GetAllArtists().OrderBy(c => c.Name).ToList();
foreach (var artist in allArtists) foreach (var artist in allArtists)
{ {
@ -156,7 +156,7 @@ namespace NzbDrone.Core.Music
{ {
try try
{ {
_logger.Info("Skipping refresh of artist: {0}", artist.ArtistName); _logger.Info("Skipping refresh of artist: {0}", artist.Name);
//TODO: _diskScanService.Scan(artist); //TODO: _diskScanService.Scan(artist);
} }
catch (Exception e) catch (Exception e)

@ -33,7 +33,7 @@ namespace NzbDrone.Core.Music
var successCount = 0; var successCount = 0;
var failCount = 0; var failCount = 0;
var existingTracks = _trackService.GetTracksByArtist(artist.SpotifyId); var existingTracks = _trackService.GetTracksByArtist(artist.ForeignArtistId);
var albums = artist.Albums; var albums = artist.Albums;
var updateList = new List<Track>(); var updateList = new List<Track>();
@ -66,7 +66,7 @@ namespace NzbDrone.Core.Music
trackToUpdate.Explict = track.Explict; trackToUpdate.Explict = track.Explict;
if (track.ArtistSpotifyId.IsNullOrWhiteSpace()) if (track.ArtistSpotifyId.IsNullOrWhiteSpace())
{ {
trackToUpdate.ArtistSpotifyId = artist.SpotifyId; trackToUpdate.ArtistSpotifyId = artist.ForeignArtistId;
} else } else
{ {
trackToUpdate.ArtistSpotifyId = track.ArtistSpotifyId; trackToUpdate.ArtistSpotifyId = track.ArtistSpotifyId;
@ -104,7 +104,7 @@ namespace NzbDrone.Core.Music
if (failCount != 0) if (failCount != 0)
{ {
_logger.Info("Finished track refresh for artist: {0}. Successful: {1} - Failed: {2} ", _logger.Info("Finished track refresh for artist: {0}. Successful: {1} - Failed: {2} ",
artist.ArtistName, successCount, failCount); artist.Name, successCount, failCount);
} }
else else
{ {

@ -26,13 +26,13 @@ namespace NzbDrone.Core.Music
{ {
if (artist.LastInfoSync < DateTime.UtcNow.AddDays(-30)) if (artist.LastInfoSync < DateTime.UtcNow.AddDays(-30))
{ {
_logger.Trace("Artist {0} last updated more than 30 days ago, should refresh.", artist.ArtistName); _logger.Trace("Artist {0} last updated more than 30 days ago, should refresh.", artist.Name);
return true; return true;
} }
if (artist.LastInfoSync >= DateTime.UtcNow.AddHours(-6)) if (artist.LastInfoSync >= DateTime.UtcNow.AddHours(-6))
{ {
_logger.Trace("Artist {0} last updated less than 6 hours ago, should not be refreshed.", artist.ArtistName); _logger.Trace("Artist {0} last updated less than 6 hours ago, should not be refreshed.", artist.Name);
return false; return false;
} }

@ -118,7 +118,7 @@ namespace NzbDrone.Core.Music
private SortBuilder<Track> GetMissingEpisodesQuery(PagingSpec<Track> pagingSpec, DateTime currentTime) private SortBuilder<Track> GetMissingEpisodesQuery(PagingSpec<Track> pagingSpec, DateTime currentTime)
{ {
return Query.Join<Track, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistSpotifyId == s.SpotifyId) return Query.Join<Track, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistSpotifyId == s.ForeignArtistId)
.Where(pagingSpec.FilterExpression) .Where(pagingSpec.FilterExpression)
.AndWhere(e => e.TrackFileId == 0) .AndWhere(e => e.TrackFileId == 0)
.AndWhere(BuildAirDateUtcCutoffWhereClause(currentTime)) .AndWhere(BuildAirDateUtcCutoffWhereClause(currentTime))
@ -130,7 +130,7 @@ namespace NzbDrone.Core.Music
private SortBuilder<Track> EpisodesWhereCutoffUnmetQuery(PagingSpec<Track> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff) private SortBuilder<Track> EpisodesWhereCutoffUnmetQuery(PagingSpec<Track> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
{ {
return Query.Join<Track, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistSpotifyId == s.SpotifyId) return Query.Join<Track, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistSpotifyId == s.ForeignArtistId)
.Join<Track, TrackFile>(JoinType.Left, e => e.TrackFile, (e, s) => e.TrackFileId == s.Id) .Join<Track, TrackFile>(JoinType.Left, e => e.TrackFile, (e, s) => e.TrackFileId == s.Id)
.Where(pagingSpec.FilterExpression) .Where(pagingSpec.FilterExpression)
.AndWhere(e => e.TrackFileId != 0) .AndWhere(e => e.TrackFileId != 0)

@ -154,7 +154,7 @@ namespace NzbDrone.Core.Music
public void HandleAsync(ArtistDeletedEvent message) public void HandleAsync(ArtistDeletedEvent message)
{ {
var tracks = GetTracksByArtist(message.Artist.SpotifyId); var tracks = GetTracksByArtist(message.Artist.ForeignArtistId);
_trackRepository.DeleteMany(tracks); _trackRepository.DeleteMany(tracks);
} }

@ -288,7 +288,6 @@
</Compile> </Compile>
<Compile Include="Datastore\Migration\105_rename_torrent_downloadstation.cs" /> <Compile Include="Datastore\Migration\105_rename_torrent_downloadstation.cs" />
<Compile Include="Datastore\Migration\111_setup_music.cs" /> <Compile Include="Datastore\Migration\111_setup_music.cs" />
<Compile Include="Datastore\Migration\112_add_music_fields_to_namingconfig.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationDbFactory.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationDbFactory.cs" />
@ -816,7 +815,7 @@
<Compile Include="Messaging\IProcessMessage.cs" /> <Compile Include="Messaging\IProcessMessage.cs" />
<Compile Include="MetadataSource\IProvideArtistInfo.cs" /> <Compile Include="MetadataSource\IProvideArtistInfo.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ActorResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\ActorResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\AlbumInfoResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\AlbumResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ArtistInfoResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\ArtistInfoResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ArtistResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\ArtistResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\EpisodeResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\EpisodeResource.cs" />
@ -825,7 +824,7 @@
<Compile Include="MetadataSource\SkyHook\Resource\SeasonResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\SeasonResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ShowResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\ShowResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\TimeOfDayResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\TimeOfDayResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\TrackInfoResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\TrackResource.cs" />
<Compile Include="MetadataSource\SkyHook\SkyHookProxy.cs" /> <Compile Include="MetadataSource\SkyHook\SkyHookProxy.cs" />
<Compile Include="MetadataSource\SearchSeriesComparer.cs" /> <Compile Include="MetadataSource\SearchSeriesComparer.cs" />
<Compile Include="MetadataSource\SkyHook\SkyHookException.cs" /> <Compile Include="MetadataSource\SkyHook\SkyHookException.cs" />

@ -284,8 +284,8 @@ namespace NzbDrone.Core.Organizer
private void AddArtistTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Artist artist) private void AddArtistTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Artist artist)
{ {
tokenHandlers["{Artist Name}"] = m => artist.ArtistName; tokenHandlers["{Artist Name}"] = m => artist.Name;
tokenHandlers["{Artist CleanTitle}"] = m => CleanTitle(artist.ArtistName); tokenHandlers["{Artist CleanTitle}"] = m => CleanTitle(artist.Name);
} }
private string AddSeasonEpisodeNumberingTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Episode> episodes, NamingConfig namingConfig) private string AddSeasonEpisodeNumberingTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Episode> episodes, NamingConfig namingConfig)

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Parser.Model
{
public class RemoteAlbum
{
public ReleaseInfo Release { get; set; }
public ParsedTrackInfo ParsedTrackInfo { get; set; }
public Artist Artist { get; set; }
public List<Album> Albums { get; set; }
public bool DownloadAllowed { get; set; }
public bool IsRecentAlbum()
{
return Albums.Any(e => e.ReleaseDate >= DateTime.UtcNow.Date.AddDays(-14));
}
public override string ToString()
{
return Release.Title;
}
}
}

@ -21,7 +21,7 @@ namespace NzbDrone.Core.Validation.Paths
{ {
if (context.PropertyValue == null) return true; if (context.PropertyValue == null) return true;
return (!_artistService.GetAllArtists().Exists(s => s.SpotifyId == context.PropertyValue.ToString())); return (!_artistService.GetAllArtists().Exists(s => s.ForeignArtistId == context.PropertyValue.ToString()));
} }
} }
} }

@ -1,3 +1,3 @@
<div class="text-center hint col-md-12"> <div class="text-center hint col-md-12">
<span>You can also search by Spotify using the spotify: prefixes.</span> <span>You can also search by MusicBrianzID using the MBID: prefixes.</span>
</div> </div>

@ -97,7 +97,7 @@ var view = Marionette.ItemView.extend({
}, },
_configureTemplateHelpers : function() { _configureTemplateHelpers : function() {
var existingArtist = ArtistCollection.where({ spotifyId : this.model.get('spotifyId') }); var existingArtist = ArtistCollection.where({ foreignArtistId : this.model.get('foreignArtistId') });
if (existingArtist.length > 0) { if (existingArtist.length > 0) {
this.templateHelpers.existing = existingArtist[0].toJSON(); this.templateHelpers.existing = existingArtist[0].toJSON();

@ -5,7 +5,7 @@
<div class="col-md-12"> <div class="col-md-12">
<h2 class="artist-title"> <h2 class="artist-title">
<!--{{titleWithYear}}--> <!--{{titleWithYear}}-->
{{artistName}} {{name}}
<!--<span class="labels"> <!--<span class="labels">
<span class="label label-default">{{network}}</span> <span class="label label-default">{{network}}</span>
@ -68,16 +68,16 @@
</div> </div>
<div class="row"> <div class="row">
{{#unless existing}} {{#unless existing}}
{{#if artistName}} {{#if name}}
<div class="form-group col-md-2 col-md-offset-10"> <div class="form-group col-md-2 col-md-offset-10">
<!--Uncomment if we need to add even more controls to add artist--> <!--Uncomment if we need to add even more controls to add artist-->
<!--<label style="visibility: hidden">Add</label>--> <!--<label style="visibility: hidden">Add</label>-->
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-success add x-add" title="Add" data-artist="{{artistName}}"> <button class="btn btn-success add x-add" title="Add" data-artist="{{name}}">
<i class="icon-lidarr-add"></i> <i class="icon-lidarr-add"></i>
</button> </button>
<button class="btn btn-success add x-add-search" title="Add and Search for missing tracks" data-artist="{{artistName}}"> <button class="btn btn-success add x-add-search" title="Add and Search for missing tracks" data-artist="{{name}}">
<i class="icon-lidarr-search"></i> <i class="icon-lidarr-search"></i>
</button> </button>
</div> </div>

@ -77,7 +77,7 @@ var Collection = PageableCollection.extend({
}, },
artistName: { artistName: {
sortKey : 'artistName' sortKey : 'name'
}, },
nextAiring : { nextAiring : {

@ -21,12 +21,12 @@ module.exports = NzbDroneController.extend({
}, },
artistDetails : function(query) { artistDetails : function(query) {
var artists = ArtistCollection.where({ artistSlug : query }); var artists = ArtistCollection.where({ nameSlug : query });
console.log('artistDetails, artists: ', artists); console.log('artistDetails, artists: ', artists);
if (artists.length !== 0) { if (artists.length !== 0) {
var targetArtist = artists[0]; var targetArtist = artists[0];
console.log("[ArtistController] targetArtist: ", targetArtist); console.log("[ArtistController] targetArtist: ", targetArtist);
this.setTitle(targetArtist.get('artistName')); // TODO: Update NzbDroneController this.setTitle(targetArtist.get('name')); // TODO: Update NzbDroneController
//this.setArtistName(targetSeries.get('artistName')); //this.setArtistName(targetSeries.get('artistName'));
this.showMainRegion(new ArtistDetailsLayout({ model : targetArtist })); this.showMainRegion(new ArtistDetailsLayout({ model : targetArtist }));
} else { } else {

@ -63,7 +63,7 @@ module.exports = Marionette.Layout.extend({
onShow : function() { onShow : function() {
this._showBackdrop(); this._showBackdrop();
this._showSeasons(); this._showAlbums();
this._setMonitoredState(); this._setMonitoredState();
this._showInfo(); this._showInfo();
}, },

@ -1,35 +1,35 @@
<div class="row series-page-header"> <div class="row artist-page-header">
<div class="visible-lg col-lg-2 poster"> <div class="visible-lg col-lg-2 poster">
{{poster}} {{poster}}
</div> </div>
<div class="col-md-12 col-lg-10"> <div class="col-md-12 col-lg-10">
<div> <div>
<h1 class="header-text"> <h1 class="header-text">
<i class="x-monitored" title="Toggle monitored state for entire series"/> <i class="x-monitored" title="Toggle monitored state for entire artist"/>
{{title}} {{name}}
<div class="series-actions pull-right"> <div class="artist-actions pull-right">
<div class="x-episode-file-editor"> <div class="x-episode-file-editor">
<i class="icon-lidarr-episode-file" title="Modify episode files for series"/> <i class="icon-lidarr-episode-file" title="Modify episode files for artist"/>
</div> </div>
<div class="x-refresh"> <div class="x-refresh">
<i class="icon-lidarr-refresh icon-can-spin" title="Update series info and scan disk"/> <i class="icon-lidarr-refresh icon-can-spin" title="Update artist info and scan disk"/>
</div> </div>
<div class="x-rename"> <div class="x-rename">
<i class="icon-lidarr-rename" title="Preview rename for all episodes"/> <i class="icon-lidarr-rename" title="Preview rename for all episodes"/>
</div> </div>
<div class="x-search"> <div class="x-search">
<i class="icon-lidarr-search" title="Search for monitored episodes in this series"/> <i class="icon-lidarr-search" title="Search for monitored episodes in this artist"/>
</div> </div>
<div class="x-edit"> <div class="x-edit">
<i class="icon-lidarr-edit" title="Edit series"/> <i class="icon-lidarr-edit" title="Edit artist"/>
</div> </div>
</div> </div>
</h1> </h1>
</div> </div>
<div class="series-detail-overview"> <div class="artist-detail-overview">
{{overview}} {{overview}}
</div> </div>
<div id="info" class="series-info"></div> <div id="info" class="artist-info"></div>
</div> </div>
</div> </div>
<div id="seasons"></div> <div id="seasons"></div>

@ -1,18 +1,18 @@
var Marionette = require('marionette'); var Marionette = require('marionette');
module.exports = Marionette.ItemView.extend({ module.exports = Marionette.ItemView.extend({
template : 'Series/Details/InfoViewTemplate', template : 'Artist/Details/InfoViewTemplate',
initialize : function(options) { initialize : function(options) {
this.episodeFileCollection = options.episodeFileCollection; this.trackFileCollection = options.trackFileCollection;
this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'change', this.render);
this.listenTo(this.episodeFileCollection, 'sync', this.render); this.listenTo(this.trackFileCollection, 'sync', this.render);
}, },
templateHelpers : function() { templateHelpers : function() {
return { return {
fileCount : this.episodeFileCollection.length fileCount : this.trackFileCollection.length
}; };
} }
}); });

@ -28,7 +28,7 @@
{{/if_eq}} {{/if_eq}}
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<span class="series-info-links"> <span class="artist-info-links">
<a href="{{traktUrl}}" class="label label-info">Trakt</a> <a href="{{traktUrl}}" class="label label-info">Trakt</a>
<a href="{{tvdbUrl}}" class="label label-info">The TVDB</a> <a href="{{tvdbUrl}}" class="label label-info">The TVDB</a>

@ -45,7 +45,7 @@ module.exports = Marionette.Layout.extend({
cell : ArtistStatusCell cell : ArtistStatusCell
}, },
{ {
name : 'artistName', name : 'name',
label : 'Artist', label : 'Artist',
cell : ArtistTitleCell, cell : ArtistTitleCell,
cellValue : 'this' cellValue : 'this'

@ -9,7 +9,7 @@
<div class="row"> <div class="row">
<div class="col-md-10 col-xs-10"> <div class="col-md-10 col-xs-10">
<a href="{{route}}" target="_blank"> <a href="{{route}}" target="_blank">
<h2>{{artistName}}</h2> <h2>{{name}}</h2>
</a> </a>
</div> </div>
<div class="col-md-2 col-xs-2"> <div class="col-md-2 col-xs-2">

@ -40,7 +40,7 @@ Handlebars.registerHelper('tvMazeUrl', function() {
}); });
Handlebars.registerHelper('route', function() { Handlebars.registerHelper('route', function() {
return StatusModel.get('urlBase') + '/artist/' + this.artistSlug; return StatusModel.get('urlBase') + '/artist/' + this.nameSlug;
}); });
Handlebars.registerHelper('percentOfEpisodes', function() { Handlebars.registerHelper('percentOfEpisodes', function() {

Loading…
Cancel
Save