import _ from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import TextTruncate from 'react-text-truncate'; import ArtistPoster from 'Artist/ArtistPoster'; import DeleteArtistModal from 'Artist/Delete/DeleteArtistModal'; import EditArtistModalConnector from 'Artist/Edit/EditArtistModalConnector'; import ArtistHistoryModal from 'Artist/History/ArtistHistoryModal'; import ArtistInteractiveSearchModalConnector from 'Artist/Search/ArtistInteractiveSearchModalConnector'; import HeartRating from 'Components/HeartRating'; import Icon from 'Components/Icon'; import Label from 'Components/Label'; import IconButton from 'Components/Link/IconButton'; import Link from 'Components/Link/Link'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import MonitorToggleButton from 'Components/MonitorToggleButton'; import PageContent from 'Components/Page/PageContent'; import PageContentBody from 'Components/Page/PageContentBody'; import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; import Popover from 'Components/Tooltip/Popover'; import Tooltip from 'Components/Tooltip/Tooltip'; import { align, icons, kinds, sizes, tooltipPositions } from 'Helpers/Props'; import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector'; import RetagPreviewModalConnector from 'Retag/RetagPreviewModalConnector'; import QualityProfileNameConnector from 'Settings/Profiles/Quality/QualityProfileNameConnector'; import fonts from 'Styles/Variables/fonts'; import TrackFileEditorModal from 'TrackFile/Editor/TrackFileEditorModal'; import formatBytes from 'Utilities/Number/formatBytes'; import selectAll from 'Utilities/Table/selectAll'; import toggleSelected from 'Utilities/Table/toggleSelected'; import InteractiveImportModal from '../../InteractiveImport/InteractiveImportModal'; import ArtistAlternateTitles from './ArtistAlternateTitles'; import ArtistDetailsLinks from './ArtistDetailsLinks'; import ArtistDetailsSeasonConnector from './ArtistDetailsSeasonConnector'; import ArtistTagsConnector from './ArtistTagsConnector'; import styles from './ArtistDetails.css'; const defaultFontSize = parseInt(fonts.defaultFontSize); const lineHeight = parseFloat(fonts.lineHeight); function getFanartUrl(images) { const fanartImage = _.find(images, { coverType: 'fanart' }); if (fanartImage) { // Remove protocol return fanartImage.url.replace(/^https?:/, ''); } } function getExpandedState(newState) { return { allExpanded: newState.allSelected, allCollapsed: newState.allUnselected, expandedState: newState.selectedState }; } class ArtistDetails extends Component { // // Lifecycle constructor(props, context) { super(props, context); this.state = { isOrganizeModalOpen: false, isRetagModalOpen: false, isManageTracksOpen: false, isEditArtistModalOpen: false, isDeleteArtistModalOpen: false, isArtistHistoryModalOpen: false, isInteractiveImportModalOpen: false, isInteractiveSearchModalOpen: false, allExpanded: false, allCollapsed: false, expandedState: {} }; } // // Listeners onOrganizePress = () => { this.setState({ isOrganizeModalOpen: true }); } onOrganizeModalClose = () => { this.setState({ isOrganizeModalOpen: false }); } onRetagPress = () => { this.setState({ isRetagModalOpen: true }); } onRetagModalClose = () => { this.setState({ isRetagModalOpen: false }); } onManageTracksPress = () => { this.setState({ isManageTracksOpen: true }); } onManageTracksModalClose = () => { this.setState({ isManageTracksOpen: false }); } onInteractiveImportPress = () => { this.setState({ isInteractiveImportModalOpen: true }); } onInteractiveImportModalClose = () => { this.setState({ isInteractiveImportModalOpen: false }); } onInteractiveSearchPress = () => { this.setState({ isInteractiveSearchModalOpen: true }); } onInteractiveSearchModalClose = () => { this.setState({ isInteractiveSearchModalOpen: false }); } onEditArtistPress = () => { this.setState({ isEditArtistModalOpen: true }); } onEditArtistModalClose = () => { this.setState({ isEditArtistModalOpen: false }); } onDeleteArtistPress = () => { this.setState({ isEditArtistModalOpen: false, isDeleteArtistModalOpen: true }); } onDeleteArtistModalClose = () => { this.setState({ isDeleteArtistModalOpen: false }); } onArtistHistoryPress = () => { this.setState({ isArtistHistoryModalOpen: true }); } onArtistHistoryModalClose = () => { this.setState({ isArtistHistoryModalOpen: false }); } onExpandAllPress = () => { const { allExpanded, expandedState } = this.state; this.setState(getExpandedState(selectAll(expandedState, !allExpanded))); } onExpandPress = (albumId, isExpanded) => { this.setState((state) => { const convertedState = { allSelected: state.allExpanded, allUnselected: state.allCollapsed, selectedState: state.expandedState }; const newState = toggleSelected(convertedState, [], albumId, isExpanded, false); return getExpandedState(newState); }); } // // Render render() { const { id, foreignArtistId, artistName, ratings, path, statistics, qualityProfileId, monitored, albumTypes, status, overview, links, images, artistType, alternateTitles, tags, isSaving, isRefreshing, isSearching, isFetching, isPopulated, albumsError, trackFilesError, hasAlbums, hasMonitoredAlbums, hasTrackFiles, previousArtist, nextArtist, onMonitorTogglePress, onRefreshPress, onSearchPress } = this.props; const { trackFileCount, sizeOnDisk } = statistics; const { isOrganizeModalOpen, isRetagModalOpen, isManageTracksOpen, isEditArtistModalOpen, isDeleteArtistModalOpen, isArtistHistoryModalOpen, isInteractiveImportModalOpen, isInteractiveSearchModalOpen, allExpanded, allCollapsed, expandedState } = this.state; const continuing = status === 'continuing'; const endedString = artistType === 'Person' ? 'Deceased' : 'Ended'; let trackFilesCountMessage = 'No track files'; if (trackFileCount === 1) { trackFilesCountMessage = '1 track file'; } else if (trackFileCount > 1) { trackFilesCountMessage = `${trackFileCount} track files`; } let expandIcon = icons.EXPAND_INDETERMINATE; if (allExpanded) { expandIcon = icons.COLLAPSE; } else if (allCollapsed) { expandIcon = icons.EXPAND; } return (
{artistName}
{ !!alternateTitles.length &&
} title="Alternate Titles" body={} position={tooltipPositions.BOTTOM} />
}
Links } tooltip={ } kind={kinds.INVERSE} position={tooltipPositions.BOTTOM} /> { !!tags.length && Tags } tooltip={} kind={kinds.INVERSE} position={tooltipPositions.BOTTOM} /> }
{ !isPopulated && !albumsError && !trackFilesError && } { !isFetching && albumsError &&
Loading albums failed
} { !isFetching && trackFilesError &&
Loading track files failed
} { isPopulated && !!albumTypes.length &&
{ albumTypes.slice(0).map((albumType) => { return ( ); }) }
}
Missing Albums, Singles, or Other Types? Modify or create a new Metadata Profile or manually Search for new items!
); } } ArtistDetails.propTypes = { id: PropTypes.number.isRequired, foreignArtistId: PropTypes.string.isRequired, artistName: PropTypes.string.isRequired, ratings: PropTypes.object.isRequired, path: PropTypes.string.isRequired, statistics: PropTypes.object.isRequired, qualityProfileId: PropTypes.number.isRequired, monitored: PropTypes.bool.isRequired, artistType: PropTypes.string, albumTypes: PropTypes.arrayOf(PropTypes.string), status: PropTypes.string.isRequired, overview: PropTypes.string.isRequired, links: PropTypes.arrayOf(PropTypes.object).isRequired, images: PropTypes.arrayOf(PropTypes.object).isRequired, alternateTitles: PropTypes.arrayOf(PropTypes.string).isRequired, tags: PropTypes.arrayOf(PropTypes.number).isRequired, isSaving: PropTypes.bool.isRequired, isRefreshing: PropTypes.bool.isRequired, isSearching: PropTypes.bool.isRequired, isFetching: PropTypes.bool.isRequired, isPopulated: PropTypes.bool.isRequired, albumsError: PropTypes.object, trackFilesError: PropTypes.object, hasAlbums: PropTypes.bool.isRequired, hasMonitoredAlbums: PropTypes.bool.isRequired, hasTrackFiles: PropTypes.bool.isRequired, previousArtist: PropTypes.object.isRequired, nextArtist: PropTypes.object.isRequired, onMonitorTogglePress: PropTypes.func.isRequired, onRefreshPress: PropTypes.func.isRequired, onSearchPress: PropTypes.func.isRequired }; ArtistDetails.defaultProps = { statistics: {}, tags: [], isSaving: false }; export default ArtistDetails;