New: Show Custom Formats on Manual Import / Manage Episodes

Closes #5241
pull/5281/head
Mark McDowall 1 year ago committed by Mark McDowall
parent 6216a71f8c
commit da4f6b7df9

@ -77,6 +77,15 @@ const columns = [
isSortable: true,
isVisible: true
},
{
name: 'customFormats',
label: React.createElement(Icon, {
name: icons.INTERACTIVE,
title: 'Custom Format'
}),
isSortable: true,
isVisible: true
},
{
name: 'rejections',
label: React.createElement(Icon, {

@ -23,3 +23,7 @@
margin-top: 0;
text-align: start;
}
.customFormatTooltip {
max-width: 250px;
}

@ -7,6 +7,7 @@ import TableRowCellButton from 'Components/Table/Cells/TableRowCellButton';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
import TableRow from 'Components/Table/TableRow';
import Popover from 'Components/Tooltip/Popover';
import EpisodeFormats from 'Episode/EpisodeFormats';
import EpisodeLanguages from 'Episode/EpisodeLanguages';
import EpisodeQuality from 'Episode/EpisodeQuality';
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
@ -213,6 +214,7 @@ class InteractiveImportRow extends Component {
languages,
releaseGroup,
size,
customFormats,
rejections,
isReprocessing,
isSelected,
@ -366,7 +368,26 @@ class InteractiveImportRow extends Component {
<TableRowCell>
{
rejections && rejections.length ?
customFormats?.length ?
<Popover
anchor={
<Icon name={icons.INTERACTIVE} />
}
title="Formats"
body={
<div className={styles.customFormatTooltip}>
<EpisodeFormats formats={customFormats} />
</div>
}
position={tooltipPositions.LEFT}
/> :
null
}
</TableRowCell>
<TableRowCell>
{
rejections.length ?
<Popover
anchor={
<Icon
@ -389,6 +410,7 @@ class InteractiveImportRow extends Component {
</ul>
}
position={tooltipPositions.LEFT}
canFlip={false}
/> :
null
}
@ -462,6 +484,7 @@ InteractiveImportRow.propTypes = {
quality: PropTypes.object,
languages: PropTypes.arrayOf(PropTypes.object),
size: PropTypes.number.isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object),
rejections: PropTypes.arrayOf(PropTypes.object).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
episodeFileId: PropTypes.number,

@ -18,6 +18,7 @@ namespace NzbDrone.Core.CustomFormats
List<CustomFormat> ParseCustomFormat(EpisodeFile episodeFile);
List<CustomFormat> ParseCustomFormat(Blocklist blocklist, Series series);
List<CustomFormat> ParseCustomFormat(EpisodeHistory history, Series series);
List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode);
}
public class CustomFormatCalculationService : ICustomFormatCalculationService
@ -102,6 +103,28 @@ namespace NzbDrone.Core.CustomFormats
return ParseCustomFormat(input);
}
public List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode)
{
var episodeInfo = new ParsedEpisodeInfo
{
SeriesTitle = localEpisode.Series.Title,
ReleaseTitle = localEpisode.SceneName,
Quality = localEpisode.Quality,
Languages = localEpisode.Languages,
ReleaseGroup = localEpisode.ReleaseGroup
};
var input = new CustomFormatInput
{
EpisodeInfo = episodeInfo,
Series = localEpisode.Series,
Size = localEpisode.Size,
Languages = localEpisode.Languages
};
return ParseCustomFormat(input);
}
private List<CustomFormat> ParseCustomFormat(CustomFormatInput input)
{
return ParseCustomFormat(input, _formatService.All());
@ -148,7 +171,7 @@ namespace NzbDrone.Core.CustomFormats
var episodeInfo = new ParsedEpisodeInfo
{
SeriesTitle = episodeFile.Series.Value.Title,
SeriesTitle = series.Title,
ReleaseTitle = sceneName,
Quality = episodeFile.Quality,
Languages = episodeFile.Languages,

@ -4,6 +4,7 @@ using System.Linq;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download;
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation;
@ -28,6 +29,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
private readonly IAggregationService _aggregationService;
private readonly IDiskProvider _diskProvider;
private readonly IDetectSample _detectSample;
private readonly ICustomFormatCalculationService _formatCalculator;
private readonly Logger _logger;
public ImportDecisionMaker(IEnumerable<IImportDecisionEngineSpecification> specifications,
@ -35,6 +37,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
IAggregationService aggregationService,
IDiskProvider diskProvider,
IDetectSample detectSample,
ICustomFormatCalculationService formatCalculator,
Logger logger)
{
_specifications = specifications;
@ -42,6 +45,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
_aggregationService = aggregationService;
_diskProvider = diskProvider;
_detectSample = detectSample;
_formatCalculator = formatCalculator;
_logger = logger;
}

@ -1,4 +1,5 @@
using System.Collections.Generic;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Qualities;
@ -21,6 +22,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
public List<Language> Languages { get; set; }
public string ReleaseGroup { get; set; }
public string DownloadId { get; set; }
public List<CustomFormat> CustomFormats { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
public ManualImportItem()
{
CustomFormats = new List<CustomFormat>();
}
}
}

@ -6,6 +6,7 @@ using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.TrackedDownloads;
@ -40,6 +41,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
private readonly ITrackedDownloadService _trackedDownloadService;
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
private readonly IMediaFileService _mediaFileService;
private readonly ICustomFormatCalculationService _formatCalculator;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
@ -54,6 +56,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
ITrackedDownloadService trackedDownloadService,
IDownloadedEpisodesImportService downloadedEpisodesImportService,
IMediaFileService mediaFileService,
ICustomFormatCalculationService formatCalculator,
IEventAggregator eventAggregator,
Logger logger)
{
@ -68,6 +71,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
_trackedDownloadService = trackedDownloadService;
_downloadedEpisodesImportService = downloadedEpisodesImportService;
_mediaFileService = mediaFileService;
_formatCalculator = formatCalculator;
_eventAggregator = eventAggregator;
_logger = logger;
}
@ -382,6 +386,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
if (decision.LocalEpisode.Series != null)
{
item.Series = decision.LocalEpisode.Series;
item.CustomFormats = _formatCalculator.ParseCustomFormat(decision.LocalEpisode);
}
if (decision.LocalEpisode.Episodes.Any() && decision.LocalEpisode.Episodes.Select(c => c.SeasonNumber).Distinct().Count() == 1)
@ -429,6 +435,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
item.Size = _diskProvider.GetFileSize(item.Path);
item.Rejections = Enumerable.Empty<Rejection>();
item.EpisodeFileId = episodeFile.Id;
item.CustomFormats = _formatCalculator.ParseCustomFormat(episodeFile, series);
return item;
}

@ -5,6 +5,7 @@ using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaFiles.EpisodeImport.Manual;
using NzbDrone.Core.Qualities;
using Sonarr.Api.V3.CustomFormats;
using Sonarr.Api.V3.Episodes;
using Sonarr.Api.V3.Series;
using Sonarr.Http.REST;
@ -27,6 +28,7 @@ namespace Sonarr.Api.V3.ManualImport
public List<Language> Languages { get; set; }
public int QualityWeight { get; set; }
public string DownloadId { get; set; }
public List<CustomFormatResource> CustomFormats { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
}
@ -54,6 +56,7 @@ namespace Sonarr.Api.V3.ManualImport
ReleaseGroup = model.ReleaseGroup,
Quality = model.Quality,
Languages = model.Languages,
CustomFormats = model.CustomFormats.ToResource(),
// QualityWeight
DownloadId = model.DownloadId,

Loading…
Cancel
Save