mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-15 09:33:52 -07:00
New: Optionally show Custom Format Score for tracks on Album Details
(cherry picked from commit eadd0c4e101af0386360bbff859f80e008a5be7c) Closes #3872
This commit is contained in:
parent
227217561c
commit
df0097ea03
9 changed files with 97 additions and 11 deletions
|
@ -28,3 +28,9 @@
|
||||||
|
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.customFormatScore {
|
||||||
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
width: 55px;
|
||||||
|
}
|
||||||
|
|
1
frontend/src/Album/Details/TrackRow.css.d.ts
vendored
1
frontend/src/Album/Details/TrackRow.css.d.ts
vendored
|
@ -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…
Add table
Add a link
Reference in a new issue