New: Album group improvements on Artist Details page

This commit is contained in:
Qstick 2022-12-11 23:15:36 -06:00
parent 7e10d6b59c
commit 4b367d3129
5 changed files with 205 additions and 28 deletions

View File

@ -0,0 +1,11 @@
.title {
composes: title from '~Components/DescriptionList/DescriptionListItemTitle.css';
width: 90px;
}
.description {
composes: title from '~Components/DescriptionList/DescriptionListItemDescription.css';
margin-left: 110px;
}

View File

@ -0,0 +1,56 @@
import PropTypes from 'prop-types';
import React from 'react';
import DescriptionList from 'Components/DescriptionList/DescriptionList';
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
import formatBytes from 'Utilities/Number/formatBytes';
import styles from './AlbumGroupInfo.css';
function AlbumGroupInfo(props) {
const {
totalAlbumCount,
monitoredAlbumCount,
trackFileCount,
sizeOnDisk
} = props;
return (
<DescriptionList>
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Total"
data={totalAlbumCount}
/>
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Monitored"
data={monitoredAlbumCount}
/>
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Track Files"
data={trackFileCount}
/>
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Size on Disk"
data={formatBytes(sizeOnDisk)}
/>
</DescriptionList>
);
}
AlbumGroupInfo.propTypes = {
totalAlbumCount: PropTypes.number.isRequired,
monitoredAlbumCount: PropTypes.number.isRequired,
trackFileCount: PropTypes.number.isRequired,
sizeOnDisk: PropTypes.number.isRequired
};
export default AlbumGroupInfo;

View File

@ -15,11 +15,10 @@
align-items: center;
width: 100%;
font-size: 24px;
cursor: pointer;
}
.albumTypeLabel {
margin-right: 5px;
margin-right: 10px;
margin-left: 5px;
}
@ -29,10 +28,16 @@
font-size: 18px;
}
.episodeCountTooltip {
.albumCountTooltip {
display: flex;
}
.sizeOnDisk {
margin-left: 10px;
color: #777;
font-size: $defaultFontSize;
}
.expandButton {
composes: link from '~Components/Link/Link.css';
@ -44,7 +49,7 @@
.left {
display: flex;
align-items: center;
flex: 0 1 300px;
flex: 0 1 350px;
}
.left,
@ -103,7 +108,7 @@
top: 50%;
left: 50%;
margin-top: -12px;
margin-left: -15px;
margin-left: -12px;
}
.noAlbums {
@ -122,4 +127,8 @@
position: static;
margin: 0;
}
.sizeOnDisk {
display: none;
}
}

View File

@ -2,18 +2,70 @@ import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import MonitorToggleButton from 'Components/MonitorToggleButton';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import { icons, sortDirections } from 'Helpers/Props';
import Popover from 'Components/Tooltip/Popover';
import { icons, kinds, sizes, sortDirections, tooltipPositions } from 'Helpers/Props';
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
import TrackFileEditorModal from 'TrackFile/Editor/TrackFileEditorModal';
import isBefore from 'Utilities/Date/isBefore';
import formatBytes from 'Utilities/Number/formatBytes';
import translate from 'Utilities/String/translate';
import getToggledRange from 'Utilities/Table/getToggledRange';
import AlbumGroupInfo from './AlbumGroupInfo';
import AlbumRowConnector from './AlbumRowConnector';
import styles from './ArtistDetailsSeason.css';
function getAlbumTypeStatistics(albums) {
let albumCount = 0;
let trackFileCount = 0;
let totalAlbumCount = 0;
let monitoredAlbumCount = 0;
let hasMonitoredAlbums = false;
let sizeOnDisk = 0;
albums.forEach((album) => {
sizeOnDisk = sizeOnDisk + album.statistics.sizeOnDisk;
trackFileCount = trackFileCount + album.statistics.trackFileCount;
if (album.statistics.trackFileCount === album.statistics.totalTrackCount || (album.monitored && isBefore(album.airDateUtc))) {
albumCount++;
}
if (album.monitored) {
monitoredAlbumCount++;
hasMonitoredAlbums = true;
}
totalAlbumCount++;
});
return {
albumCount,
totalAlbumCount,
trackFileCount,
monitoredAlbumCount,
sizeOnDisk,
hasMonitoredAlbums
};
}
function getAlbumCountKind(monitored, albumCount, monitoredAlbumCount) {
if (albumCount === monitoredAlbumCount && monitoredAlbumCount > 0) {
return kinds.SUCCESS;
}
if (!monitored) {
return kinds.WARNING;
}
return kinds.DANGER;
}
class ArtistDetailsSeason extends Component {
//
@ -108,7 +160,13 @@ class ArtistDetailsSeason extends Component {
this.setState({ lastToggledAlbum: albumId });
this.props.onMonitorAlbumPress(_.uniq(albumIds), monitored);
this.props.onMonitorAlbumsPress(_.uniq(albumIds), monitored);
};
onMonitorAlbumsPress = (monitored, { shiftKey }) => {
const albumIds = this.props.items.map((a) => a.id);
this.props.onMonitorAlbumsPress(_.uniq(albumIds), monitored);
};
//
@ -120,7 +178,9 @@ class ArtistDetailsSeason extends Component {
label,
items,
columns,
isSaving,
isExpanded,
artistMonitored,
sortKey,
sortDirection,
onSortPress,
@ -128,6 +188,15 @@ class ArtistDetailsSeason extends Component {
onTableOptionChange
} = this.props;
const {
albumCount,
totalAlbumCount,
trackFileCount,
monitoredAlbumCount,
sizeOnDisk,
hasMonitoredAlbums
} = getAlbumTypeStatistics(items);
const {
isOrganizeModalOpen,
isManageTracksOpen
@ -137,25 +206,55 @@ class ArtistDetailsSeason extends Component {
<div
className={styles.albumType}
>
<Link
className={styles.expandButton}
onPress={this.onExpandPress}
>
<div className={styles.header}>
<div className={styles.left}>
{
<div className={styles.header}>
<div className={styles.left}>
<MonitorToggleButton
monitored={hasMonitoredAlbums}
isDisabled={!artistMonitored}
isSaving={isSaving}
size={24}
onPress={this.onMonitorAlbumsPress}
/>
<span className={styles.albumTypeLabel}>
{label}
</span>
<Popover
className={styles.albumCountTooltip}
anchor={
<Label
size={sizes.LARGE}
kind={getAlbumCountKind(hasMonitoredAlbums, albumCount, monitoredAlbumCount)}
>
<span>{albumCount} / {monitoredAlbumCount}</span>
</Label>
}
title="Group Information"
body={
<div>
<span className={styles.albumTypeLabel}>
{label}
</span>
<span className={styles.albumCount}>
({items.length} Releases)
</span>
<AlbumGroupInfo
totalAlbumCount={totalAlbumCount}
monitoredAlbumCount={monitoredAlbumCount}
trackFileCount={trackFileCount}
sizeOnDisk={sizeOnDisk}
/>
</div>
}
position={tooltipPositions.BOTTOM}
/>
</div>
{
sizeOnDisk ?
<div className={styles.sizeOnDisk}>
{formatBytes(sizeOnDisk)}
</div> :
null
}
</div>
<Link
className={styles.expandButton}
onPress={this.onExpandPress}
>
<Icon
className={styles.expandButtonIcon}
@ -168,9 +267,9 @@ class ArtistDetailsSeason extends Component {
!isSmallScreen &&
<span>&nbsp;</span>
}
</Link>
</div>
</Link>
</div>
<div>
{
@ -238,16 +337,18 @@ ArtistDetailsSeason.propTypes = {
artistId: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
artistMonitored: PropTypes.bool.isRequired,
sortKey: PropTypes.string,
sortDirection: PropTypes.oneOf(sortDirections.all),
items: PropTypes.arrayOf(PropTypes.object).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
isSaving: PropTypes.bool,
isExpanded: PropTypes.bool,
isSmallScreen: PropTypes.bool.isRequired,
onTableOptionChange: PropTypes.func.isRequired,
onExpandPress: PropTypes.func.isRequired,
onSortPress: PropTypes.func.isRequired,
onMonitorAlbumPress: PropTypes.func.isRequired,
onMonitorAlbumsPress: PropTypes.func.isRequired,
uiSettings: PropTypes.object.isRequired
};

View File

@ -36,9 +36,9 @@ function createMapStateToProps() {
return {
items: sortedAlbums,
columns: albums.columns,
artistMonitored: artist.monitored,
sortKey: albums.sortKey,
sortDirection: albums.sortDirection,
artistMonitored: artist.monitored,
isSmallScreen: dimensions.isSmallScreen,
uiSettings
};
@ -66,7 +66,7 @@ class ArtistDetailsSeasonConnector extends Component {
this.props.dispatchSetAlbumSort({ sortKey });
};
onMonitorAlbumPress = (albumIds, monitored) => {
onMonitorAlbumsPress = (albumIds, monitored) => {
this.props.toggleAlbumsMonitored({
albumIds,
monitored
@ -82,7 +82,7 @@ class ArtistDetailsSeasonConnector extends Component {
{...this.props}
onSortPress={this.onSortPress}
onTableOptionChange={this.onTableOptionChange}
onMonitorAlbumPress={this.onMonitorAlbumPress}
onMonitorAlbumsPress={this.onMonitorAlbumsPress}
/>
);
}