From e8ab1f842b1168ba7605357a58bfb3fd82e5470f Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 23 Jun 2024 21:52:39 +0300 Subject: [PATCH 001/320] Bump version to 2.4.1 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 973c6d14b..c2b0be96e 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.0' + majorVersion: '2.4.1' minorVersion: $[counter('minorVersion', 1076)] lidarrVersion: '$(majorVersion).$(minorVersion)' buildName: '$(Build.SourceBranchName).$(lidarrVersion)' From d602f38b7d1fc7e09f4d74a8fd245928f8e0e811 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 25 Jun 2024 15:52:12 -0700 Subject: [PATCH 002/320] New: Ignore Deluge torrents without a title (cherry picked from commit a0d29331341320268552660658b949179c963793) --- .../Download/Clients/Deluge/Deluge.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs index 9cbf3c4ca..faaff7112 100644 --- a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs +++ b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs @@ -122,14 +122,23 @@ namespace NzbDrone.Core.Download.Clients.Deluge } var items = new List(); + var ignoredCount = 0; foreach (var torrent in torrents) { - if (torrent.Hash == null) + // Silently ignore torrents with no hash + if (torrent.Hash.IsNullOrWhiteSpace()) { continue; } + // Ignore torrents without a name, but track to log a single warning for all invalid torrents. + if (torrent.Name.IsNullOrWhiteSpace()) + { + ignoredCount++; + continue; + } + var item = new DownloadClientItem(); item.DownloadId = torrent.Hash.ToUpper(); item.Title = torrent.Name; @@ -187,6 +196,11 @@ namespace NzbDrone.Core.Download.Clients.Deluge items.Add(item); } + if (ignoredCount > 0) + { + _logger.Warn("{0} torrent(s) were ignored becuase they did not have a title, check Deluge and remove any invalid torrents"); + } + return items; } From 47b5bbc9e1e7867d747b7449ba8f7b6091daaaa4 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Thu, 20 Jun 2024 00:16:53 +0300 Subject: [PATCH 003/320] Fixed: Exclude invalid releases from Newznab and Torznab parsers (cherry picked from commit fb060730c7d52cd342484dc68595698a9430df7b) --- .../Indexers/Newznab/NewznabRssParser.cs | 9 +++-- src/NzbDrone.Core/Indexers/RssParser.cs | 38 +++++++++---------- .../Indexers/Torznab/TorznabRssParser.cs | 9 +++-- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs b/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs index e94ac6bf7..a56badf6c 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs @@ -68,16 +68,17 @@ namespace NzbDrone.Core.Indexers.Newznab protected override bool PostProcess(IndexerResponse indexerResponse, List items, List releases) { var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray(); + if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty()) { if (enclosureTypes.Intersect(TorrentEnclosureMimeTypes).Any()) { _logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Torznab indexer?", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]); + + return false; } - else - { - _logger.Warn("{1} does not contain {1}, found {2}.", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]); - } + + _logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]); } return true; diff --git a/src/NzbDrone.Core/Indexers/RssParser.cs b/src/NzbDrone.Core/Indexers/RssParser.cs index 01758ed84..fe638c61e 100644 --- a/src/NzbDrone.Core/Indexers/RssParser.cs +++ b/src/NzbDrone.Core/Indexers/RssParser.cs @@ -262,26 +262,26 @@ namespace NzbDrone.Core.Indexers protected virtual RssEnclosure[] GetEnclosures(XElement item) { var enclosures = item.Elements("enclosure") - .Select(v => - { - try - { - return new RssEnclosure - { - Url = v.Attribute("url")?.Value, - Type = v.Attribute("type")?.Value, - Length = v.Attribute("length")?.Value?.ParseInt64() ?? 0 - }; - } - catch (Exception e) - { - _logger.Warn(e, "Failed to get enclosure for: {0}", item.Title()); - } + .Select(v => + { + try + { + return new RssEnclosure + { + Url = v.Attribute("url")?.Value, + Type = v.Attribute("type")?.Value, + Length = v.Attribute("length")?.Value?.ParseInt64() ?? 0 + }; + } + catch (Exception ex) + { + _logger.Warn(ex, "Failed to get enclosure for: {0}", item.Title()); + } - return null; - }) - .Where(v => v != null) - .ToArray(); + return null; + }) + .Where(v => v != null) + .ToArray(); return enclosures; } diff --git a/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs b/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs index f4d210a84..3b85a427e 100644 --- a/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs +++ b/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs @@ -59,16 +59,17 @@ namespace NzbDrone.Core.Indexers.Torznab protected override bool PostProcess(IndexerResponse indexerResponse, List items, List releases) { var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray(); + if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty()) { if (enclosureTypes.Intersect(UsenetEnclosureMimeTypes).Any()) { _logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Newznab indexer?", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]); + + return false; } - else - { - _logger.Warn("{1} does not contain {1}, found {2}.", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]); - } + + _logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]); } return true; From 838e49ba232e6535cb56acbd4fcff69dd20e1bc6 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Wed, 26 Jun 2024 23:50:50 +0300 Subject: [PATCH 004/320] Bump mac image to 12 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c2b0be96e..f17e5374a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -20,7 +20,7 @@ variables: innoVersion: '6.2.0' windowsImage: 'windows-2022' linuxImage: 'ubuntu-20.04' - macImage: 'macOS-11' + macImage: 'macOS-12' trigger: branches: From e31f2ad2536fd0ab868a9a22f3bf0c2c0b8a37f4 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 30 Jun 2024 05:35:37 +0300 Subject: [PATCH 005/320] Fixed: Validate metadata and quality profiles for root folders Don't allow `0` as possible value for metadata and quality profiles, and permit to edit root folders with bad values in UI. --- .../ImportLists/Manage/ManageImportListsModalRow.tsx | 5 +++-- .../src/Settings/MediaManagement/RootFolder/RootFolder.js | 8 ++++---- src/Lidarr.Api.V1/RootFolders/RootFolderController.cs | 6 ++++-- .../Validation/QualityProfileExistsValidator.cs | 8 ++++---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx index 410e626e2..095ac7c03 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx @@ -7,6 +7,7 @@ import TableRow from 'Components/Table/TableRow'; import TagListConnector from 'Components/TagListConnector'; import { createQualityProfileSelectorForHook } from 'Store/Selectors/createQualityProfileSelector'; import { SelectStateInputProps } from 'typings/props'; +import translate from 'Utilities/String/translate'; import styles from './ManageImportListsModalRow.css'; interface ManageImportListsModalRowProps { @@ -63,7 +64,7 @@ function ManageImportListsModalRow(props: ManageImportListsModalRowProps) { - {qualityProfile?.name ?? 'None'} + {qualityProfile?.name ?? translate('None')} @@ -71,7 +72,7 @@ function ManageImportListsModalRow(props: ManageImportListsModalRowProps) { - {enableAutomaticAdd ? 'Yes' : 'No'} + {enableAutomaticAdd ? translate('Yes') : translate('No')} diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js index 20cefc53f..47e5dfcf1 100644 --- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js +++ b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js @@ -75,12 +75,12 @@ class RootFolder extends Component { {path} - ); 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 017/320] 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 018/320] 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 019/320] 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 {