New: Optionally show Custom Format Score for episodes on Series Details
This commit is contained in:
parent
ef6ff370ba
commit
eadd0c4e10
|
@ -56,3 +56,9 @@
|
||||||
|
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.customFormatScore {
|
||||||
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
width: 55px;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
interface CssExports {
|
interface CssExports {
|
||||||
'audio': string;
|
'audio': string;
|
||||||
'audioLanguages': string;
|
'audioLanguages': string;
|
||||||
|
'customFormatScore': string;
|
||||||
'episodeNumber': string;
|
'episodeNumber': string;
|
||||||
'episodeNumberAnime': string;
|
'episodeNumberAnime': string;
|
||||||
'languages': string;
|
'languages': string;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import MonitorToggleButton from 'Components/MonitorToggleButton';
|
||||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||||
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 EpisodeFormats from 'Episode/EpisodeFormats';
|
import EpisodeFormats from 'Episode/EpisodeFormats';
|
||||||
import EpisodeNumber from 'Episode/EpisodeNumber';
|
import EpisodeNumber from 'Episode/EpisodeNumber';
|
||||||
import EpisodeSearchCellConnector from 'Episode/EpisodeSearchCellConnector';
|
import EpisodeSearchCellConnector from 'Episode/EpisodeSearchCellConnector';
|
||||||
|
@ -12,7 +13,9 @@ import EpisodeTitleLink from 'Episode/EpisodeTitleLink';
|
||||||
import EpisodeFileLanguageConnector from 'EpisodeFile/EpisodeFileLanguageConnector';
|
import EpisodeFileLanguageConnector from 'EpisodeFile/EpisodeFileLanguageConnector';
|
||||||
import MediaInfoConnector from 'EpisodeFile/MediaInfoConnector';
|
import MediaInfoConnector from 'EpisodeFile/MediaInfoConnector';
|
||||||
import * as mediaInfoTypes from 'EpisodeFile/mediaInfoTypes';
|
import * as mediaInfoTypes from 'EpisodeFile/mediaInfoTypes';
|
||||||
|
import { tooltipPositions } from 'Helpers/Props';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import formatPreferredWordScore from 'Utilities/Number/formatPreferredWordScore';
|
||||||
import formatRuntime from 'Utilities/Number/formatRuntime';
|
import formatRuntime from 'Utilities/Number/formatRuntime';
|
||||||
import styles from './EpisodeRow.css';
|
import styles from './EpisodeRow.css';
|
||||||
|
|
||||||
|
@ -72,6 +75,7 @@ class EpisodeRow extends Component {
|
||||||
episodeFileSize,
|
episodeFileSize,
|
||||||
releaseGroup,
|
releaseGroup,
|
||||||
customFormats,
|
customFormats,
|
||||||
|
customFormatScore,
|
||||||
alternateTitles,
|
alternateTitles,
|
||||||
columns
|
columns
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -193,6 +197,24 @@ class EpisodeRow extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === 'customFormatScore') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.customFormatScore}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
anchor={formatPreferredWordScore(
|
||||||
|
customFormatScore,
|
||||||
|
customFormats.length
|
||||||
|
)}
|
||||||
|
tooltip={<EpisodeFormats formats={customFormats} />}
|
||||||
|
position={tooltipPositions.BOTTOM}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (name === 'languages') {
|
if (name === 'languages') {
|
||||||
return (
|
return (
|
||||||
<TableRowCell
|
<TableRowCell
|
||||||
|
@ -355,6 +377,7 @@ EpisodeRow.propTypes = {
|
||||||
episodeFileSize: PropTypes.number,
|
episodeFileSize: PropTypes.number,
|
||||||
releaseGroup: PropTypes.string,
|
releaseGroup: PropTypes.string,
|
||||||
customFormats: PropTypes.arrayOf(PropTypes.object),
|
customFormats: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
customFormatScore: PropTypes.number.isRequired,
|
||||||
mediaInfo: PropTypes.object,
|
mediaInfo: PropTypes.object,
|
||||||
alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired,
|
alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
|
|
@ -19,6 +19,7 @@ function createMapStateToProps() {
|
||||||
episodeFileSize: episodeFile ? episodeFile.size : null,
|
episodeFileSize: episodeFile ? episodeFile.size : null,
|
||||||
releaseGroup: episodeFile ? episodeFile.releaseGroup : null,
|
releaseGroup: episodeFile ? episodeFile.releaseGroup : null,
|
||||||
customFormats: episodeFile ? episodeFile.customFormats : [],
|
customFormats: episodeFile ? episodeFile.customFormats : [],
|
||||||
|
customFormatScore: episodeFile ? episodeFile.customFormatScore : 0,
|
||||||
alternateTitles: series.alternateTitles
|
alternateTitles: series.alternateTitles
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import React from 'react';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import { batchActions } from 'redux-batched-actions';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
|
import Icon from 'Components/Icon';
|
||||||
import episodeEntities from 'Episode/episodeEntities';
|
import episodeEntities from 'Episode/episodeEntities';
|
||||||
import { sortDirections } from 'Helpers/Props';
|
import { icons, sortDirections } from 'Helpers/Props';
|
||||||
import { createThunk, handleThunks } from 'Store/thunks';
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import { updateItem } from './baseActions';
|
import { updateItem } from './baseActions';
|
||||||
import createFetchHandler from './Creators/createFetchHandler';
|
import createFetchHandler from './Creators/createFetchHandler';
|
||||||
import createHandleActions from './Creators/createHandleActions';
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
@ -109,6 +112,15 @@ export const defaultState = {
|
||||||
label: 'Formats',
|
label: 'Formats',
|
||||||
isVisible: false
|
isVisible: false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'customFormatScore',
|
||||||
|
columnLabel: translate('CustomFormatScore'),
|
||||||
|
label: React.createElement(Icon, {
|
||||||
|
name: icons.SCORE,
|
||||||
|
title: translate('CustomFormatScore')
|
||||||
|
}),
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'status',
|
name: 'status',
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"CountImportListsSelected": "{count} import list(s) selected",
|
"CountImportListsSelected": "{count} import list(s) selected",
|
||||||
"CountIndexersSelected": "{count} indexer(s) selected",
|
"CountIndexersSelected": "{count} indexer(s) selected",
|
||||||
"CountSeasons": "{count} seasons",
|
"CountSeasons": "{count} seasons",
|
||||||
|
"CustomFormatScore": "Custom Format Score",
|
||||||
"Delete": "Delete",
|
"Delete": "Delete",
|
||||||
"DeleteCondition": "Delete Condition",
|
"DeleteCondition": "Delete Condition",
|
||||||
"DeleteConditionMessageText": "Are you sure you want to delete the condition '{0}'?",
|
"DeleteConditionMessageText": "Are you sure you want to delete the condition '{0}'?",
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
||||||
public List<Language> Languages { get; set; }
|
public List<Language> Languages { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public List<CustomFormatResource> CustomFormats { 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; }
|
||||||
|
@ -67,6 +68,8 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
model.Series = series;
|
model.Series = series;
|
||||||
|
var customFormats = formatCalculationService?.ParseCustomFormat(model, model.Series);
|
||||||
|
var customFormatScore = series?.QualityProfile?.Value?.CalculateCustomFormatScore(customFormats) ?? 0;
|
||||||
|
|
||||||
return new EpisodeFileResource
|
return new EpisodeFileResource
|
||||||
{
|
{
|
||||||
|
@ -84,7 +87,8 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
||||||
Quality = model.Quality,
|
Quality = model.Quality,
|
||||||
MediaInfo = model.MediaInfo.ToResource(model.SceneName),
|
MediaInfo = model.MediaInfo.ToResource(model.SceneName),
|
||||||
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(series.QualityProfile.Value, model.Quality),
|
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(series.QualityProfile.Value, model.Quality),
|
||||||
CustomFormats = formatCalculationService.ParseCustomFormat(model).ToResource(false)
|
CustomFormats = customFormats.ToResource(false),
|
||||||
|
CustomFormatScore = customFormatScore
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue