New: Show book file details in interactive import and unmapped files

pull/965/head
ta264 4 years ago
parent 9f37b1c484
commit 110e867bd3

@ -6,7 +6,7 @@ import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'
import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription'; import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription';
import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle'; import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; import stripHtml from 'Utilities/String/stripHtml';
import styles from './FileDetails.css'; import styles from './FileDetails.css';
function renderRejections(rejections) { function renderRejections(rejections) {
@ -90,6 +90,20 @@ function FileDetails(props) {
data={audioTags.authorTitle} data={audioTags.authorTitle}
/> />
} }
{
audioTags.seriesTitle !== undefined &&
<DescriptionListItem
title="Series"
data={audioTags.seriesTitle}
/>
}
{
audioTags.seriesIndex !== undefined &&
<DescriptionListItem
title="Series Number"
data={audioTags.seriesIndex}
/>
}
{ {
audioTags.country !== undefined && audioTags.country !== undefined &&
<DescriptionListItem <DescriptionListItem
@ -97,6 +111,13 @@ function FileDetails(props) {
data={audioTags.country.name} data={audioTags.country.name}
/> />
} }
{
audioTags.language !== undefined && audioTags.language !== 'UND' &&
<DescriptionListItem
title="Language"
data={audioTags.language}
/>
}
{ {
audioTags.year > 0 && audioTags.year > 0 &&
<DescriptionListItem <DescriptionListItem
@ -111,6 +132,13 @@ function FileDetails(props) {
data={audioTags.label} data={audioTags.label}
/> />
} }
{
audioTags.publisher !== undefined &&
<DescriptionListItem
title="Publisher"
data={audioTags.publisher}
/>
}
{ {
audioTags.catalogNumber !== undefined && audioTags.catalogNumber !== undefined &&
<DescriptionListItem <DescriptionListItem
@ -121,18 +149,24 @@ function FileDetails(props) {
{ {
audioTags.disambiguation !== undefined && audioTags.disambiguation !== undefined &&
<DescriptionListItem <DescriptionListItem
title="Disambiguation" title="Overview"
data={audioTags.disambiguation} data={stripHtml(audioTags.disambiguation)}
/> />
} }
{ {
audioTags.duration !== undefined && audioTags.isbn !== undefined &&
<DescriptionListItem <DescriptionListItem
title="Duration" title="ISBN"
data={formatTimeSpan(audioTags.duration)} data={audioTags.isbn}
/> />
} }
{ {
audioTags.asin !== undefined &&
<DescriptionListItem
title="ASIN"
data={audioTags.asin}
/>
} {
audioTags.authorMBId !== undefined && audioTags.authorMBId !== undefined &&
<Link <Link
to={`https://musicbrainz.org/author/${audioTags.authorMBId}`} to={`https://musicbrainz.org/author/${audioTags.authorMBId}`}

@ -2,6 +2,7 @@
composes: cell from '~Components/Table/Cells/TableRowCell.css'; composes: cell from '~Components/Table/Cells/TableRowCell.css';
word-break: break-all; word-break: break-all;
cursor: pointer;
} }
.quality { .quality {

@ -1,14 +1,16 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import BookQuality from 'Book/BookQuality'; import BookQuality from 'Book/BookQuality';
import FileDetails from 'BookFile/FileDetails';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableRowCellButton from 'Components/Table/Cells/TableRowCellButton'; import TableRowCellButton from 'Components/Table/Cells/TableRowCellButton';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
import TableRow from 'Components/Table/TableRow'; import TableRow from 'Components/Table/TableRow';
import Popover from 'Components/Tooltip/Popover'; import Popover from 'Components/Tooltip/Popover';
import Tooltip from 'Components/Tooltip/Tooltip'; import Tooltip from 'Components/Tooltip/Tooltip';
import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
import SelectAuthorModal from 'InteractiveImport/Author/SelectAuthorModal'; import SelectAuthorModal from 'InteractiveImport/Author/SelectAuthorModal';
import SelectBookModal from 'InteractiveImport/Book/SelectBookModal'; import SelectBookModal from 'InteractiveImport/Book/SelectBookModal';
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal'; import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
@ -25,6 +27,7 @@ class InteractiveImportRow extends Component {
super(props, context); super(props, context);
this.state = { this.state = {
isDetailsModalOpen: false,
isSelectAuthorModalOpen: false, isSelectAuthorModalOpen: false,
isSelectBookModalOpen: false, isSelectBookModalOpen: false,
isSelectQualityModalOpen: false isSelectQualityModalOpen: false
@ -97,6 +100,14 @@ class InteractiveImportRow extends Component {
// //
// Listeners // Listeners
onDetailsPress = () => {
this.setState({ isDetailsModalOpen: true });
}
onDetailsModalClose = () => {
this.setState({ isDetailsModalOpen: false });
}
onSelectAuthorPress = () => { onSelectAuthorPress = () => {
this.setState({ isSelectAuthorModalOpen: true }); this.setState({ isSelectAuthorModalOpen: true });
} }
@ -139,10 +150,12 @@ class InteractiveImportRow extends Component {
rejections, rejections,
additionalFile, additionalFile,
isSelected, isSelected,
onSelectedChange onSelectedChange,
audioTags
} = this.props; } = this.props;
const { const {
isDetailsModalOpen,
isSelectAuthorModalOpen, isSelectAuthorModalOpen,
isSelectBookModalOpen, isSelectBookModalOpen,
isSelectQualityModalOpen isSelectQualityModalOpen
@ -159,7 +172,7 @@ class InteractiveImportRow extends Component {
const showQualityPlaceholder = isSelected && !quality; const showQualityPlaceholder = isSelected && !quality;
const pathCellContents = ( const pathCellContents = (
<div> <div onClick={this.onDetailsPress}>
{path} {path}
</div> </div>
); );
@ -172,6 +185,13 @@ class InteractiveImportRow extends Component {
/> />
) : pathCellContents; ) : pathCellContents;
const fileDetails = (
<FileDetails
audioTags={audioTags}
filename={path}
/>
);
return ( return (
<TableRow <TableRow
className={additionalFile ? styles.additionalFile : undefined} className={additionalFile ? styles.additionalFile : undefined}
@ -262,6 +282,18 @@ class InteractiveImportRow extends Component {
} }
</TableRowCell> </TableRowCell>
<ConfirmModal
isOpen={isDetailsModalOpen}
title="File Details"
message={fileDetails}
size={sizes.LARGE}
kind={kinds.DEFAULT}
hideCancelButton={true}
confirmLabel="Close"
onConfirm={this.onDetailsModalClose}
onCancel={this.onDetailsModalClose}
/>
<SelectAuthorModal <SelectAuthorModal
isOpen={isSelectAuthorModalOpen} isOpen={isSelectAuthorModalOpen}
ids={[id]} ids={[id]}

@ -1,4 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Books; using NzbDrone.Core.Books;
@ -24,7 +26,7 @@ namespace Readarr.Api.V1.BookFiles
{ {
private readonly IMediaFileService _mediaFileService; private readonly IMediaFileService _mediaFileService;
private readonly IDeleteMediaFiles _mediaFileDeletionService; private readonly IDeleteMediaFiles _mediaFileDeletionService;
private readonly IAudioTagService _audioTagService; private readonly IEBookTagService _eBookTagService;
private readonly IAuthorService _authorService; private readonly IAuthorService _authorService;
private readonly IBookService _bookService; private readonly IBookService _bookService;
private readonly IUpgradableSpecification _upgradableSpecification; private readonly IUpgradableSpecification _upgradableSpecification;
@ -32,7 +34,7 @@ namespace Readarr.Api.V1.BookFiles
public BookFileController(IBroadcastSignalRMessage signalRBroadcaster, public BookFileController(IBroadcastSignalRMessage signalRBroadcaster,
IMediaFileService mediaFileService, IMediaFileService mediaFileService,
IDeleteMediaFiles mediaFileDeletionService, IDeleteMediaFiles mediaFileDeletionService,
IAudioTagService audioTagService, IEBookTagService eBookTagService,
IAuthorService authorService, IAuthorService authorService,
IBookService bookService, IBookService bookService,
IUpgradableSpecification upgradableSpecification) IUpgradableSpecification upgradableSpecification)
@ -40,7 +42,7 @@ namespace Readarr.Api.V1.BookFiles
{ {
_mediaFileService = mediaFileService; _mediaFileService = mediaFileService;
_mediaFileDeletionService = mediaFileDeletionService; _mediaFileDeletionService = mediaFileDeletionService;
_audioTagService = audioTagService; _eBookTagService = eBookTagService;
_authorService = authorService; _authorService = authorService;
_bookService = bookService; _bookService = bookService;
_upgradableSpecification = upgradableSpecification; _upgradableSpecification = upgradableSpecification;
@ -61,7 +63,7 @@ namespace Readarr.Api.V1.BookFiles
public override BookFileResource GetResourceById(int id) public override BookFileResource GetResourceById(int id)
{ {
var resource = MapToResource(_mediaFileService.Get(id)); var resource = MapToResource(_mediaFileService.Get(id));
resource.AudioTags = _audioTagService.ReadTags(resource.Path); resource.AudioTags = _eBookTagService.ReadTags((FileInfoBase)new FileInfo(resource.Path));
return resource; return resource;
} }

Loading…
Cancel
Save