import classNames from 'classnames'; import React, { useCallback, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import AlbumTitleLink from 'Album/AlbumTitleLink'; import { useSelect } from 'App/SelectContext'; import { Statistics } from 'Artist/Artist'; import ArtistBanner from 'Artist/ArtistBanner'; import ArtistNameLink from 'Artist/ArtistNameLink'; import DeleteArtistModal from 'Artist/Delete/DeleteArtistModal'; import EditArtistModalConnector from 'Artist/Edit/EditArtistModalConnector'; import createArtistIndexItemSelector from 'Artist/Index/createArtistIndexItemSelector'; import ArtistIndexProgressBar from 'Artist/Index/ProgressBar/ArtistIndexProgressBar'; import ArtistStatusCell from 'Artist/Index/Table/ArtistStatusCell'; import { ARTIST_SEARCH, REFRESH_ARTIST } from 'Commands/commandNames'; import HeartRating from 'Components/HeartRating'; import IconButton from 'Components/Link/IconButton'; import Link from 'Components/Link/Link'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell'; import Column from 'Components/Table/Column'; import TagListConnector from 'Components/TagListConnector'; import { icons } from 'Helpers/Props'; import { executeCommand } from 'Store/Actions/commandActions'; import { SelectStateInputProps } from 'typings/props'; import formatBytes from 'Utilities/Number/formatBytes'; import firstCharToUpper from 'Utilities/String/firstCharToUpper'; import translate from 'Utilities/String/translate'; import AlbumsCell from './AlbumsCell'; import hasGrowableColumns from './hasGrowableColumns'; import selectTableOptions from './selectTableOptions'; import styles from './ArtistIndexRow.css'; interface ArtistIndexRowProps { artistId: number; sortKey: string; columns: Column[]; isSelectMode: boolean; } function ArtistIndexRow(props: ArtistIndexRowProps) { const { artistId, columns, isSelectMode } = props; const { artist, qualityProfile, metadataProfile, isRefreshingArtist, isSearchingArtist, } = useSelector(createArtistIndexItemSelector(props.artistId)); const { showBanners, showSearchAction } = useSelector(selectTableOptions); const { artistName, foreignArtistId, monitored, status, path, monitorNewItems, nextAlbum, lastAlbum, added, statistics = {} as Statistics, images, artistType, genres = [], ratings, tags = [], isSaving = false, } = artist; const { albumCount = 0, trackCount = 0, trackFileCount = 0, totalTrackCount = 0, sizeOnDisk = 0, } = statistics; const dispatch = useDispatch(); const [hasBannerError, setHasBannerError] = useState(false); const [isEditArtistModalOpen, setIsEditArtistModalOpen] = useState(false); const [isDeleteArtistModalOpen, setIsDeleteArtistModalOpen] = useState(false); const [selectState, selectDispatch] = useSelect(); const onRefreshPress = useCallback(() => { dispatch( executeCommand({ name: REFRESH_ARTIST, artistId, }) ); }, [artistId, dispatch]); const onSearchPress = useCallback(() => { dispatch( executeCommand({ name: ARTIST_SEARCH, artistId, }) ); }, [artistId, dispatch]); const onBannerLoadError = useCallback(() => { setHasBannerError(true); }, [setHasBannerError]); const onBannerLoad = useCallback(() => { setHasBannerError(false); }, [setHasBannerError]); const onEditArtistPress = useCallback(() => { setIsEditArtistModalOpen(true); }, [setIsEditArtistModalOpen]); const onEditArtistModalClose = useCallback(() => { setIsEditArtistModalOpen(false); }, [setIsEditArtistModalOpen]); const onDeleteArtistPress = useCallback(() => { setIsEditArtistModalOpen(false); setIsDeleteArtistModalOpen(true); }, [setIsDeleteArtistModalOpen]); const onDeleteArtistModalClose = useCallback(() => { setIsDeleteArtistModalOpen(false); }, [setIsDeleteArtistModalOpen]); const onSelectedChange = useCallback( ({ id, value, shiftKey }: SelectStateInputProps) => { selectDispatch({ type: 'toggleSelected', id, isSelected: value, shiftKey, }); }, [selectDispatch] ); return ( <> {isSelectMode ? ( ) : null} {columns.map((column) => { const { name, isVisible } = column; if (!isVisible) { return null; } if (name === 'status') { return ( ); } if (name === 'sortName') { return ( {showBanners ? ( {hasBannerError && (
{artistName}
)} ) : ( )}
); } if (name === 'artistType') { return ( {artistType} ); } if (name === 'qualityProfileId') { return ( {qualityProfile?.name ?? ''} ); } if (name === 'metadataProfileId') { return ( {metadataProfile?.name ?? ''} ); } if (name === 'monitorNewItems') { return ( {translate(firstCharToUpper(monitorNewItems))} ); } if (name === 'nextAlbum') { if (nextAlbum) { return ( ); } return ( {translate('None')} ); } if (name === 'lastAlbum') { if (lastAlbum) { return ( ); } return ( {translate('None')} ); } if (name === 'added') { return ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore ts(2739) ); } if (name === 'albumCount') { return ( ); } if (name === 'trackProgress') { return ( ); } if (name === 'trackCount') { return ( {totalTrackCount} ); } if (name === 'path') { return ( {path} ); } if (name === 'sizeOnDisk') { return ( {formatBytes(sizeOnDisk)} ); } if (name === 'genres') { const joinedGenres = genres.join(', '); return ( {joinedGenres} ); } if (name === 'ratings') { return ( ); } if (name === 'tags') { return ( ); } if (name === 'actions') { return ( {showSearchAction ? ( ) : null} ); } return null; })} ); } export default ArtistIndexRow;