Artist index poster improvements

This commit is contained in:
Bogdan 2023-05-30 04:21:15 +03:00
parent f0fceb1499
commit bd5aaf9839
11 changed files with 155 additions and 30 deletions

View File

@ -14,6 +14,7 @@ function createMapStateToProps() {
bannerOptions,
showRelativeDates: uiSettings.showRelativeDates,
shortDateFormat: uiSettings.shortDateFormat,
longDateFormat: uiSettings.longDateFormat,
timeFormat: uiSettings.timeFormat,
isSmallScreen: dimensions.isSmallScreen
};

View File

@ -43,7 +43,7 @@ $hoverScale: 1.05;
font-size: 20px;
}
.nextAiring {
.nextAlbum {
background-color: var(--artistBackgroundColor);
text-align: center;
font-size: $smallFontSize;

View File

@ -7,7 +7,7 @@ interface CssExports {
'controls': string;
'ended': string;
'link': string;
'nextAiring': string;
'nextAlbum': string;
'overlayTitle': string;
'posterContainer': string;
'title': string;

View File

@ -73,7 +73,8 @@ class ArtistIndexPoster extends Component {
monitored,
foreignArtistId,
status,
nextAiring,
nextAlbum,
lastAlbum,
statistics,
images,
posterWidth,
@ -83,9 +84,11 @@ class ArtistIndexPoster extends Component {
showMonitored,
showQualityProfile,
qualityProfile,
showNextAlbum,
showSearchAction,
showRelativeDates,
shortDateFormat,
longDateFormat,
timeFormat,
isRefreshingArtist,
isSearchingArtist,
@ -118,7 +121,7 @@ class ArtistIndexPoster extends Component {
return (
<div>
<div className={styles.content}>
<div className={styles.posterContainer}>
<div className={styles.posterContainer} title={artistName}>
<Label className={styles.controls}>
<SpinnerIconButton
className={styles.action}
@ -193,7 +196,7 @@ class ArtistIndexPoster extends Component {
{
showTitle &&
<div className={styles.title}>
<div className={styles.title} title={artistName}>
{artistName}
</div>
}
@ -207,16 +210,17 @@ class ArtistIndexPoster extends Component {
{
showQualityProfile &&
<div className={styles.title}>
<div className={styles.title} title={translate('QualityProfile')}>
{qualityProfile.name}
</div>
}
{
nextAiring &&
<div className={styles.nextAiring}>
showNextAlbum && !!nextAlbum?.releaseDate &&
<div className={styles.nextAlbum} title={translate('NextAlbum')}>
{
getRelativeDate(
nextAiring,
nextAlbum.releaseDate,
shortDateFormat,
showRelativeDates,
{
@ -228,12 +232,16 @@ class ArtistIndexPoster extends Component {
</div>
}
<ArtistIndexPosterInfo
nextAlbum={nextAlbum}
lastAlbum={lastAlbum}
albumCount={albumCount}
sizeOnDisk={sizeOnDisk}
qualityProfile={qualityProfile}
showQualityProfile={showQualityProfile}
showNextAlbum={showNextAlbum}
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
longDateFormat={longDateFormat}
timeFormat={timeFormat}
{...otherProps}
/>
@ -262,7 +270,8 @@ ArtistIndexPoster.propTypes = {
monitored: PropTypes.bool.isRequired,
status: PropTypes.string.isRequired,
foreignArtistId: PropTypes.string.isRequired,
nextAiring: PropTypes.string,
nextAlbum: PropTypes.object,
lastAlbum: PropTypes.object,
statistics: PropTypes.object.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired,
@ -272,9 +281,11 @@ ArtistIndexPoster.propTypes = {
showMonitored: PropTypes.bool.isRequired,
showQualityProfile: PropTypes.bool.isRequired,
qualityProfile: PropTypes.object.isRequired,
showNextAlbum: PropTypes.bool.isRequired,
showSearchAction: PropTypes.bool.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
isRefreshingArtist: PropTypes.bool.isRequired,
isSearchingArtist: PropTypes.bool.isRequired,

View File

@ -1,38 +1,86 @@
import PropTypes from 'prop-types';
import React from 'react';
import TagListConnector from 'Components/TagListConnector';
import formatDateTime from 'Utilities/Date/formatDateTime';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
import formatBytes from 'Utilities/Number/formatBytes';
import translate from 'Utilities/String/translate';
import styles from './ArtistIndexPosterInfo.css';
function ArtistIndexPosterInfo(props) {
const {
artistType,
qualityProfile,
showQualityProfile,
previousAiring,
showNextAlbum,
nextAlbum,
lastAlbum,
added,
albumCount,
path,
sizeOnDisk,
tags,
sortKey,
showRelativeDates,
shortDateFormat,
longDateFormat,
timeFormat
} = props;
if (sortKey === 'artistType' && artistType) {
return (
<div className={styles.info} title={translate('ArtistType')}>
{artistType}
</div>
);
}
if (sortKey === 'qualityProfileId' && !showQualityProfile) {
return (
<div className={styles.info}>
<div className={styles.info} title={translate('QualityProfile')}>
{qualityProfile.name}
</div>
);
}
if (sortKey === 'previousAiring' && previousAiring) {
if (sortKey === 'nextAlbum' && !showNextAlbum && !!nextAlbum?.releaseDate) {
return (
<div className={styles.info}>
<div
className={styles.info}
title={`${translate('NextAlbum')}: ${formatDateTime(
nextAlbum.releaseDate,
longDateFormat,
timeFormat
)}`}
>
{
getRelativeDate(
previousAiring,
nextAlbum.releaseDate,
shortDateFormat,
showRelativeDates,
{
timeFormat,
timeForToday: true
}
)
}
</div>
);
}
if (sortKey === 'lastAlbum' && !!lastAlbum?.releaseDate) {
return (
<div
className={styles.info}
title={`${translate('LastAlbum')}: ${formatDateTime(
lastAlbum.releaseDate,
longDateFormat,
timeFormat
)}`}
>
{
getRelativeDate(
lastAlbum.releaseDate,
shortDateFormat,
showRelativeDates,
{
@ -57,19 +105,22 @@ function ArtistIndexPosterInfo(props) {
);
return (
<div className={styles.info}>
{`Added ${addedDate}`}
<div
className={styles.info}
title={formatDateTime(added, longDateFormat, timeFormat)}
>
{translate('Added')}: {addedDate}
</div>
);
}
if (sortKey === 'albumCount') {
let albums = '1 album';
let albums = translate('OneAlbum');
if (albumCount === 0) {
albums = 'No albums';
albums = translate('NoAlbums');
} else if (albumCount > 1) {
albums = `${albumCount} albums`;
albums = translate('CountAlbums', [albumCount]);
}
return (
@ -81,7 +132,7 @@ function ArtistIndexPosterInfo(props) {
if (sortKey === 'path') {
return (
<div className={styles.info}>
<div className={styles.info} title={translate('Path')}>
{path}
</div>
);
@ -89,26 +140,41 @@ function ArtistIndexPosterInfo(props) {
if (sortKey === 'sizeOnDisk') {
return (
<div className={styles.info}>
<div className={styles.info} title={translate('SizeOnDisk')}>
{formatBytes(sizeOnDisk)}
</div>
);
}
if (sortKey === 'tags') {
return (
<div className={styles.info} title={translate('Tags')}>
<TagListConnector
tags={tags}
/>
</div>
);
}
return null;
}
ArtistIndexPosterInfo.propTypes = {
artistType: PropTypes.string,
qualityProfile: PropTypes.object.isRequired,
showQualityProfile: PropTypes.bool.isRequired,
previousAiring: PropTypes.string,
showNextAlbum: PropTypes.bool.isRequired,
nextAlbum: PropTypes.object,
lastAlbum: PropTypes.object,
added: PropTypes.string,
albumCount: PropTypes.number.isRequired,
path: PropTypes.string.isRequired,
sizeOnDisk: PropTypes.number,
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired
};

View File

@ -38,7 +38,8 @@ function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions)
detailedProgressBar,
showTitle,
showMonitored,
showQualityProfile
showQualityProfile,
showNextAlbum
} = posterOptions;
const nextAiringHeight = 19;
@ -62,12 +63,19 @@ function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions)
heights.push(19);
}
if (showNextAlbum) {
heights.push(19);
}
switch (sortKey) {
case 'artistType':
case 'lastAlbum':
case 'seasons':
case 'previousAiring':
case 'added':
case 'albumCount':
case 'path':
case 'sizeOnDisk':
case 'tags':
heights.push(19);
break;
case 'qualityProfileId':
@ -75,6 +83,11 @@ function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions)
heights.push(19);
}
break;
case 'nextAlbum':
if (!showNextAlbum) {
heights.push(19);
}
break;
default:
// No need to add a height of 0
}
@ -197,6 +210,7 @@ class ArtistIndexPosters extends Component {
posterOptions,
showRelativeDates,
shortDateFormat,
longDateFormat,
timeFormat
} = this.props;
@ -210,7 +224,8 @@ class ArtistIndexPosters extends Component {
detailedProgressBar,
showTitle,
showMonitored,
showQualityProfile
showQualityProfile,
showNextAlbum
} = posterOptions;
const artist = items[rowIndex * columnCount + columnIndex];
@ -237,8 +252,10 @@ class ArtistIndexPosters extends Component {
showTitle={showTitle}
showMonitored={showMonitored}
showQualityProfile={showQualityProfile}
showNextAlbum={showNextAlbum}
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
longDateFormat={longDateFormat}
timeFormat={timeFormat}
style={style}
artistId={artist.id}
@ -326,8 +343,9 @@ ArtistIndexPosters.propTypes = {
scroller: PropTypes.instanceOf(Element).isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
timeFormat: PropTypes.string.isRequired
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
isSmallScreen: PropTypes.bool.isRequired
};
export default ArtistIndexPosters;

View File

@ -14,6 +14,7 @@ function createMapStateToProps() {
posterOptions,
showRelativeDates: uiSettings.showRelativeDates,
shortDateFormat: uiSettings.shortDateFormat,
longDateFormat: uiSettings.longDateFormat,
timeFormat: uiSettings.timeFormat,
isSmallScreen: dimensions.isSmallScreen
};

View File

@ -33,6 +33,7 @@ class ArtistIndexPosterOptionsModalContent extends Component {
showTitle: props.showTitle,
showMonitored: props.showMonitored,
showQualityProfile: props.showQualityProfile,
showNextAlbum: props.showNextAlbum,
showSearchAction: props.showSearchAction
};
}
@ -44,6 +45,7 @@ class ArtistIndexPosterOptionsModalContent extends Component {
showTitle,
showMonitored,
showQualityProfile,
showNextAlbum,
showSearchAction
} = this.props;
@ -69,6 +71,10 @@ class ArtistIndexPosterOptionsModalContent extends Component {
state.showQualityProfile = showQualityProfile;
}
if (showNextAlbum !== prevProps.showNextAlbum) {
state.showNextAlbum = showNextAlbum;
}
if (showSearchAction !== prevProps.showSearchAction) {
state.showSearchAction = showSearchAction;
}
@ -103,6 +109,7 @@ class ArtistIndexPosterOptionsModalContent extends Component {
showTitle,
showMonitored,
showQualityProfile,
showNextAlbum,
showSearchAction
} = this.state;
@ -184,6 +191,20 @@ class ArtistIndexPosterOptionsModalContent extends Component {
/>
</FormGroup>
<FormGroup>
<FormLabel>
{translate('ShowNextAlbum')}
</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showNextAlbum"
value={showNextAlbum}
helpText={translate('ShowNextAlbumHelpText')}
onChange={this.onChangePosterOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>
{translate('ShowSearch')}
@ -217,6 +238,7 @@ ArtistIndexPosterOptionsModalContent.propTypes = {
showTitle: PropTypes.bool.isRequired,
showMonitored: PropTypes.bool.isRequired,
showQualityProfile: PropTypes.bool.isRequired,
showNextAlbum: PropTypes.bool.isRequired,
detailedProgressBar: PropTypes.bool.isRequired,
showSearchAction: PropTypes.bool.isRequired,
onChangePosterOption: PropTypes.func.isRequired,

View File

@ -89,11 +89,11 @@ export const filterPredicates = {
},
nextAlbum: function(item, filterValue, type) {
return dateFilterPredicate(item.nextAlbum, filterValue, type);
return dateFilterPredicate(item.nextAlbum?.releaseDate, filterValue, type);
},
lastAlbum: function(item, filterValue, type) {
return dateFilterPredicate(item.lastAlbum, filterValue, type);
return dateFilterPredicate(item.lastAlbum?.releaseDate, filterValue, type);
},
added: function(item, filterValue, type) {

View File

@ -29,6 +29,7 @@ export const defaultState = {
showTitle: true,
showMonitored: true,
showQualityProfile: true,
showNextAlbum: true,
showSearchAction: false
},

View File

@ -157,6 +157,7 @@
"CopyUsingHardlinksHelpText": "Hardlinks allow Lidarr to import seeding torrents to the the series folder without taking extra disk space or copying the entire contents of the file. Hardlinks will only work if the source and destination are on the same volume",
"CopyUsingHardlinksHelpTextWarning": "Occasionally, file locks may prevent renaming files that are being seeded. You may temporarily disable seeding and use Lidarr's rename function as a work around.",
"CouldntFindAnyResultsForTerm": "Couldn't find any results for '{0}'",
"CountAlbums": "{0} albums",
"Country": "Country",
"CreateEmptyArtistFolders": "Create empty artist folders",
"CreateEmptyArtistFoldersHelpText": "Create missing artist folders during disk scan",
@ -545,6 +546,7 @@
"NewAlbums": "New Albums",
"NextAlbum": "Next Album",
"NextExecution": "Next Execution",
"NoAlbums": "No albums",
"NoBackupsAreAvailable": "No backups are available",
"NoHistory": "No history.",
"NoLeaveIt": "No, Leave It",
@ -584,6 +586,7 @@
"OnTrackRetagHelpText": "On Track Retag",
"OnUpgrade": "On Upgrade",
"OnUpgradeHelpText": "On Upgrade",
"OneAlbum": "1 album",
"OnlyTorrent": "Only Torrent",
"OnlyUsenet": "Only Usenet",
"OpenBrowserOnStart": "Open browser on start",
@ -804,6 +807,8 @@
"ShowMonitored": "Show Monitored",
"ShowMonitoredHelpText": "Show monitored status under poster",
"ShowName": "Show Name",
"ShowNextAlbum": "Show Next Album",
"ShowNextAlbumHelpText": "Show next album under poster",
"ShowPath": "Show Path",
"ShowQualityProfile": "Show Quality Profile",
"ShowQualityProfileHelpText": "Show quality profile under poster",