mirror of
https://github.com/Radarr/Radarr
synced 2026-05-09 01:33:50 +02:00
New: Original Language and Title sort and filter options
Fixes #7019 Fixes #5438
This commit is contained in:
parent
ccd561eb24
commit
ff7f95a0ab
8 changed files with 102 additions and 0 deletions
|
|
@ -136,6 +136,24 @@ function MovieIndexSortMenu(props) {
|
||||||
>
|
>
|
||||||
{translate('Certification')}
|
{translate('Certification')}
|
||||||
</SortMenuItem>
|
</SortMenuItem>
|
||||||
|
|
||||||
|
<SortMenuItem
|
||||||
|
name="originalTitle"
|
||||||
|
sortKey={sortKey}
|
||||||
|
sortDirection={sortDirection}
|
||||||
|
onPress={onSortSelect}
|
||||||
|
>
|
||||||
|
{translate('OriginalTitle')}
|
||||||
|
</SortMenuItem>
|
||||||
|
|
||||||
|
<SortMenuItem
|
||||||
|
name="originalLanguage"
|
||||||
|
sortKey={sortKey}
|
||||||
|
sortDirection={sortDirection}
|
||||||
|
onPress={onSortSelect}
|
||||||
|
>
|
||||||
|
{translate('OriginalLanguage')}
|
||||||
|
</SortMenuItem>
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
</SortMenu>
|
</SortMenu>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.collection,
|
.collection,
|
||||||
|
.originalTitle,
|
||||||
.sortTitle {
|
.sortTitle {
|
||||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
|
|
@ -23,6 +24,7 @@
|
||||||
flex: 2 0 90px;
|
flex: 2 0 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.originalLanguage,
|
||||||
.qualityProfileId {
|
.qualityProfileId {
|
||||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.collection,
|
.collection,
|
||||||
|
.originalTitle,
|
||||||
.sortTitle {
|
.sortTitle {
|
||||||
composes: cell;
|
composes: cell;
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@
|
||||||
flex: 2 0 90px;
|
flex: 2 0 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.originalLanguage,
|
||||||
.qualityProfileId {
|
.qualityProfileId {
|
||||||
composes: cell;
|
composes: cell;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ class MovieIndexRow extends Component {
|
||||||
year,
|
year,
|
||||||
inCinemas,
|
inCinemas,
|
||||||
physicalRelease,
|
physicalRelease,
|
||||||
|
originalLanguage,
|
||||||
|
originalTitle,
|
||||||
digitalRelease,
|
digitalRelease,
|
||||||
runtime,
|
runtime,
|
||||||
minimumAvailability,
|
minimumAvailability,
|
||||||
|
|
@ -184,6 +186,28 @@ class MovieIndexRow extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === 'originalLanguage') {
|
||||||
|
return (
|
||||||
|
<VirtualTableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles[name]}
|
||||||
|
>
|
||||||
|
{originalLanguage.name}
|
||||||
|
</VirtualTableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'originalTitle') {
|
||||||
|
return (
|
||||||
|
<VirtualTableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles[name]}
|
||||||
|
>
|
||||||
|
{originalTitle}
|
||||||
|
</VirtualTableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (name === 'qualityProfileId') {
|
if (name === 'qualityProfileId') {
|
||||||
return (
|
return (
|
||||||
<VirtualTableRowCell
|
<VirtualTableRowCell
|
||||||
|
|
@ -442,6 +466,8 @@ MovieIndexRow.propTypes = {
|
||||||
status: PropTypes.string.isRequired,
|
status: PropTypes.string.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
titleSlug: PropTypes.string.isRequired,
|
titleSlug: PropTypes.string.isRequired,
|
||||||
|
originalTitle: PropTypes.string.isRequired,
|
||||||
|
originalLanguage: PropTypes.object.isRequired,
|
||||||
studio: PropTypes.string,
|
studio: PropTypes.string,
|
||||||
collection: PropTypes.object,
|
collection: PropTypes.object,
|
||||||
qualityProfile: PropTypes.object.isRequired,
|
qualityProfile: PropTypes.object.isRequired,
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,13 @@ export const filterPredicates = {
|
||||||
return predicate(collection ? collection.name : '', filterValue);
|
return predicate(collection ? collection.name : '', filterValue);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
originalLanguage: function(item, filterValue, type) {
|
||||||
|
const predicate = filterTypePredicates[type];
|
||||||
|
const { originalLanguage } = item;
|
||||||
|
|
||||||
|
return predicate(originalLanguage ? originalLanguage.name : '', filterValue);
|
||||||
|
},
|
||||||
|
|
||||||
inCinemas: function(item, filterValue, type) {
|
inCinemas: function(item, filterValue, type) {
|
||||||
return dateFilterPredicate(item.inCinemas, filterValue, type);
|
return dateFilterPredicate(item.inCinemas, filterValue, type);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,12 @@ export const defaultState = {
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
isModifiable: false
|
isModifiable: false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'originalTitle',
|
||||||
|
label: translate('OriginalTitle'),
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'collection',
|
name: 'collection',
|
||||||
label: translate('Collection'),
|
label: translate('Collection'),
|
||||||
|
|
@ -99,6 +105,12 @@ export const defaultState = {
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'originalLanguage',
|
||||||
|
label: translate('OriginalLanguage'),
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'added',
|
name: 'added',
|
||||||
label: translate('Added'),
|
label: translate('Added'),
|
||||||
|
|
@ -206,6 +218,12 @@ export const defaultState = {
|
||||||
return collection.name;
|
return collection.name;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
originalLanguage: function(item) {
|
||||||
|
const { originalLanguage ={} } = item;
|
||||||
|
|
||||||
|
return originalLanguage.name;
|
||||||
|
},
|
||||||
|
|
||||||
ratings: function(item) {
|
ratings: function(item) {
|
||||||
const { ratings = {} } = item;
|
const { ratings = {} } = item;
|
||||||
|
|
||||||
|
|
@ -242,6 +260,30 @@ export const defaultState = {
|
||||||
label: translate('Title'),
|
label: translate('Title'),
|
||||||
type: filterBuilderTypes.STRING
|
type: filterBuilderTypes.STRING
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'originalTitle',
|
||||||
|
label: translate('OriginalTitle'),
|
||||||
|
type: filterBuilderTypes.STRING
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'originalLanguage',
|
||||||
|
label: translate('OriginalLanguage'),
|
||||||
|
type: filterBuilderTypes.EXACT,
|
||||||
|
optionsSelector: function(items) {
|
||||||
|
const collectionList = items.reduce((acc, movie) => {
|
||||||
|
if (movie.originalLanguage) {
|
||||||
|
acc.push({
|
||||||
|
id: movie.originalLanguage.name,
|
||||||
|
name: movie.originalLanguage.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return collectionList.sort(sortByName);
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'status',
|
name: 'status',
|
||||||
label: translate('ReleaseStatus'),
|
label: translate('ReleaseStatus'),
|
||||||
|
|
|
||||||
|
|
@ -645,6 +645,8 @@
|
||||||
"OpenThisModal": "Open This Modal",
|
"OpenThisModal": "Open This Modal",
|
||||||
"Options": "Options",
|
"Options": "Options",
|
||||||
"Organize": "Organize",
|
"Organize": "Organize",
|
||||||
|
"OriginalTitle": "Original Title",
|
||||||
|
"OriginalLanguage": "Original Language",
|
||||||
"OrganizeAndRename": "Organize & Rename",
|
"OrganizeAndRename": "Organize & Rename",
|
||||||
"OrganizeConfirm": "Are you sure you want to organize all files in the {0} selected movie(s)?",
|
"OrganizeConfirm": "Are you sure you want to organize all files in the {0} selected movie(s)?",
|
||||||
"OrganizeModalAllPathsRelative": "All paths are relative to:",
|
"OrganizeModalAllPathsRelative": "All paths are relative to:",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.Translations;
|
using NzbDrone.Core.Movies.Translations;
|
||||||
|
|
@ -26,6 +27,7 @@ public MovieResource()
|
||||||
//View Only
|
//View Only
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string OriginalTitle { get; set; }
|
public string OriginalTitle { get; set; }
|
||||||
|
public Language OriginalLanguage { get; set; }
|
||||||
public List<AlternativeTitleResource> AlternateTitles { get; set; }
|
public List<AlternativeTitleResource> AlternateTitles { get; set; }
|
||||||
public int? SecondaryYear { get; set; }
|
public int? SecondaryYear { get; set; }
|
||||||
public int SecondaryYearSourceId { get; set; }
|
public int SecondaryYearSourceId { get; set; }
|
||||||
|
|
@ -96,6 +98,7 @@ public static MovieResource ToResource(this Movie model, int availDelay, MovieTr
|
||||||
TmdbId = model.TmdbId,
|
TmdbId = model.TmdbId,
|
||||||
Title = translatedTitle,
|
Title = translatedTitle,
|
||||||
OriginalTitle = model.OriginalTitle,
|
OriginalTitle = model.OriginalTitle,
|
||||||
|
OriginalLanguage = model.OriginalLanguage,
|
||||||
SortTitle = translatedTitle.NormalizeTitle(),
|
SortTitle = translatedTitle.NormalizeTitle(),
|
||||||
InCinemas = model.InCinemas,
|
InCinemas = model.InCinemas,
|
||||||
PhysicalRelease = model.PhysicalRelease,
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue