New: Optionally show Custom Format Score for tracks on Album Details

(cherry picked from commit eadd0c4e101af0386360bbff859f80e008a5be7c)

Closes #3872
pull/3877/head
jack-mil 10 months ago committed by Bogdan
parent 227217561c
commit df0097ea03

@ -28,3 +28,9 @@
width: 100px; width: 100px;
} }
.customFormatScore {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 55px;
}

@ -2,6 +2,7 @@
// Please do not change this file! // Please do not change this file!
interface CssExports { interface CssExports {
'audio': string; 'audio': string;
'customFormatScore': string;
'duration': string; 'duration': string;
'monitored': string; 'monitored': string;
'status': string; 'status': string;

@ -1,11 +1,15 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import AlbumFormats from 'Album/AlbumFormats';
import EpisodeStatusConnector from 'Album/EpisodeStatusConnector'; import EpisodeStatusConnector from 'Album/EpisodeStatusConnector';
import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableRow from 'Components/Table/TableRow'; import TableRow from 'Components/Table/TableRow';
import Tooltip from 'Components/Tooltip/Tooltip';
import { tooltipPositions } from 'Helpers/Props';
import MediaInfoConnector from 'TrackFile/MediaInfoConnector'; import MediaInfoConnector from 'TrackFile/MediaInfoConnector';
import * as mediaInfoTypes from 'TrackFile/mediaInfoTypes'; import * as mediaInfoTypes from 'TrackFile/mediaInfoTypes';
import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
import formatPreferredWordScore from 'Utilities/Number/formatPreferredWordScore';
import TrackActionsCell from './TrackActionsCell'; import TrackActionsCell from './TrackActionsCell';
import styles from './TrackRow.css'; import styles from './TrackRow.css';
@ -24,6 +28,8 @@ class TrackRow extends Component {
title, title,
duration, duration,
trackFilePath, trackFilePath,
customFormats,
customFormatScore,
columns, columns,
deleteTrackFile deleteTrackFile
} = this.props; } = this.props;
@ -111,6 +117,34 @@ class TrackRow extends Component {
); );
} }
if (name === 'customFormats') {
return (
<TableRowCell key={name}>
<AlbumFormats
formats={customFormats}
/>
</TableRowCell>
);
}
if (name === 'customFormatScore') {
return (
<TableRowCell
key={name}
className={styles.customFormatScore}
>
<Tooltip
anchor={formatPreferredWordScore(
customFormatScore,
customFormats.length
)}
tooltip={<AlbumFormats formats={customFormats} />}
position={tooltipPositions.BOTTOM}
/>
</TableRowCell>
);
}
if (name === 'status') { if (name === 'status') {
return ( return (
<TableRowCell <TableRowCell
@ -158,8 +192,14 @@ TrackRow.propTypes = {
duration: PropTypes.number.isRequired, duration: PropTypes.number.isRequired,
isSaving: PropTypes.bool, isSaving: PropTypes.bool,
trackFilePath: PropTypes.string, trackFilePath: PropTypes.string,
customFormats: PropTypes.arrayOf(PropTypes.object),
customFormatScore: PropTypes.number.isRequired,
mediaInfo: PropTypes.object, mediaInfo: PropTypes.object,
columns: PropTypes.arrayOf(PropTypes.object).isRequired columns: PropTypes.arrayOf(PropTypes.object).isRequired
}; };
TrackRow.defaultProps = {
customFormats: []
};
export default TrackRow; export default TrackRow;

@ -10,7 +10,9 @@ function createMapStateToProps() {
createTrackFileSelector(), createTrackFileSelector(),
(id, trackFile) => { (id, trackFile) => {
return { return {
trackFilePath: trackFile ? trackFile.path : null trackFilePath: trackFile ? trackFile.path : null,
customFormats: trackFile ? trackFile.customFormats : [],
customFormatScore: trackFile ? trackFile.customFormatScore : 0
}; };
} }
); );

@ -1,5 +1,7 @@
import React from 'react';
import { createAction } from 'redux-actions'; import { createAction } from 'redux-actions';
import { sortDirections } from 'Helpers/Props'; import Icon from 'Components/Icon';
import { icons, sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks'; import { createThunk, handleThunks } from 'Store/thunks';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import createFetchHandler from './Creators/createFetchHandler'; import createFetchHandler from './Creators/createFetchHandler';
@ -56,6 +58,20 @@ export const defaultState = {
label: translate('AudioInfo'), label: translate('AudioInfo'),
isVisible: true isVisible: true
}, },
{
name: 'customFormats',
label: 'Formats',
isVisible: false
},
{
name: 'customFormatScore',
columnLabel: translate('CustomFormatScore'),
label: React.createElement(Icon, {
name: icons.SCORE,
title: translate('CustomFormatScore')
}),
isVisible: false
},
{ {
name: 'status', name: 'status',
label: translate('Status'), label: translate('Status'),

@ -4,6 +4,7 @@ using Lidarr.Http;
using Lidarr.Http.REST; using Lidarr.Http.REST;
using Lidarr.Http.REST.Attributes; using Lidarr.Http.REST.Attributes;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
@ -28,6 +29,7 @@ namespace Lidarr.Api.V1.TrackFiles
private readonly IAudioTagService _audioTagService; private readonly IAudioTagService _audioTagService;
private readonly IArtistService _artistService; private readonly IArtistService _artistService;
private readonly IAlbumService _albumService; private readonly IAlbumService _albumService;
private readonly ICustomFormatCalculationService _formatCalculator;
private readonly IUpgradableSpecification _upgradableSpecification; private readonly IUpgradableSpecification _upgradableSpecification;
public TrackFileController(IBroadcastSignalRMessage signalRBroadcaster, public TrackFileController(IBroadcastSignalRMessage signalRBroadcaster,
@ -36,6 +38,7 @@ namespace Lidarr.Api.V1.TrackFiles
IAudioTagService audioTagService, IAudioTagService audioTagService,
IArtistService artistService, IArtistService artistService,
IAlbumService albumService, IAlbumService albumService,
ICustomFormatCalculationService formatCalculator,
IUpgradableSpecification upgradableSpecification) IUpgradableSpecification upgradableSpecification)
: base(signalRBroadcaster) : base(signalRBroadcaster)
{ {
@ -44,6 +47,7 @@ namespace Lidarr.Api.V1.TrackFiles
_audioTagService = audioTagService; _audioTagService = audioTagService;
_artistService = artistService; _artistService = artistService;
_albumService = albumService; _albumService = albumService;
_formatCalculator = formatCalculator;
_upgradableSpecification = upgradableSpecification; _upgradableSpecification = upgradableSpecification;
} }
@ -51,7 +55,7 @@ namespace Lidarr.Api.V1.TrackFiles
{ {
if (trackFile.AlbumId > 0 && trackFile.Artist != null && trackFile.Artist.Value != null) if (trackFile.AlbumId > 0 && trackFile.Artist != null && trackFile.Artist.Value != null)
{ {
return trackFile.ToResource(trackFile.Artist.Value, _upgradableSpecification); return trackFile.ToResource(trackFile.Artist.Value, _upgradableSpecification, _formatCalculator);
} }
else else
{ {
@ -84,7 +88,7 @@ namespace Lidarr.Api.V1.TrackFiles
{ {
var artist = _artistService.GetArtist(artistId.Value); var artist = _artistService.GetArtist(artistId.Value);
return _mediaFileService.GetFilesByArtist(artistId.Value).ConvertAll(f => f.ToResource(artist, _upgradableSpecification)); return _mediaFileService.GetFilesByArtist(artistId.Value).ConvertAll(f => f.ToResource(artist, _upgradableSpecification, _formatCalculator));
} }
if (albumIds.Any()) if (albumIds.Any())
@ -94,7 +98,7 @@ namespace Lidarr.Api.V1.TrackFiles
{ {
var album = _albumService.GetAlbum(albumId); var album = _albumService.GetAlbum(albumId);
var albumArtist = _artistService.GetArtist(album.ArtistId); var albumArtist = _artistService.GetArtist(album.ArtistId);
result.AddRange(_mediaFileService.GetFilesByAlbum(album.Id).ConvertAll(f => f.ToResource(albumArtist, _upgradableSpecification))); result.AddRange(_mediaFileService.GetFilesByAlbum(album.Id).ConvertAll(f => f.ToResource(albumArtist, _upgradableSpecification, _formatCalculator)));
} }
return result; return result;
@ -152,7 +156,7 @@ namespace Lidarr.Api.V1.TrackFiles
_mediaFileService.Update(trackFiles); _mediaFileService.Update(trackFiles);
return Accepted(trackFiles.ConvertAll(f => f.ToResource(trackFiles.First().Artist.Value, _upgradableSpecification))); return Accepted(trackFiles.ConvertAll(f => f.ToResource(trackFiles.First().Artist.Value, _upgradableSpecification, _formatCalculator)));
} }
[RestDeleteById] [RestDeleteById]

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Lidarr.Api.V1.CustomFormats;
using Lidarr.Http.REST; using Lidarr.Http.REST;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
@ -19,6 +22,8 @@ namespace Lidarr.Api.V1.TrackFiles
public string ReleaseGroup { get; set; } public string ReleaseGroup { get; set; }
public QualityModel Quality { get; set; } public QualityModel Quality { get; set; }
public int QualityWeight { get; set; } public int QualityWeight { get; set; }
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public MediaInfoResource MediaInfo { get; set; } public MediaInfoResource MediaInfo { get; set; }
public bool QualityCutoffNotMet { get; set; } public bool QualityCutoffNotMet { get; set; }
@ -62,13 +67,17 @@ namespace Lidarr.Api.V1.TrackFiles
}; };
} }
public static TrackFileResource ToResource(this TrackFile model, NzbDrone.Core.Music.Artist artist, IUpgradableSpecification upgradableSpecification) public static TrackFileResource ToResource(this TrackFile model, NzbDrone.Core.Music.Artist artist, IUpgradableSpecification upgradableSpecification, ICustomFormatCalculationService formatCalculationService)
{ {
if (model == null) if (model == null)
{ {
return null; return null;
} }
model.Artist = artist;
var customFormats = formatCalculationService?.ParseCustomFormat(model, model.Artist);
var customFormatScore = artist?.QualityProfile?.Value?.CalculateCustomFormatScore(customFormats) ?? 0;
return new TrackFileResource return new TrackFileResource
{ {
Id = model.Id, Id = model.Id,
@ -83,7 +92,9 @@ namespace Lidarr.Api.V1.TrackFiles
Quality = model.Quality, Quality = model.Quality,
QualityWeight = QualityWeight(model.Quality), QualityWeight = QualityWeight(model.Quality),
MediaInfo = model.MediaInfo.ToResource(), MediaInfo = model.MediaInfo.ToResource(),
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(artist.QualityProfile.Value, model.Quality) QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(artist.QualityProfile.Value, model.Quality),
CustomFormats = customFormats.ToResource(false),
CustomFormatScore = customFormatScore
}; };
} }
} }

@ -3,6 +3,7 @@ using System.Linq;
using Lidarr.Http; using Lidarr.Http;
using Lidarr.Http.REST; using Lidarr.Http.REST;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Music; using NzbDrone.Core.Music;
using NzbDrone.SignalR; using NzbDrone.SignalR;
@ -15,8 +16,9 @@ namespace Lidarr.Api.V1.Tracks
public TrackController(IArtistService artistService, public TrackController(IArtistService artistService,
ITrackService trackService, ITrackService trackService,
IUpgradableSpecification upgradableSpecification, IUpgradableSpecification upgradableSpecification,
ICustomFormatCalculationService formatCalculator,
IBroadcastSignalRMessage signalRBroadcaster) IBroadcastSignalRMessage signalRBroadcaster)
: base(trackService, artistService, upgradableSpecification, signalRBroadcaster) : base(trackService, artistService, upgradableSpecification, formatCalculator, signalRBroadcaster)
{ {
} }

@ -3,6 +3,7 @@ using Lidarr.Api.V1.Artist;
using Lidarr.Api.V1.TrackFiles; using Lidarr.Api.V1.TrackFiles;
using Lidarr.Http.REST; using Lidarr.Http.REST;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
@ -19,16 +20,19 @@ namespace Lidarr.Api.V1.Tracks
protected readonly ITrackService _trackService; protected readonly ITrackService _trackService;
protected readonly IArtistService _artistService; protected readonly IArtistService _artistService;
protected readonly IUpgradableSpecification _upgradableSpecification; protected readonly IUpgradableSpecification _upgradableSpecification;
private readonly ICustomFormatCalculationService _formatCalculator;
protected TrackControllerWithSignalR(ITrackService trackService, protected TrackControllerWithSignalR(ITrackService trackService,
IArtistService artistService, IArtistService artistService,
IUpgradableSpecification upgradableSpecification, IUpgradableSpecification upgradableSpecification,
ICustomFormatCalculationService formatCalculator,
IBroadcastSignalRMessage signalRBroadcaster) IBroadcastSignalRMessage signalRBroadcaster)
: base(signalRBroadcaster) : base(signalRBroadcaster)
{ {
_trackService = trackService; _trackService = trackService;
_artistService = artistService; _artistService = artistService;
_upgradableSpecification = upgradableSpecification; _upgradableSpecification = upgradableSpecification;
_formatCalculator = formatCalculator;
} }
public override TrackResource GetResourceById(int id) public override TrackResource GetResourceById(int id)
@ -53,7 +57,7 @@ namespace Lidarr.Api.V1.Tracks
if (includeTrackFile && track.TrackFileId != 0) if (includeTrackFile && track.TrackFileId != 0)
{ {
resource.TrackFile = track.TrackFile.Value.ToResource(artist, _upgradableSpecification); resource.TrackFile = track.TrackFile.Value.ToResource(artist, _upgradableSpecification, _formatCalculator);
} }
} }
@ -80,7 +84,7 @@ namespace Lidarr.Api.V1.Tracks
if (includeTrackFile && tracks[i].TrackFileId != 0) if (includeTrackFile && tracks[i].TrackFileId != 0)
{ {
resource.TrackFile = tracks[i].TrackFile.Value.ToResource(artist, _upgradableSpecification); resource.TrackFile = tracks[i].TrackFile.Value.ToResource(artist, _upgradableSpecification, _formatCalculator);
} }
} }
} }

Loading…
Cancel
Save