From 19f824dbd8bce56ba91a96800ef1dd54a5fcc098 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 14 Jul 2024 14:03:47 +0300 Subject: [PATCH 001/316] Bump version to 2.5.0 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b9bb0f4b9..4f3e61d15 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ variables: testsFolder: './_tests' yarnCacheFolder: $(Pipeline.Workspace)/.yarn nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages - majorVersion: '2.4.3' + majorVersion: '2.5.0' minorVersion: $[counter('minorVersion', 1076)] lidarrVersion: '$(majorVersion).$(minorVersion)' buildName: '$(Build.SourceBranchName).$(lidarrVersion)' From 30e681e84336a1656ab66586cd82a21c8b340465 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 14 Dec 2022 17:45:43 -0800 Subject: [PATCH 002/316] Fixed: Refactor artist statistics (cherry picked from commit 6c53bf30d52b9d10aa0f65c05cb6561cfbf3f8bd) --- .../ArtistStatisticsFixture.cs | 22 +++++++ .../ArtistStats/ArtistStatisticsRepository.cs | 63 ++++++++++++------- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/NzbDrone.Core.Test/ArtistStatsTests/ArtistStatisticsFixture.cs b/src/NzbDrone.Core.Test/ArtistStatsTests/ArtistStatisticsFixture.cs index 7757ddfc1..e0ad418ba 100644 --- a/src/NzbDrone.Core.Test/ArtistStatsTests/ArtistStatisticsFixture.cs +++ b/src/NzbDrone.Core.Test/ArtistStatsTests/ArtistStatisticsFixture.cs @@ -3,6 +3,7 @@ using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Common.Extensions; using NzbDrone.Core.ArtistStats; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Music; @@ -124,5 +125,26 @@ namespace NzbDrone.Core.Test.ArtistStatsTests stats.Should().HaveCount(1); stats.First().SizeOnDisk.Should().Be(_trackFile.Size); } + + [Test] + public void should_not_duplicate_size_for_multi_track_files() + { + GivenTrackWithFile(); + GivenTrack(); + GivenTrackFile(); + + var track2 = _track.JsonClone(); + + track2.Id = 0; + track2.TrackNumber += 1; + track2.ForeignTrackId = "2"; + + Db.Insert(track2); + + var stats = Subject.ArtistStatistics(); + + stats.Should().HaveCount(1); + stats.First().SizeOnDisk.Should().Be(_trackFile.Size); + } } } diff --git a/src/NzbDrone.Core/ArtistStats/ArtistStatisticsRepository.cs b/src/NzbDrone.Core/ArtistStats/ArtistStatisticsRepository.cs index a7e73bb9a..d74863a4f 100644 --- a/src/NzbDrone.Core/ArtistStats/ArtistStatisticsRepository.cs +++ b/src/NzbDrone.Core/ArtistStats/ArtistStatisticsRepository.cs @@ -16,7 +16,8 @@ namespace NzbDrone.Core.ArtistStats public class ArtistStatisticsRepository : IArtistStatisticsRepository { - private const string _selectTemplate = "SELECT /**select**/ FROM \"Tracks\" /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/ /**groupby**/ /**having**/ /**orderby**/"; + private const string _selectTracksTemplate = "SELECT /**select**/ FROM \"Tracks\" /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/ /**groupby**/ /**having**/ /**orderby**/"; + private const string _selectTrackFilesTemplate = "SELECT /**select**/ FROM \"TrackFiles\" /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/ /**groupby**/ /**having**/ /**orderby**/"; private readonly IMainDatabase _database; @@ -28,32 +29,33 @@ namespace NzbDrone.Core.ArtistStats public List ArtistStatistics() { var time = DateTime.UtcNow; - - if (_database.DatabaseType == DatabaseType.PostgreSQL) - { - return Query(Builder().WherePostgres(x => x.ReleaseDate < time)); - } - - return Query(Builder().Where(x => x.ReleaseDate < time)); + return MapResults(Query(TracksBuilder(time), _selectTracksTemplate), + Query(TrackFilesBuilder(), _selectTrackFilesTemplate)); } public List ArtistStatistics(int artistId) { var time = DateTime.UtcNow; - if (_database.DatabaseType == DatabaseType.PostgreSQL) - { - return Query(Builder().WherePostgres(x => x.ReleaseDate < time) - .WherePostgres(x => x.Id == artistId)); - } - - return Query(Builder().Where(x => x.ReleaseDate < time) - .Where(x => x.Id == artistId)); + return MapResults(Query(TracksBuilder(time).Where(x => x.Id == artistId), _selectTracksTemplate), + Query(TrackFilesBuilder().Where(x => x.Id == artistId), _selectTrackFilesTemplate)); } - private List Query(SqlBuilder builder) + private List MapResults(List tracksResult, List filesResult) { - var sql = builder.AddTemplate(_selectTemplate).LogQuery(); + tracksResult.ForEach(e => + { + var file = filesResult.SingleOrDefault(f => f.ArtistId == e.ArtistId & f.AlbumId == e.AlbumId); + + e.SizeOnDisk = file?.SizeOnDisk ?? 0; + }); + + return tracksResult; + } + + private List Query(SqlBuilder builder, string template) + { + var sql = builder.AddTemplate(template).LogQuery(); using (var conn = _database.OpenConnection()) { @@ -61,25 +63,38 @@ namespace NzbDrone.Core.ArtistStats } } - private SqlBuilder Builder() + private SqlBuilder TracksBuilder(DateTime currentDate) { + var parameters = new DynamicParameters(); + parameters.Add("currentDate", currentDate, null); + var trueIndicator = _database.DatabaseType == DatabaseType.PostgreSQL ? "true" : "1"; return new SqlBuilder(_database.DatabaseType) .Select($@"""Artists"".""Id"" AS ""ArtistId"", ""Albums"".""Id"" AS ""AlbumId"", - SUM(COALESCE(""TrackFiles"".""Size"", 0)) AS ""SizeOnDisk"", COUNT(""Tracks"".""Id"") AS ""TotalTrackCount"", - SUM(CASE WHEN ""Tracks"".""TrackFileId"" > 0 THEN 1 ELSE 0 END) AS ""AvailableTrackCount"", - SUM(CASE WHEN ""Albums"".""Monitored"" = {trueIndicator} OR ""Tracks"".""TrackFileId"" > 0 THEN 1 ELSE 0 END) AS ""TrackCount"", - SUM(CASE WHEN ""TrackFiles"".""Id"" IS NULL THEN 0 ELSE 1 END) AS ""TrackFileCount""") + SUM(CASE WHEN ""Albums"".""ReleaseDate"" <= @currentDate OR ""Tracks"".""TrackFileId"" > 0 THEN 1 ELSE 0 END) AS ""AvailableTrackCount"", + SUM(CASE WHEN (""Albums"".""Monitored"" = {trueIndicator} AND ""Albums"".""ReleaseDate"" <= @currentDate) OR ""Tracks"".""TrackFileId"" > 0 THEN 1 ELSE 0 END) AS ""TrackCount"", + SUM(CASE WHEN ""Tracks"".""TrackFileId"" > 0 THEN 1 ELSE 0 END) AS TrackFileCount", parameters) .Join((t, r) => t.AlbumReleaseId == r.Id) .Join((r, a) => r.AlbumId == a.Id) .Join((album, artist) => album.ArtistMetadataId == artist.ArtistMetadataId) - .LeftJoin((t, f) => t.TrackFileId == f.Id) .Where(x => x.Monitored == true) .GroupBy(x => x.Id) .GroupBy(x => x.Id); } + + private SqlBuilder TrackFilesBuilder() + { + return new SqlBuilder(_database.DatabaseType) + .Select(@"""Artists"".""Id"" AS ""ArtistId"", + ""AlbumId"", + SUM(COALESCE(""Size"", 0)) AS SizeOnDisk") + .Join((t, a) => t.AlbumId == a.Id) + .Join((album, artist) => album.ArtistMetadataId == artist.ArtistMetadataId) + .GroupBy(x => x.Id) + .GroupBy(x => x.AlbumId); + } } } From eb04673040e9a320c038f7c5be798b34cba7d1d4 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 14 Jul 2024 13:25:24 +0300 Subject: [PATCH 003/316] New: Include with files in album group info --- .../src/Album/Details/AlbumDetailsMedium.js | 5 +-- frontend/src/Artist/Details/AlbumGroupInfo.js | 9 +++++ frontend/src/Artist/Details/AlbumRow.js | 2 +- .../src/Artist/Details/ArtistDetailsSeason.js | 37 +++++++++++++------ src/NzbDrone.Core/Localization/Core/en.json | 1 + 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/frontend/src/Album/Details/AlbumDetailsMedium.js b/frontend/src/Album/Details/AlbumDetailsMedium.js index 09c489b2d..9e80e2c7a 100644 --- a/frontend/src/Album/Details/AlbumDetailsMedium.js +++ b/frontend/src/Album/Details/AlbumDetailsMedium.js @@ -12,16 +12,13 @@ import TrackRowConnector from './TrackRowConnector'; import styles from './AlbumDetailsMedium.css'; function getMediumStatistics(tracks) { - let trackCount = 0; + const trackCount = tracks.length; let trackFileCount = 0; let totalTrackCount = 0; tracks.forEach((track) => { if (track.trackFileId) { - trackCount++; trackFileCount++; - } else { - trackCount++; } totalTrackCount++; diff --git a/frontend/src/Artist/Details/AlbumGroupInfo.js b/frontend/src/Artist/Details/AlbumGroupInfo.js index 0fb62d4a3..139cd7765 100644 --- a/frontend/src/Artist/Details/AlbumGroupInfo.js +++ b/frontend/src/Artist/Details/AlbumGroupInfo.js @@ -10,6 +10,7 @@ function AlbumGroupInfo(props) { const { totalAlbumCount, monitoredAlbumCount, + albumFileCount, trackFileCount, sizeOnDisk } = props; @@ -30,6 +31,13 @@ function AlbumGroupInfo(props) { data={monitoredAlbumCount} /> + + { - statistics.totalTrackCount + totalTrackCount } ); diff --git a/frontend/src/Artist/Details/ArtistDetailsSeason.js b/frontend/src/Artist/Details/ArtistDetailsSeason.js index 37c85aa66..004613e30 100644 --- a/frontend/src/Artist/Details/ArtistDetailsSeason.js +++ b/frontend/src/Artist/Details/ArtistDetailsSeason.js @@ -22,32 +22,43 @@ import styles from './ArtistDetailsSeason.css'; function getAlbumStatistics(albums) { let albumCount = 0; + let albumFileCount = 0; let trackFileCount = 0; let totalAlbumCount = 0; let monitoredAlbumCount = 0; let hasMonitoredAlbums = false; let sizeOnDisk = 0; - albums.forEach((album) => { - if (album.statistics) { - sizeOnDisk = sizeOnDisk + album.statistics.sizeOnDisk; - trackFileCount = trackFileCount + album.statistics.trackFileCount; + albums.forEach(({ monitored, releaseDate, statistics = {} }) => { + const { + trackFileCount: albumTrackFileCount = 0, + totalTrackCount: albumTotalTrackCount = 0, + sizeOnDisk: albumSizeOnDisk = 0 + } = statistics; - if (album.statistics.trackFileCount === album.statistics.totalTrackCount || (album.monitored && isBefore(album.airDateUtc))) { - albumCount++; - } + const hasFiles = albumTrackFileCount > 0 && albumTrackFileCount === albumTotalTrackCount; + + if (hasFiles || (monitored && isBefore(releaseDate))) { + albumCount++; } - if (album.monitored) { + if (hasFiles) { + albumFileCount++; + } + + if (monitored) { monitoredAlbumCount++; hasMonitoredAlbums = true; } totalAlbumCount++; + trackFileCount = trackFileCount + albumTrackFileCount; + sizeOnDisk = sizeOnDisk + albumSizeOnDisk; }); return { albumCount, + albumFileCount, totalAlbumCount, trackFileCount, monitoredAlbumCount, @@ -56,8 +67,8 @@ function getAlbumStatistics(albums) { }; } -function getAlbumCountKind(monitored, albumCount, monitoredAlbumCount) { - if (albumCount === monitoredAlbumCount && monitoredAlbumCount > 0) { +function getAlbumCountKind(monitored, albumCount, albumFileCount) { + if (albumCount === albumFileCount && albumFileCount > 0) { return kinds.SUCCESS; } @@ -192,6 +203,7 @@ class ArtistDetailsSeason extends Component { const { albumCount, + albumFileCount, totalAlbumCount, trackFileCount, monitoredAlbumCount, @@ -226,9 +238,9 @@ class ArtistDetailsSeason extends Component { anchor={ } title={translate('GroupInformation')} @@ -237,6 +249,7 @@ class ArtistDetailsSeason extends Component { diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index d279bfadd..642d99a2a 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1294,6 +1294,7 @@ "WatchRootFoldersForFileChanges": "Watch Root Folders for file changes", "WeekColumnHeader": "Week Column Header", "WhatsNew": "What's New?", + "WithFiles": "With Files", "WouldYouLikeToRestoreBackup": "Would you like to restore the backup '{name}'?", "WriteAudioTagsHelpTextWarning": "Selecting 'All files' will alter existing files when they are imported.", "WriteMetadataTags": "Write Metadata Tags", From a52c6f6f41bff9b76a34085aca01a1a709bdf62d Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 14 Jul 2024 19:28:28 +0300 Subject: [PATCH 004/316] Fixed: Display last/next monitored albums for artists --- frontend/src/Album/Album.ts | 1 + frontend/src/Album/AlbumTitleLink.js | 5 +++-- frontend/src/Artist/Artist.ts | 1 - .../Store/Selectors/createArtistAlbumsSelector.ts | 2 +- src/Lidarr.Api.V1/Artist/ArtistResource.cs | 6 ++++-- src/Lidarr.Api.V1/openapi.json | 4 ---- .../AlbumRepositoryTests/AlbumRepositoryFixture.cs | 4 ++-- .../Music/Repositories/AlbumRepository.cs | 12 ++++++------ 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/frontend/src/Album/Album.ts b/frontend/src/Album/Album.ts index c9f10a87c..7a645efee 100644 --- a/frontend/src/Album/Album.ts +++ b/frontend/src/Album/Album.ts @@ -10,6 +10,7 @@ export interface Statistics { } interface Album extends ModelBase { + artistId: number; artist: Artist; foreignAlbumId: string; title: string; diff --git a/frontend/src/Album/AlbumTitleLink.js b/frontend/src/Album/AlbumTitleLink.js index 8b4dfe212..e55fadfc0 100644 --- a/frontend/src/Album/AlbumTitleLink.js +++ b/frontend/src/Album/AlbumTitleLink.js @@ -4,10 +4,11 @@ import Link from 'Components/Link/Link'; function AlbumTitleLink({ foreignAlbumId, title, disambiguation }) { const link = `/album/${foreignAlbumId}`; + const albumTitle = `${title}${disambiguation ? ` (${disambiguation})` : ''}`; return ( - - {title}{disambiguation ? ` (${disambiguation})` : ''} + + {albumTitle} ); } diff --git a/frontend/src/Artist/Artist.ts b/frontend/src/Artist/Artist.ts index d89e32f34..813dbea08 100644 --- a/frontend/src/Artist/Artist.ts +++ b/frontend/src/Artist/Artist.ts @@ -23,7 +23,6 @@ export interface Ratings { interface Artist extends ModelBase { added: string; - artistMetadataId: string; foreignArtistId: string; cleanName: string; ended: boolean; diff --git a/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts b/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts index 2ae54a10c..baffd87ec 100644 --- a/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts +++ b/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts @@ -11,7 +11,7 @@ function createArtistAlbumsSelector(artistId: number) { const { isFetching, isPopulated, error, items } = albums; const filteredAlbums = items.filter( - (album) => album.artist.artistMetadataId === artist.artistMetadataId + (album) => album.artistId === artist.id ); return { diff --git a/src/Lidarr.Api.V1/Artist/ArtistResource.cs b/src/Lidarr.Api.V1/Artist/ArtistResource.cs index 288208fcf..a71791ba0 100644 --- a/src/Lidarr.Api.V1/Artist/ArtistResource.cs +++ b/src/Lidarr.Api.V1/Artist/ArtistResource.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json.Serialization; using Lidarr.Api.V1.Albums; using Lidarr.Http.REST; -using Newtonsoft.Json; using NzbDrone.Common.Extensions; using NzbDrone.Core.MediaCover; using NzbDrone.Core.Music; @@ -32,7 +32,10 @@ namespace Lidarr.Api.V1.Artist public string Disambiguation { get; set; } public List Links { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public AlbumResource NextAlbum { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public AlbumResource LastAlbum { get; set; } public List Images { get; set; } @@ -74,7 +77,6 @@ namespace Lidarr.Api.V1.Artist return new ArtistResource { Id = model.Id, - ArtistMetadataId = model.ArtistMetadataId, ArtistName = model.Name, diff --git a/src/Lidarr.Api.V1/openapi.json b/src/Lidarr.Api.V1/openapi.json index d3d5e381c..b48424105 100644 --- a/src/Lidarr.Api.V1/openapi.json +++ b/src/Lidarr.Api.V1/openapi.json @@ -8670,10 +8670,6 @@ "type": "integer", "format": "int32" }, - "artistMetadataId": { - "type": "integer", - "format": "int32" - }, "status": { "$ref": "#/components/schemas/ArtistStatusType" }, diff --git a/src/NzbDrone.Core.Test/MusicTests/AlbumRepositoryTests/AlbumRepositoryFixture.cs b/src/NzbDrone.Core.Test/MusicTests/AlbumRepositoryTests/AlbumRepositoryFixture.cs index 5d57b2755..4d762c5a0 100644 --- a/src/NzbDrone.Core.Test/MusicTests/AlbumRepositoryTests/AlbumRepositoryFixture.cs +++ b/src/NzbDrone.Core.Test/MusicTests/AlbumRepositoryTests/AlbumRepositoryFixture.cs @@ -193,7 +193,7 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests GivenMultipleAlbums(); var result = _albumRepo.GetNextAlbums(new[] { _artist.ArtistMetadataId }); - result.Should().BeEquivalentTo(_albums.Take(1), AlbumComparerOptions); + result.Should().BeEquivalentTo(_albums.Skip(1).Take(1), AlbumComparerOptions); } [Test] @@ -202,7 +202,7 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests GivenMultipleAlbums(); var result = _albumRepo.GetLastAlbums(new[] { _artist.ArtistMetadataId }); - result.Should().BeEquivalentTo(_albums.Skip(2).Take(1), AlbumComparerOptions); + result.Should().BeEquivalentTo(_albums.Skip(3).Take(1), AlbumComparerOptions); } private EquivalencyAssertionOptions AlbumComparerOptions(EquivalencyAssertionOptions opts) => opts.ComparingByMembers() diff --git a/src/NzbDrone.Core/Music/Repositories/AlbumRepository.cs b/src/NzbDrone.Core/Music/Repositories/AlbumRepository.cs index 9d8602f2c..3c69cf42b 100644 --- a/src/NzbDrone.Core/Music/Repositories/AlbumRepository.cs +++ b/src/NzbDrone.Core/Music/Repositories/AlbumRepository.cs @@ -46,13 +46,13 @@ namespace NzbDrone.Core.Music var now = DateTime.UtcNow; var inner = Builder() - .Select("MIN(\"Albums\".\"Id\") as id, MAX(\"Albums\".\"ReleaseDate\") as date") - .Where(x => artistMetadataIds.Contains(x.ArtistMetadataId) && x.ReleaseDate < now) + .Select("\"Albums\".\"ArtistMetadataId\" AS artist_metadata_id, MAX(\"Albums\".\"ReleaseDate\") AS date") + .Where(x => artistMetadataIds.Contains(x.ArtistMetadataId) && x.Monitored == true && x.ReleaseDate < now) .GroupBy(x => x.ArtistMetadataId) .AddSelectTemplate(typeof(Album)); var outer = Builder() - .Join($"({inner.RawSql}) ids on ids.id = \"Albums\".\"Id\" and ids.date = \"Albums\".\"ReleaseDate\"") + .Join($"({inner.RawSql}) ids ON ids.artist_metadata_id = \"Albums\".\"ArtistMetadataId\" AND ids.date = \"Albums\".\"ReleaseDate\"") .AddParameters(inner.Parameters); return Query(outer); @@ -63,13 +63,13 @@ namespace NzbDrone.Core.Music var now = DateTime.UtcNow; var inner = Builder() - .Select("MIN(\"Albums\".\"Id\") as id, MIN(\"Albums\".\"ReleaseDate\") as date") - .Where(x => artistMetadataIds.Contains(x.ArtistMetadataId) && x.ReleaseDate > now) + .Select("\"Albums\".\"ArtistMetadataId\" AS artist_metadata_id, MIN(\"Albums\".\"ReleaseDate\") AS date") + .Where(x => artistMetadataIds.Contains(x.ArtistMetadataId) && x.Monitored == true && x.ReleaseDate > now) .GroupBy(x => x.ArtistMetadataId) .AddSelectTemplate(typeof(Album)); var outer = Builder() - .Join($"({inner.RawSql}) ids on ids.id = \"Albums\".\"Id\" and ids.date = \"Albums\".\"ReleaseDate\"") + .Join($"({inner.RawSql}) ids ON ids.artist_metadata_id = \"Albums\".\"ArtistMetadataId\" AND ids.date = \"Albums\".\"ReleaseDate\"") .AddParameters(inner.Parameters); return Query(outer); From 56679861a01232a5881a81d0a7593c452452b04f Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 14 Jul 2024 21:48:23 +0300 Subject: [PATCH 005/316] Mapping `ArtistMetadataId` is needed for last/next monitored albums --- src/Lidarr.Api.V1/Artist/ArtistController.cs | 6 ++++-- src/Lidarr.Api.V1/Artist/ArtistResource.cs | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Lidarr.Api.V1/Artist/ArtistController.cs b/src/Lidarr.Api.V1/Artist/ArtistController.cs index 24d7855e1..e5829ff96 100644 --- a/src/Lidarr.Api.V1/Artist/ArtistController.cs +++ b/src/Lidarr.Api.V1/Artist/ArtistController.cs @@ -204,8 +204,10 @@ namespace Lidarr.Api.V1.Artist private void LinkNextPreviousAlbums(params ArtistResource[] artists) { - var nextAlbums = _albumService.GetNextAlbumsByArtistMetadataId(artists.Select(x => x.ArtistMetadataId)); - var lastAlbums = _albumService.GetLastAlbumsByArtistMetadataId(artists.Select(x => x.ArtistMetadataId)); + var artistMetadataIds = artists.Select(x => x.ArtistMetadataId).Distinct().ToList(); + + var nextAlbums = _albumService.GetNextAlbumsByArtistMetadataId(artistMetadataIds); + var lastAlbums = _albumService.GetLastAlbumsByArtistMetadataId(artistMetadataIds); foreach (var artistResource in artists) { diff --git a/src/Lidarr.Api.V1/Artist/ArtistResource.cs b/src/Lidarr.Api.V1/Artist/ArtistResource.cs index a71791ba0..73fbe4240 100644 --- a/src/Lidarr.Api.V1/Artist/ArtistResource.cs +++ b/src/Lidarr.Api.V1/Artist/ArtistResource.cs @@ -77,6 +77,7 @@ namespace Lidarr.Api.V1.Artist return new ArtistResource { Id = model.Id, + ArtistMetadataId = model.ArtistMetadataId, ArtistName = model.Name, From 633feaa02342b646277557610e78133c7eb1aeaf Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 14 Jul 2024 23:19:20 +0300 Subject: [PATCH 006/316] Fixed disable options for SelectInput --- frontend/src/Components/Form/MonitorAlbumsSelectInput.js | 2 +- frontend/src/Components/Form/SelectInput.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/Components/Form/MonitorAlbumsSelectInput.js b/frontend/src/Components/Form/MonitorAlbumsSelectInput.js index f3cefd29e..d48284c38 100644 --- a/frontend/src/Components/Form/MonitorAlbumsSelectInput.js +++ b/frontend/src/Components/Form/MonitorAlbumsSelectInput.js @@ -25,7 +25,7 @@ function MonitorAlbumsSelectInput(props) { if (includeMixed) { values.unshift({ key: 'mixed', - value: '(Mixed)', + value: `(${translate('Mixed')})`, isDisabled: true }); } diff --git a/frontend/src/Components/Form/SelectInput.js b/frontend/src/Components/Form/SelectInput.js index 553501afc..d43560134 100644 --- a/frontend/src/Components/Form/SelectInput.js +++ b/frontend/src/Components/Form/SelectInput.js @@ -52,6 +52,7 @@ class SelectInput extends Component { const { key, value: optionValue, + isDisabled: optionIsDisabled = false, ...otherOptionProps } = option; @@ -59,6 +60,7 @@ class SelectInput extends Component {