mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-04-24 13:57:11 -04:00
New: Add runtime format option in Settings > UI so users can choose between a mins view and h/m view
This commit is contained in:
parent
361ffe353d
commit
3548433a10
13 changed files with 82 additions and 30 deletions
|
@ -118,7 +118,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.links,
|
.links,
|
||||||
.tags,
|
|
||||||
.rating,
|
.rating,
|
||||||
.year,
|
.year,
|
||||||
.runtime {
|
.runtime {
|
||||||
|
@ -209,10 +208,13 @@
|
||||||
|
|
||||||
.certification,
|
.certification,
|
||||||
.links,
|
.links,
|
||||||
.tags,
|
|
||||||
.rating,
|
.rating,
|
||||||
.year,
|
.year,
|
||||||
.runtime {
|
.runtime {
|
||||||
margin-right: 10px;
|
margin-right: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details {
|
||||||
|
font-size: 19px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,7 +268,8 @@ class MovieDetails extends Component {
|
||||||
nextMovie,
|
nextMovie,
|
||||||
onMonitorTogglePress,
|
onMonitorTogglePress,
|
||||||
onRefreshPress,
|
onRefreshPress,
|
||||||
onSearchPress
|
onSearchPress,
|
||||||
|
movieRuntimeFormat
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -426,7 +427,7 @@ class MovieDetails extends Component {
|
||||||
{
|
{
|
||||||
!!runtime &&
|
!!runtime &&
|
||||||
<span className={styles.runtime}>
|
<span className={styles.runtime}>
|
||||||
{formatRuntime(runtime)}
|
{formatRuntime(runtime, movieRuntimeFormat)}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +466,7 @@ class MovieDetails extends Component {
|
||||||
|
|
||||||
{
|
{
|
||||||
!!tags.length &&
|
!!tags.length &&
|
||||||
<span className={styles.tags}>
|
<span>
|
||||||
<Popover
|
<Popover
|
||||||
anchor={
|
anchor={
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -773,7 +774,8 @@ MovieDetails.propTypes = {
|
||||||
onMonitorTogglePress: PropTypes.func.isRequired,
|
onMonitorTogglePress: PropTypes.func.isRequired,
|
||||||
onRefreshPress: PropTypes.func.isRequired,
|
onRefreshPress: PropTypes.func.isRequired,
|
||||||
onSearchPress: PropTypes.func.isRequired,
|
onSearchPress: PropTypes.func.isRequired,
|
||||||
onGoToMovie: PropTypes.func.isRequired
|
onGoToMovie: PropTypes.func.isRequired,
|
||||||
|
movieRuntimeFormat: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
MovieDetails.defaultProps = {
|
MovieDetails.defaultProps = {
|
||||||
|
|
|
@ -88,7 +88,8 @@ function createMapStateToProps() {
|
||||||
createCommandsSelector(),
|
createCommandsSelector(),
|
||||||
createDimensionsSelector(),
|
createDimensionsSelector(),
|
||||||
(state) => state.app.isSidebarVisible,
|
(state) => state.app.isSidebarVisible,
|
||||||
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, isSidebarVisible) => {
|
(state) => state.settings.ui.item.movieRuntimeFormat,
|
||||||
|
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, isSidebarVisible, movieRuntimeFormat) => {
|
||||||
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
|
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
|
||||||
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
|
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
|
||||||
const movie = sortedMovies[movieIndex];
|
const movie = sortedMovies[movieIndex];
|
||||||
|
@ -160,7 +161,8 @@ function createMapStateToProps() {
|
||||||
previousMovie,
|
previousMovie,
|
||||||
nextMovie,
|
nextMovie,
|
||||||
isSmallScreen: dimensions.isSmallScreen,
|
isSmallScreen: dimensions.isSmallScreen,
|
||||||
isSidebarVisible
|
isSidebarVisible,
|
||||||
|
movieRuntimeFormat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -97,7 +97,8 @@ class MovieIndexRow extends Component {
|
||||||
isSelected,
|
isSelected,
|
||||||
onRefreshMoviePress,
|
onRefreshMoviePress,
|
||||||
onSearchPress,
|
onSearchPress,
|
||||||
onSelectedChange
|
onSelectedChange,
|
||||||
|
movieRuntimeFormat
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -253,7 +254,7 @@ class MovieIndexRow extends Component {
|
||||||
key={name}
|
key={name}
|
||||||
className={styles[name]}
|
className={styles[name]}
|
||||||
>
|
>
|
||||||
{formatRuntime(runtime)}
|
{formatRuntime(runtime, movieRuntimeFormat)}
|
||||||
</VirtualTableRowCell>
|
</VirtualTableRowCell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -462,7 +463,8 @@ MovieIndexRow.propTypes = {
|
||||||
onSelectedChange: PropTypes.func.isRequired,
|
onSelectedChange: PropTypes.func.isRequired,
|
||||||
tmdbId: PropTypes.number.isRequired,
|
tmdbId: PropTypes.number.isRequired,
|
||||||
imdbId: PropTypes.string,
|
imdbId: PropTypes.string,
|
||||||
youTubeTrailerId: PropTypes.string
|
youTubeTrailerId: PropTypes.string,
|
||||||
|
movieRuntimeFormat: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
MovieIndexRow.defaultProps = {
|
MovieIndexRow.defaultProps = {
|
||||||
|
|
|
@ -49,7 +49,8 @@ class MovieIndexTable extends Component {
|
||||||
columns,
|
columns,
|
||||||
selectedState,
|
selectedState,
|
||||||
onSelectedChange,
|
onSelectedChange,
|
||||||
isMovieEditorActive
|
isMovieEditorActive,
|
||||||
|
movieRuntimeFormat
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const movie = items[rowIndex];
|
const movie = items[rowIndex];
|
||||||
|
@ -68,6 +69,7 @@ class MovieIndexTable extends Component {
|
||||||
isSelected={selectedState[movie.id]}
|
isSelected={selectedState[movie.id]}
|
||||||
onSelectedChange={onSelectedChange}
|
onSelectedChange={onSelectedChange}
|
||||||
isMovieEditorActive={isMovieEditorActive}
|
isMovieEditorActive={isMovieEditorActive}
|
||||||
|
movieRuntimeFormat={movieRuntimeFormat}
|
||||||
/>
|
/>
|
||||||
</VirtualTableRow>
|
</VirtualTableRow>
|
||||||
);
|
);
|
||||||
|
@ -135,7 +137,8 @@ MovieIndexTable.propTypes = {
|
||||||
selectedState: PropTypes.object.isRequired,
|
selectedState: PropTypes.object.isRequired,
|
||||||
onSelectedChange: PropTypes.func.isRequired,
|
onSelectedChange: PropTypes.func.isRequired,
|
||||||
onSelectAllChange: PropTypes.func.isRequired,
|
onSelectAllChange: PropTypes.func.isRequired,
|
||||||
isMovieEditorActive: PropTypes.bool.isRequired
|
isMovieEditorActive: PropTypes.bool.isRequired,
|
||||||
|
movieRuntimeFormat: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MovieIndexTable;
|
export default MovieIndexTable;
|
||||||
|
|
|
@ -8,11 +8,13 @@ function createMapStateToProps() {
|
||||||
(state) => state.app.dimensions,
|
(state) => state.app.dimensions,
|
||||||
(state) => state.movieIndex.tableOptions,
|
(state) => state.movieIndex.tableOptions,
|
||||||
(state) => state.movieIndex.columns,
|
(state) => state.movieIndex.columns,
|
||||||
(dimensions, tableOptions, columns) => {
|
(state) => state.settings.ui.item.movieRuntimeFormat,
|
||||||
|
(dimensions, tableOptions, columns, movieRuntimeFormat) => {
|
||||||
return {
|
return {
|
||||||
isSmallScreen: dimensions.isSmallScreen,
|
isSmallScreen: dimensions.isSmallScreen,
|
||||||
showBanners: tableOptions.showBanners,
|
showBanners: tableOptions.showBanners,
|
||||||
columns
|
columns,
|
||||||
|
movieRuntimeFormat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -43,6 +43,11 @@ export const timeFormatOptions = [
|
||||||
{ key: 'HH:mm', value: '17:00/17:30' }
|
{ key: 'HH:mm', value: '17:00/17:30' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const movieRuntimeFormatOptions = [
|
||||||
|
{ key: 'hoursMinutes', value: '1h 15m' },
|
||||||
|
{ key: 'minutes', value: '75 mins' }
|
||||||
|
];
|
||||||
|
|
||||||
class UISettings extends Component {
|
class UISettings extends Component {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -111,9 +116,21 @@ class UISettings extends Component {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
|
||||||
<FieldSet
|
<FieldSet legend={translate('Movies')}>
|
||||||
legend={translate('Dates')}
|
<FormGroup>
|
||||||
>
|
<FormLabel>{translate('SettingsRuntimeFormat')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.SELECT}
|
||||||
|
name="movieRuntimeFormat"
|
||||||
|
values={movieRuntimeFormatOptions}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...settings.movieRuntimeFormat}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FieldSet>
|
||||||
|
|
||||||
|
<FieldSet legend={translate('Dates')}>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>{translate('SettingsShortDateFormat')}</FormLabel>
|
<FormLabel>{translate('SettingsShortDateFormat')}</FormLabel>
|
||||||
|
|
||||||
|
@ -162,9 +179,7 @@ class UISettings extends Component {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
|
||||||
<FieldSet
|
<FieldSet legend={translate('Style')}>
|
||||||
legend={translate('Style')}
|
|
||||||
>
|
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>{translate('SettingsEnableColorImpairedMode')}</FormLabel>
|
<FormLabel>{translate('SettingsEnableColorImpairedMode')}</FormLabel>
|
||||||
<FormInputGroup
|
<FormInputGroup
|
||||||
|
@ -177,9 +192,7 @@ class UISettings extends Component {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
|
||||||
<FieldSet
|
<FieldSet legend={translate('Language')}>
|
||||||
legend={translate('Language')}
|
|
||||||
>
|
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>{translate('SettingsUiLanguage')}</FormLabel>
|
<FormLabel>{translate('SettingsUiLanguage')}</FormLabel>
|
||||||
<FormInputGroup
|
<FormInputGroup
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
function formatRuntime(minutes) {
|
function formatRuntime(minutes, format) {
|
||||||
if (!minutes) {
|
if (!minutes) {
|
||||||
return '0m';
|
return (format === 'hoursMinutes') ? '0m' : '0 mins';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'minutes') {
|
||||||
|
return `${minutes} mins`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const movieHours = Math.floor(minutes / 60);
|
const movieHours = Math.floor(minutes / 60);
|
||||||
const movieMinutes = (minutes <= 59) ? minutes : minutes % 60;
|
const movieMinutes = (minutes <= 59) ? minutes : minutes % 60;
|
||||||
const formattedRuntime = `${((movieHours > 0) ? `${movieHours}h ` : '') + movieMinutes}m`;
|
return `${((movieHours > 0) ? `${movieHours}h ` : '') + movieMinutes}m`;
|
||||||
|
|
||||||
return formattedRuntime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default formatRuntime;
|
export default formatRuntime;
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
using NzbDrone.Common.Http.Proxy;
|
using NzbDrone.Common.Http.Proxy;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Configuration.Events;
|
using NzbDrone.Core.Configuration.Events;
|
||||||
using NzbDrone.Core.Languages;
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
@ -336,6 +337,13 @@ namespace NzbDrone.Core.Configuration
|
||||||
set { SetValue("CalendarWeekColumnHeader", value); }
|
set { SetValue("CalendarWeekColumnHeader", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MovieRuntimeFormatType MovieRuntimeFormat
|
||||||
|
{
|
||||||
|
get { return GetValueEnum("MovieRuntimeFormat", MovieRuntimeFormatType.HoursMinutes); }
|
||||||
|
|
||||||
|
set { SetValue("MovieRuntimeFormat", value); }
|
||||||
|
}
|
||||||
|
|
||||||
public string ShortDateFormat
|
public string ShortDateFormat
|
||||||
{
|
{
|
||||||
get { return GetValue("ShortDateFormat", "MMM D YYYY"); }
|
get { return GetValue("ShortDateFormat", "MMM D YYYY"); }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Common.Http.Proxy;
|
using NzbDrone.Common.Http.Proxy;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||||
using NzbDrone.Core.Security;
|
using NzbDrone.Core.Security;
|
||||||
|
@ -68,6 +69,7 @@ namespace NzbDrone.Core.Configuration
|
||||||
//UI
|
//UI
|
||||||
int FirstDayOfWeek { get; set; }
|
int FirstDayOfWeek { get; set; }
|
||||||
string CalendarWeekColumnHeader { get; set; }
|
string CalendarWeekColumnHeader { get; set; }
|
||||||
|
MovieRuntimeFormatType MovieRuntimeFormat { get; set; }
|
||||||
|
|
||||||
string ShortDateFormat { get; set; }
|
string ShortDateFormat { get; set; }
|
||||||
string LongDateFormat { get; set; }
|
string LongDateFormat { get; set; }
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace NzbDrone.Core.Configuration
|
||||||
|
{
|
||||||
|
public enum MovieRuntimeFormatType
|
||||||
|
{
|
||||||
|
HoursMinutes,
|
||||||
|
Minutes
|
||||||
|
}
|
||||||
|
}
|
|
@ -523,6 +523,7 @@
|
||||||
"SettingsRemotePathMappingLocalPathHelpText": "Path that Radarr should use to access the remote path locally",
|
"SettingsRemotePathMappingLocalPathHelpText": "Path that Radarr should use to access the remote path locally",
|
||||||
"SettingsRemotePathMappingRemotePath": "Remote Path",
|
"SettingsRemotePathMappingRemotePath": "Remote Path",
|
||||||
"SettingsRemotePathMappingRemotePathHelpText": "Root path to the directory that the Download Client accesses",
|
"SettingsRemotePathMappingRemotePathHelpText": "Root path to the directory that the Download Client accesses",
|
||||||
|
"SettingsRuntimeFormat": "Runtime Format",
|
||||||
"SettingsShortDateFormat": "Short Date Format",
|
"SettingsShortDateFormat": "Short Date Format",
|
||||||
"SettingsShowRelativeDates": "Show Relative Dates",
|
"SettingsShowRelativeDates": "Show Relative Dates",
|
||||||
"SettingsShowRelativeDatesHelpText": "Show relative (Today/Yesterday/etc) or absolute dates",
|
"SettingsShowRelativeDatesHelpText": "Show relative (Today/Yesterday/etc) or absolute dates",
|
||||||
|
|
|
@ -9,6 +9,9 @@ namespace Radarr.Api.V3.Config
|
||||||
public int FirstDayOfWeek { get; set; }
|
public int FirstDayOfWeek { get; set; }
|
||||||
public string CalendarWeekColumnHeader { get; set; }
|
public string CalendarWeekColumnHeader { get; set; }
|
||||||
|
|
||||||
|
// Movies
|
||||||
|
public MovieRuntimeFormatType MovieRuntimeFormat { get; set; }
|
||||||
|
|
||||||
//Dates
|
//Dates
|
||||||
public string ShortDateFormat { get; set; }
|
public string ShortDateFormat { get; set; }
|
||||||
public string LongDateFormat { get; set; }
|
public string LongDateFormat { get; set; }
|
||||||
|
@ -28,6 +31,8 @@ namespace Radarr.Api.V3.Config
|
||||||
FirstDayOfWeek = model.FirstDayOfWeek,
|
FirstDayOfWeek = model.FirstDayOfWeek,
|
||||||
CalendarWeekColumnHeader = model.CalendarWeekColumnHeader,
|
CalendarWeekColumnHeader = model.CalendarWeekColumnHeader,
|
||||||
|
|
||||||
|
MovieRuntimeFormat = model.MovieRuntimeFormat,
|
||||||
|
|
||||||
ShortDateFormat = model.ShortDateFormat,
|
ShortDateFormat = model.ShortDateFormat,
|
||||||
LongDateFormat = model.LongDateFormat,
|
LongDateFormat = model.LongDateFormat,
|
||||||
TimeFormat = model.TimeFormat,
|
TimeFormat = model.TimeFormat,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue