mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-16 10:03:51 -07:00
Fixed: UI Fixes
This commit is contained in:
parent
718e8d7a9e
commit
94cca69e92
17 changed files with 287 additions and 261 deletions
|
@ -71,7 +71,6 @@ class AddNewArtistSearchResult extends Component {
|
||||||
artistType,
|
artistType,
|
||||||
status,
|
status,
|
||||||
overview,
|
overview,
|
||||||
albumCount,
|
|
||||||
ratings,
|
ratings,
|
||||||
images,
|
images,
|
||||||
isExistingArtist,
|
isExistingArtist,
|
||||||
|
@ -83,11 +82,6 @@ class AddNewArtistSearchResult extends Component {
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const linkProps = isExistingArtist ? { to: `/artist/${foreignArtistId}` } : { onPress: this.onPress };
|
const linkProps = isExistingArtist ? { to: `/artist/${foreignArtistId}` } : { onPress: this.onPress };
|
||||||
let albums = '1 Album';
|
|
||||||
|
|
||||||
if (albumCount > 1) {
|
|
||||||
albums = `${albumCount} Albums`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const height = calculateHeight(230, isSmallScreen);
|
const height = calculateHeight(230, isSmallScreen);
|
||||||
|
|
||||||
|
@ -146,13 +140,6 @@ class AddNewArtistSearchResult extends Component {
|
||||||
</Label>
|
</Label>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
!!albumCount &&
|
|
||||||
<Label size={sizes.LARGE}>
|
|
||||||
{albums}
|
|
||||||
</Label>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
status === 'ended' &&
|
status === 'ended' &&
|
||||||
<Label
|
<Label
|
||||||
|
@ -201,7 +188,6 @@ AddNewArtistSearchResult.propTypes = {
|
||||||
artistType: PropTypes.string,
|
artistType: PropTypes.string,
|
||||||
status: PropTypes.string.isRequired,
|
status: PropTypes.string.isRequired,
|
||||||
overview: PropTypes.string,
|
overview: PropTypes.string,
|
||||||
albumCount: PropTypes.number,
|
|
||||||
ratings: PropTypes.object.isRequired,
|
ratings: PropTypes.object.isRequired,
|
||||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
isExistingArtist: PropTypes.bool.isRequired,
|
isExistingArtist: PropTypes.bool.isRequired,
|
||||||
|
|
|
@ -110,22 +110,6 @@ class InteractiveAlbumSearchModalContent extends Component {
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
{
|
{
|
||||||
isFetching &&
|
|
||||||
<LoadingIndicator />
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!isFetching && !!error &&
|
|
||||||
<div>Unable to load releases.</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
isPopulated && !hasItems && !error &&
|
|
||||||
<div>No results.</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
isPopulated && hasItems && !error &&
|
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.filterMenuContainer}>
|
<div className={styles.filterMenuContainer}>
|
||||||
<FilterMenu
|
<FilterMenu
|
||||||
|
@ -140,10 +124,29 @@ class InteractiveAlbumSearchModalContent extends Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
!!totalReleasesCount && !items.length &&
|
isFetching &&
|
||||||
<div>
|
<LoadingIndicator />
|
||||||
All results are hidden by {filters.length > 1 ? 'filters' : 'a filter'}.
|
}
|
||||||
</div>
|
|
||||||
|
{
|
||||||
|
!isFetching && !!error &&
|
||||||
|
<div>
|
||||||
|
Unable to load results for this album search. Try again later.
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!isFetching && isPopulated && !totalReleasesCount &&
|
||||||
|
<div>
|
||||||
|
No results found.
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!!totalReleasesCount && isPopulated && !items.length &&
|
||||||
|
<div>
|
||||||
|
All results are hidden by {filters.length > 1 ? 'filters' : 'a filter'}.
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,6 +79,8 @@ class ArtistIndexBanner extends Component {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
albumCount,
|
||||||
|
sizeOnDisk,
|
||||||
trackCount,
|
trackCount,
|
||||||
trackFileCount,
|
trackFileCount,
|
||||||
totalTrackCount
|
totalTrackCount
|
||||||
|
@ -189,12 +191,13 @@ class ArtistIndexBanner extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
<ArtistIndexBannerInfo
|
<ArtistIndexBannerInfo
|
||||||
|
albumCount={albumCount}
|
||||||
|
sizeOnDisk={sizeOnDisk}
|
||||||
qualityProfile={qualityProfile}
|
qualityProfile={qualityProfile}
|
||||||
showQualityProfile={showQualityProfile}
|
showQualityProfile={showQualityProfile}
|
||||||
showRelativeDates={showRelativeDates}
|
showRelativeDates={showRelativeDates}
|
||||||
shortDateFormat={shortDateFormat}
|
shortDateFormat={shortDateFormat}
|
||||||
timeFormat={timeFormat}
|
timeFormat={timeFormat}
|
||||||
statistics={statistics}
|
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -242,8 +245,7 @@ ArtistIndexBanner.propTypes = {
|
||||||
|
|
||||||
ArtistIndexBanner.defaultProps = {
|
ArtistIndexBanner.defaultProps = {
|
||||||
trackCount: 0,
|
trackCount: 0,
|
||||||
trackFileCount: 0,
|
trackFileCount: 0
|
||||||
albumCount: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ArtistIndexBanner;
|
export default ArtistIndexBanner;
|
||||||
|
|
|
@ -10,19 +10,15 @@ function ArtistIndexBannerInfo(props) {
|
||||||
showQualityProfile,
|
showQualityProfile,
|
||||||
previousAiring,
|
previousAiring,
|
||||||
added,
|
added,
|
||||||
statistics,
|
albumCount,
|
||||||
path,
|
path,
|
||||||
|
sizeOnDisk,
|
||||||
sortKey,
|
sortKey,
|
||||||
showRelativeDates,
|
showRelativeDates,
|
||||||
shortDateFormat,
|
shortDateFormat,
|
||||||
timeFormat
|
timeFormat
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
|
||||||
albumCount,
|
|
||||||
sizeOnDisk
|
|
||||||
} = statistics;
|
|
||||||
|
|
||||||
if (sortKey === 'qualityProfileId' && !showQualityProfile) {
|
if (sortKey === 'qualityProfileId' && !showQualityProfile) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
|
@ -107,8 +103,9 @@ ArtistIndexBannerInfo.propTypes = {
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
previousAiring: PropTypes.string,
|
previousAiring: PropTypes.string,
|
||||||
added: PropTypes.string,
|
added: PropTypes.string,
|
||||||
statistics: PropTypes.object.isRequired,
|
albumCount: PropTypes.number.isRequired,
|
||||||
path: PropTypes.string.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
|
sizeOnDisk: PropTypes.number,
|
||||||
sortKey: PropTypes.string.isRequired,
|
sortKey: PropTypes.string.isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -95,6 +95,8 @@ class ArtistIndexOverview extends Component {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
albumCount,
|
||||||
|
sizeOnDisk,
|
||||||
trackCount,
|
trackCount,
|
||||||
trackFileCount,
|
trackFileCount,
|
||||||
totalTrackCount
|
totalTrackCount
|
||||||
|
@ -196,11 +198,12 @@ class ArtistIndexOverview extends Component {
|
||||||
height={overviewHeight}
|
height={overviewHeight}
|
||||||
monitored={monitored}
|
monitored={monitored}
|
||||||
nextAiring={nextAiring}
|
nextAiring={nextAiring}
|
||||||
|
albumCount={albumCount}
|
||||||
|
sizeOnDisk={sizeOnDisk}
|
||||||
qualityProfile={qualityProfile}
|
qualityProfile={qualityProfile}
|
||||||
showRelativeDates={showRelativeDates}
|
showRelativeDates={showRelativeDates}
|
||||||
shortDateFormat={shortDateFormat}
|
shortDateFormat={shortDateFormat}
|
||||||
timeFormat={timeFormat}
|
timeFormat={timeFormat}
|
||||||
statistics={statistics}
|
|
||||||
{...overviewOptions}
|
{...overviewOptions}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
/>
|
/>
|
||||||
|
@ -251,8 +254,7 @@ ArtistIndexOverview.propTypes = {
|
||||||
|
|
||||||
ArtistIndexOverview.defaultProps = {
|
ArtistIndexOverview.defaultProps = {
|
||||||
trackCount: 0,
|
trackCount: 0,
|
||||||
trackFileCount: 0,
|
trackFileCount: 0
|
||||||
albumCount: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ArtistIndexOverview;
|
export default ArtistIndexOverview;
|
||||||
|
|
|
@ -5,17 +5,6 @@
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
|
||||||
flex: 0 0 $artistIndexOverviewInfoRowHeight;
|
|
||||||
margin: 2px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin-right: 5px;
|
|
||||||
width: 25px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: $breakpointSmall) {
|
@media only screen and (max-width: $breakpointSmall) {
|
||||||
.infos {
|
.infos {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
|
|
@ -5,190 +5,191 @@ import getRelativeDate from 'Utilities/Date/getRelativeDate';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
import dimensions from 'Styles/Variables/dimensions';
|
import dimensions from 'Styles/Variables/dimensions';
|
||||||
import Icon from 'Components/Icon';
|
import ArtistIndexOverviewInfoRow from './ArtistIndexOverviewInfoRow';
|
||||||
import styles from './ArtistIndexOverviewInfo.css';
|
import styles from './ArtistIndexOverviewInfo.css';
|
||||||
|
|
||||||
const infoRowHeight = parseInt(dimensions.artistIndexOverviewInfoRowHeight);
|
const infoRowHeight = parseInt(dimensions.artistIndexOverviewInfoRowHeight);
|
||||||
|
|
||||||
function isVisible(name, show, value, sortKey, index) {
|
const rows = [
|
||||||
if (value == null) {
|
{
|
||||||
|
name: 'monitored',
|
||||||
|
showProp: 'showMonitored',
|
||||||
|
valueProp: 'monitored'
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'qualityProfileId',
|
||||||
|
showProp: 'showQualityProfile',
|
||||||
|
valueProp: 'qualityProfileId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'added',
|
||||||
|
showProp: 'showAdded',
|
||||||
|
valueProp: 'added'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'albumCount',
|
||||||
|
showProp: 'showAlbumCount',
|
||||||
|
valueProp: 'albumCount'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'path',
|
||||||
|
showProp: 'showPath',
|
||||||
|
valueProp: 'path'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sizeOnDisk',
|
||||||
|
showProp: 'showSizeOnDisk',
|
||||||
|
valueProp: 'sizeOnDisk'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function isVisible(row, props) {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
showProp,
|
||||||
|
valueProp
|
||||||
|
} = row;
|
||||||
|
|
||||||
|
if (props[valueProp] == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return show || sortKey === name;
|
return props[showProp] || props.sortKey === name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInfoRowProps(row, props) {
|
||||||
|
const { name } = row;
|
||||||
|
|
||||||
|
if (name === 'monitored') {
|
||||||
|
const monitoredText = props.monitored ? 'Monitored' : 'Unmonitored';
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: monitoredText,
|
||||||
|
iconName: props.monitored ? icons.MONITORED : icons.UNMONITORED,
|
||||||
|
label: monitoredText
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'qualityProfileId') {
|
||||||
|
return {
|
||||||
|
title: 'Quality PROFILE',
|
||||||
|
iconName: icons.PROFILE,
|
||||||
|
label: props.qualityProfile.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'added') {
|
||||||
|
const {
|
||||||
|
added,
|
||||||
|
shortDateFormat,
|
||||||
|
showRelativeDates,
|
||||||
|
timeFormat
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: 'Added',
|
||||||
|
iconName: icons.ADD,
|
||||||
|
label: getRelativeDate(
|
||||||
|
added,
|
||||||
|
shortDateFormat,
|
||||||
|
showRelativeDates,
|
||||||
|
{
|
||||||
|
timeFormat,
|
||||||
|
timeForToday: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'albumCount') {
|
||||||
|
const { albumCount } = props;
|
||||||
|
let albums = '1 album';
|
||||||
|
|
||||||
|
if (albumCount === 0) {
|
||||||
|
albums = 'No albums';
|
||||||
|
} else if (albumCount > 1) {
|
||||||
|
albums = `${albumCount} albums`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: 'Album Count',
|
||||||
|
iconName: icons.CIRCLE,
|
||||||
|
label: albums
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'path') {
|
||||||
|
return {
|
||||||
|
title: 'Path',
|
||||||
|
iconName: icons.FOLDER,
|
||||||
|
label: props.path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'sizeOnDisk') {
|
||||||
|
return {
|
||||||
|
title: 'Size on Disk',
|
||||||
|
iconName: icons.DRIVE,
|
||||||
|
label: formatBytes(props.sizeOnDisk)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ArtistIndexOverviewInfo(props) {
|
function ArtistIndexOverviewInfo(props) {
|
||||||
const {
|
const {
|
||||||
height,
|
height,
|
||||||
showMonitored,
|
|
||||||
showQualityProfile,
|
|
||||||
showAdded,
|
|
||||||
showAlbumCount,
|
|
||||||
showPath,
|
|
||||||
showSizeOnDisk,
|
|
||||||
monitored,
|
|
||||||
nextAiring,
|
nextAiring,
|
||||||
qualityProfile,
|
|
||||||
added,
|
|
||||||
statistics,
|
|
||||||
path,
|
|
||||||
sortKey,
|
|
||||||
showRelativeDates,
|
showRelativeDates,
|
||||||
shortDateFormat,
|
shortDateFormat,
|
||||||
timeFormat
|
timeFormat
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
let shownRows = 1;
|
||||||
albumCount,
|
|
||||||
sizeOnDisk
|
|
||||||
} = statistics;
|
|
||||||
|
|
||||||
let albums = '1 album';
|
|
||||||
|
|
||||||
if (albumCount === 0) {
|
|
||||||
albums = 'No albums';
|
|
||||||
} else if (albumCount > 1) {
|
|
||||||
albums = `${albumCount} albums`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxRows = Math.floor(height / (infoRowHeight + 4));
|
const maxRows = Math.floor(height / (infoRowHeight + 4));
|
||||||
const monitoredText = monitored ? 'Monitored' : 'Unmonitored';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.infos}>
|
<div className={styles.infos}>
|
||||||
{
|
{
|
||||||
!!nextAiring &&
|
!!nextAiring &&
|
||||||
<div
|
<ArtistIndexOverviewInfoRow
|
||||||
className={styles.info}
|
title={nextAiring}
|
||||||
title="Next Airing"
|
iconName={icons.SCHEDULED}
|
||||||
>
|
label={getRelativeDate(
|
||||||
<Icon
|
nextAiring,
|
||||||
className={styles.icon}
|
shortDateFormat,
|
||||||
name={icons.SCHEDULED}
|
showRelativeDates,
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{
|
{
|
||||||
getRelativeDate(
|
timeFormat,
|
||||||
nextAiring,
|
timeForToday: true
|
||||||
shortDateFormat,
|
|
||||||
showRelativeDates,
|
|
||||||
{
|
|
||||||
timeFormat,
|
|
||||||
timeForToday: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</div>
|
)}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
isVisible('monitored', showMonitored, monitored, sortKey) && maxRows > 1 &&
|
rows.map((row) => {
|
||||||
<div
|
if (!isVisible(row, props)) {
|
||||||
className={styles.info}
|
return null;
|
||||||
title={monitoredText}
|
}
|
||||||
>
|
|
||||||
<Icon
|
if (shownRows >= maxRows) {
|
||||||
className={styles.icon}
|
return null;
|
||||||
name={monitored ? icons.MONITORED : icons.UNMONITORED}
|
}
|
||||||
size={14}
|
|
||||||
|
shownRows++;
|
||||||
|
|
||||||
|
const infoRowProps = getInfoRowProps(row, props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ArtistIndexOverviewInfoRow
|
||||||
|
key={row.name}
|
||||||
|
{...infoRowProps}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
{monitoredText}
|
})
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
isVisible('qualityProfileId', showQualityProfile, qualityProfile, sortKey) && maxRows > 2 &&
|
|
||||||
<div
|
|
||||||
className={styles.info}
|
|
||||||
title="Quality Profile"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={styles.icon}
|
|
||||||
name={icons.PROFILE}
|
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{qualityProfile.name}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
isVisible('added', showAdded, added, sortKey) && maxRows > 3 &&
|
|
||||||
<div
|
|
||||||
className={styles.info}
|
|
||||||
title="Date Added"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={styles.icon}
|
|
||||||
name={icons.ADD}
|
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{
|
|
||||||
getRelativeDate(
|
|
||||||
added,
|
|
||||||
shortDateFormat,
|
|
||||||
showRelativeDates,
|
|
||||||
{
|
|
||||||
timeFormat,
|
|
||||||
timeForToday: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
isVisible('albumCount', showAlbumCount, albumCount, sortKey) && maxRows > 4 &&
|
|
||||||
<div
|
|
||||||
className={styles.info}
|
|
||||||
title="Album Count"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={styles.icon}
|
|
||||||
name={icons.CIRCLE}
|
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{albums}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
isVisible('path', showPath, path, sortKey) && maxRows > 5 &&
|
|
||||||
<div
|
|
||||||
className={styles.info}
|
|
||||||
title="Path"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={styles.icon}
|
|
||||||
name={icons.FOLDER}
|
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{path}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
isVisible('sizeOnDisk', showSizeOnDisk, sizeOnDisk, sortKey) && maxRows > 6 &&
|
|
||||||
<div
|
|
||||||
className={styles.info}
|
|
||||||
title="Size on Disk"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={styles.icon}
|
|
||||||
name={icons.DRIVE}
|
|
||||||
size={14}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{formatBytes(sizeOnDisk)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -207,8 +208,9 @@ ArtistIndexOverviewInfo.propTypes = {
|
||||||
qualityProfile: PropTypes.object.isRequired,
|
qualityProfile: PropTypes.object.isRequired,
|
||||||
previousAiring: PropTypes.string,
|
previousAiring: PropTypes.string,
|
||||||
added: PropTypes.string,
|
added: PropTypes.string,
|
||||||
statistics: PropTypes.object.isRequired,
|
albumCount: PropTypes.number.isRequired,
|
||||||
path: PropTypes.string.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
|
sizeOnDisk: PropTypes.number,
|
||||||
sortKey: PropTypes.string.isRequired,
|
sortKey: PropTypes.string.isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
.infoRow {
|
||||||
|
flex: 0 0 $artistIndexOverviewInfoRowHeight;
|
||||||
|
margin: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
width: 25px !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import Icon from 'Components/Icon';
|
||||||
|
import styles from './ArtistIndexOverviewInfoRow.css';
|
||||||
|
|
||||||
|
function ArtistIndexOverviewInfoRow(props) {
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
iconName,
|
||||||
|
label
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles.infoRow}
|
||||||
|
title={title}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
className={styles.icon}
|
||||||
|
name={iconName}
|
||||||
|
size={14}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArtistIndexOverviewInfoRow.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
iconName: PropTypes.object.isRequired,
|
||||||
|
label: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArtistIndexOverviewInfoRow;
|
|
@ -79,6 +79,8 @@ class ArtistIndexPoster extends Component {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
albumCount,
|
||||||
|
sizeOnDisk,
|
||||||
trackCount,
|
trackCount,
|
||||||
trackFileCount,
|
trackFileCount,
|
||||||
totalTrackCount
|
totalTrackCount
|
||||||
|
@ -188,11 +190,12 @@ class ArtistIndexPoster extends Component {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<ArtistIndexPosterInfo
|
<ArtistIndexPosterInfo
|
||||||
|
albumCount={albumCount}
|
||||||
|
sizeOnDisk={sizeOnDisk}
|
||||||
qualityProfile={qualityProfile}
|
qualityProfile={qualityProfile}
|
||||||
showQualityProfile={showQualityProfile}
|
showQualityProfile={showQualityProfile}
|
||||||
showRelativeDates={showRelativeDates}
|
showRelativeDates={showRelativeDates}
|
||||||
shortDateFormat={shortDateFormat}
|
shortDateFormat={shortDateFormat}
|
||||||
statistics={statistics}
|
|
||||||
timeFormat={timeFormat}
|
timeFormat={timeFormat}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
/>
|
/>
|
||||||
|
@ -241,8 +244,7 @@ ArtistIndexPoster.propTypes = {
|
||||||
|
|
||||||
ArtistIndexPoster.defaultProps = {
|
ArtistIndexPoster.defaultProps = {
|
||||||
trackCount: 0,
|
trackCount: 0,
|
||||||
trackFileCount: 0,
|
trackFileCount: 0
|
||||||
albumCount: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ArtistIndexPoster;
|
export default ArtistIndexPoster;
|
||||||
|
|
|
@ -10,19 +10,15 @@ function ArtistIndexPosterInfo(props) {
|
||||||
showQualityProfile,
|
showQualityProfile,
|
||||||
previousAiring,
|
previousAiring,
|
||||||
added,
|
added,
|
||||||
statistics,
|
albumCount,
|
||||||
path,
|
path,
|
||||||
|
sizeOnDisk,
|
||||||
sortKey,
|
sortKey,
|
||||||
showRelativeDates,
|
showRelativeDates,
|
||||||
shortDateFormat,
|
shortDateFormat,
|
||||||
timeFormat
|
timeFormat
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
|
||||||
albumCount,
|
|
||||||
sizeOnDisk
|
|
||||||
} = statistics;
|
|
||||||
|
|
||||||
if (sortKey === 'qualityProfileId' && !showQualityProfile) {
|
if (sortKey === 'qualityProfileId' && !showQualityProfile) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
|
@ -107,8 +103,9 @@ ArtistIndexPosterInfo.propTypes = {
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
previousAiring: PropTypes.string,
|
previousAiring: PropTypes.string,
|
||||||
added: PropTypes.string,
|
added: PropTypes.string,
|
||||||
statistics: PropTypes.object.isRequired,
|
albumCount: PropTypes.number.isRequired,
|
||||||
path: PropTypes.string.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
|
sizeOnDisk: PropTypes.number,
|
||||||
sortKey: PropTypes.string.isRequired,
|
sortKey: PropTypes.string.isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
.trackCount {
|
.trackCount {
|
||||||
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
flex: 0 0 120px;
|
flex: 0 0 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path {
|
.path {
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
.sizeOnDisk {
|
.sizeOnDisk {
|
||||||
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
flex: 0 0 115px;
|
flex: 0 0 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags {
|
.tags {
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
.trackCount {
|
.trackCount {
|
||||||
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
||||||
|
|
||||||
flex: 0 0 120px;
|
flex: 0 0 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path {
|
.path {
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
.sizeOnDisk {
|
.sizeOnDisk {
|
||||||
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
||||||
|
|
||||||
flex: 0 0 110px;
|
flex: 0 0 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags {
|
.tags {
|
||||||
|
|
|
@ -382,8 +382,7 @@ ArtistIndexRow.propTypes = {
|
||||||
|
|
||||||
ArtistIndexRow.defaultProps = {
|
ArtistIndexRow.defaultProps = {
|
||||||
trackCount: 0,
|
trackCount: 0,
|
||||||
trackFileCount: 0,
|
trackFileCount: 0
|
||||||
albumCount: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ArtistIndexRow;
|
export default ArtistIndexRow;
|
||||||
|
|
|
@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import Measure from 'react-measure';
|
import Measure from 'react-measure';
|
||||||
import { align, icons } from 'Helpers/Props';
|
import { align, icons } from 'Helpers/Props';
|
||||||
import getFilterValue from 'Utilities/Filter/getFilterValue';
|
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||||
|
@ -41,6 +40,10 @@ class CalendarPage extends Component {
|
||||||
this.props.onDaysCountChange(days);
|
this.props.onDaysCountChange(days);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFilterSelect = (selectedFilterKey) => {
|
||||||
|
this.props.onUnmonitoredChange(selectedFilterKey === 'unmonitored');
|
||||||
|
}
|
||||||
|
|
||||||
onGetCalendarLinkPress = () => {
|
onGetCalendarLinkPress = () => {
|
||||||
this.setState({ isCalendarLinkModalOpen: true });
|
this.setState({ isCalendarLinkModalOpen: true });
|
||||||
}
|
}
|
||||||
|
@ -57,8 +60,7 @@ class CalendarPage extends Component {
|
||||||
selectedFilterKey,
|
selectedFilterKey,
|
||||||
filters,
|
filters,
|
||||||
hasArtist,
|
hasArtist,
|
||||||
colorImpairedMode,
|
colorImpairedMode
|
||||||
onFilterSelect
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const isMeasured = this.state.width > 0;
|
const isMeasured = this.state.width > 0;
|
||||||
|
@ -83,10 +85,11 @@ class CalendarPage extends Component {
|
||||||
<PageToolbarSection alignContent={align.RIGHT}>
|
<PageToolbarSection alignContent={align.RIGHT}>
|
||||||
<FilterMenu
|
<FilterMenu
|
||||||
alignMenu={align.RIGHT}
|
alignMenu={align.RIGHT}
|
||||||
|
isDisabled={!hasArtist}
|
||||||
selectedFilterKey={selectedFilterKey}
|
selectedFilterKey={selectedFilterKey}
|
||||||
filters={filters}
|
filters={filters}
|
||||||
customFilters={[]}
|
customFilters={[]}
|
||||||
onFilterSelect={onFilterSelect}
|
onFilterSelect={this.onFilterSelect}
|
||||||
/>
|
/>
|
||||||
</PageToolbarSection>
|
</PageToolbarSection>
|
||||||
</PageToolbar>
|
</PageToolbar>
|
||||||
|
@ -123,7 +126,7 @@ CalendarPage.propTypes = {
|
||||||
hasArtist: PropTypes.bool.isRequired,
|
hasArtist: PropTypes.bool.isRequired,
|
||||||
colorImpairedMode: PropTypes.bool.isRequired,
|
colorImpairedMode: PropTypes.bool.isRequired,
|
||||||
onDaysCountChange: PropTypes.func.isRequired,
|
onDaysCountChange: PropTypes.func.isRequired,
|
||||||
onFilterSelect: PropTypes.func.isRequired
|
onUnmonitoredChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CalendarPage;
|
export default CalendarPage;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions';
|
import { setCalendarDaysCount, setCalendarIncludeUnmonitored } from 'Store/Actions/calendarActions';
|
||||||
import createArtistCountSelector from 'Store/Selectors/createArtistCountSelector';
|
import createArtistCountSelector from 'Store/Selectors/createArtistCountSelector';
|
||||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||||
import CalendarPage from './CalendarPage';
|
import CalendarPage from './CalendarPage';
|
||||||
|
@ -12,8 +12,8 @@ function createMapStateToProps() {
|
||||||
createUISettingsSelector(),
|
createUISettingsSelector(),
|
||||||
(calendar, artistCount, uiSettings) => {
|
(calendar, artistCount, uiSettings) => {
|
||||||
return {
|
return {
|
||||||
filters: calendar.filters,
|
|
||||||
selectedFilterKey: calendar.selectedFilterKey,
|
selectedFilterKey: calendar.selectedFilterKey,
|
||||||
|
filters: calendar.filters,
|
||||||
showUpcoming: calendar.showUpcoming,
|
showUpcoming: calendar.showUpcoming,
|
||||||
colorImpairedMode: uiSettings.enableColorImpairedMode,
|
colorImpairedMode: uiSettings.enableColorImpairedMode,
|
||||||
hasArtist: !!artistCount
|
hasArtist: !!artistCount
|
||||||
|
@ -28,8 +28,8 @@ function createMapDispatchToProps(dispatch, props) {
|
||||||
dispatch(setCalendarDaysCount({ dayCount }));
|
dispatch(setCalendarDaysCount({ dayCount }));
|
||||||
},
|
},
|
||||||
|
|
||||||
onFilterSelect(selectedFilterKey) {
|
onUnmonitoredChange(unmonitored) {
|
||||||
dispatch(setCalendarFilter({ selectedFilterKey }));
|
dispatch(setCalendarIncludeUnmonitored({ unmonitored }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,27 +36,27 @@ export const defaultState = {
|
||||||
error: null,
|
error: null,
|
||||||
items: [],
|
items: [],
|
||||||
|
|
||||||
selectedFilterKey: 'all',
|
selectedFilterKey: 'monitored',
|
||||||
|
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
key: 'all',
|
key: 'monitored',
|
||||||
label: 'All',
|
label: 'Monitored Only',
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
key: 'unmonitored',
|
key: 'monitored',
|
||||||
value: false,
|
value: true,
|
||||||
type: filterTypes.EQUAL
|
type: filterTypes.EQUAL
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'unmonitored',
|
key: 'unmonitored',
|
||||||
label: 'Unmonitored',
|
label: 'Include Unmonitored',
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
key: 'unmonitored',
|
key: 'monitored',
|
||||||
value: true,
|
value: false,
|
||||||
type: filterTypes.EQUAL
|
type: filterTypes.EQUAL
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -66,7 +66,7 @@ export const defaultState = {
|
||||||
|
|
||||||
export const persistState = [
|
export const persistState = [
|
||||||
'calendar.view',
|
'calendar.view',
|
||||||
'calendar.showUpcoming',
|
'calendar.unmonitored',
|
||||||
'calendar.selectedFilterKey'
|
'calendar.selectedFilterKey'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ export const persistState = [
|
||||||
|
|
||||||
export const FETCH_CALENDAR = 'calendar/fetchCalendar';
|
export const FETCH_CALENDAR = 'calendar/fetchCalendar';
|
||||||
export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount';
|
export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount';
|
||||||
|
export const SET_CALENDAR_INCLUDE_UNMONITORED = 'calendar/setCalendarIncludeUnmonitored';
|
||||||
export const SET_CALENDAR_VIEW = 'calendar/setCalendarView';
|
export const SET_CALENDAR_VIEW = 'calendar/setCalendarView';
|
||||||
export const SET_CALENDAR_FILTER = 'calendar/setCalendarFilter';
|
|
||||||
export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday';
|
export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday';
|
||||||
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
|
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
|
||||||
export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange';
|
export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange';
|
||||||
|
@ -182,8 +182,8 @@ function isRangePopulated(start, end, state) {
|
||||||
|
|
||||||
export const fetchCalendar = createThunk(FETCH_CALENDAR);
|
export const fetchCalendar = createThunk(FETCH_CALENDAR);
|
||||||
export const setCalendarDaysCount = createThunk(SET_CALENDAR_DAYS_COUNT);
|
export const setCalendarDaysCount = createThunk(SET_CALENDAR_DAYS_COUNT);
|
||||||
|
export const setCalendarIncludeUnmonitored = createThunk(SET_CALENDAR_INCLUDE_UNMONITORED);
|
||||||
export const setCalendarView = createThunk(SET_CALENDAR_VIEW);
|
export const setCalendarView = createThunk(SET_CALENDAR_VIEW);
|
||||||
export const setCalendarFilter = createThunk(SET_CALENDAR_FILTER);
|
|
||||||
export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY);
|
export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY);
|
||||||
export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE);
|
export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE);
|
||||||
export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE);
|
export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE);
|
||||||
|
@ -196,8 +196,7 @@ export const actionHandlers = handleThunks({
|
||||||
|
|
||||||
[FETCH_CALENDAR]: function(getState, payload, dispatch) {
|
[FETCH_CALENDAR]: function(getState, payload, dispatch) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const selectedFilter = state.calendar.selectedFilterKey;
|
const unmonitored = state.calendar.unmonitored;
|
||||||
const unmonitored = state.calendar.filters.find((f) => f.key === selectedFilter).filters[0].value;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
time,
|
time,
|
||||||
|
@ -274,6 +273,18 @@ export const actionHandlers = handleThunks({
|
||||||
dispatch(fetchCalendar({ time, view }));
|
dispatch(fetchCalendar({ time, view }));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[SET_CALENDAR_INCLUDE_UNMONITORED]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
unmonitored: payload.unmonitored
|
||||||
|
}));
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
const { time, view } = state.calendar;
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
},
|
||||||
|
|
||||||
[SET_CALENDAR_VIEW]: function(getState, payload, dispatch) {
|
[SET_CALENDAR_VIEW]: function(getState, payload, dispatch) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const view = payload.view;
|
const view = payload.view;
|
||||||
|
@ -317,18 +328,6 @@ export const actionHandlers = handleThunks({
|
||||||
const amount = view === calendarViews.FORECAST ? dayCount : 1;
|
const amount = view === calendarViews.FORECAST ? dayCount : 1;
|
||||||
const time = moment(state.calendar.time).add(amount, viewRanges[view]);
|
const time = moment(state.calendar.time).add(amount, viewRanges[view]);
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
},
|
|
||||||
|
|
||||||
[SET_CALENDAR_FILTER]: function(getState, payload, dispatch) {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
selectedFilterKey: payload.selectedFilterKey
|
|
||||||
}));
|
|
||||||
|
|
||||||
const state = getState();
|
|
||||||
const { time, view } = state.calendar;
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
dispatch(fetchCalendar({ time, view }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue