New: Readarr 0.1

This commit is contained in:
ta264
2020-05-06 21:14:11 +01:00
parent 476f2d6047
commit 08496c82af
911 changed files with 14837 additions and 24442 deletions
@@ -1,34 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import TrackFileEditorModalContentConnector from './TrackFileEditorModalContentConnector';
function TrackFileEditorModal(props) {
const {
isOpen,
onModalClose,
...otherProps
} = props;
return (
<Modal
isOpen={isOpen}
onModalClose={onModalClose}
>
{
isOpen &&
<TrackFileEditorModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
}
</Modal>
);
}
TrackFileEditorModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default TrackFileEditorModal;
@@ -1,6 +1,5 @@
import PropTypes from 'prop-types';
import React from 'react';
import padNumber from 'Utilities/Number/padNumber';
import TableRow from 'Components/Table/TableRow';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
@@ -9,7 +8,6 @@ import TrackQuality from 'Album/TrackQuality';
function TrackFileEditorRow(props) {
const {
id,
trackNumber,
path,
quality,
isSelected,
@@ -23,11 +21,6 @@ function TrackFileEditorRow(props) {
isSelected={isSelected}
onSelectedChange={onSelectedChange}
/>
<TableRowCell>
{padNumber(trackNumber, 2)}
</TableRowCell>
<TableRowCell>
{path}
</TableRowCell>
@@ -43,7 +36,6 @@ function TrackFileEditorRow(props) {
TrackFileEditorRow.propTypes = {
id: PropTypes.number.isRequired,
trackNumber: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
quality: PropTypes.object.isRequired,
isSelected: PropTypes.bool,
@@ -0,0 +1,16 @@
import React from 'react';
import TrackFileEditorTableContentConnector from './TrackFileEditorTableContentConnector';
function TrackFileEditorTable(props) {
const {
...otherProps
} = props;
return (
<TrackFileEditorTableContentConnector
{...otherProps}
/>
);
}
export default TrackFileEditorTable;
@@ -8,25 +8,15 @@ import selectAll from 'Utilities/Table/selectAll';
import toggleSelected from 'Utilities/Table/toggleSelected';
import { kinds } from 'Helpers/Props';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import Button from 'Components/Link/Button';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import SpinnerButton from 'Components/Link/SpinnerButton';
import SelectInput from 'Components/Form/SelectInput';
import ModalContent from 'Components/Modal/ModalContent';
import ModalHeader from 'Components/Modal/ModalHeader';
import ModalBody from 'Components/Modal/ModalBody';
import ModalFooter from 'Components/Modal/ModalFooter';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import TrackFileEditorRow from './TrackFileEditorRow';
import styles from './TrackFileEditorModalContent.css';
import styles from './TrackFileEditorTableContent.css';
const columns = [
{
name: 'trackNumber',
label: 'Track',
isVisible: true
},
{
name: 'path',
label: 'Path',
@@ -39,7 +29,7 @@ const columns = [
}
];
class TrackFileEditorModalContent extends Component {
class TrackFileEditorTableContent extends Component {
//
// Lifecycle
@@ -127,8 +117,7 @@ class TrackFileEditorModalContent extends Component {
isPopulated,
error,
items,
qualities,
onModalClose
qualities
} = this.props;
const {
@@ -150,88 +139,74 @@ class TrackFileEditorModalContent extends Component {
const hasSelectedFiles = this.getSelectedIds().length > 0;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Manage Tracks
</ModalHeader>
<>
{
isFetching && !isPopulated ?
<LoadingIndicator /> :
null
}
<ModalBody>
{
isFetching && !isPopulated ?
<LoadingIndicator /> :
null
}
{
!isFetching && error ?
<div>{error}</div> :
null
}
{
!isFetching && error ?
<div>{error}</div> :
null
}
{
isPopulated && !items.length ?
<div>
No track files to manage.
</div> :
null
}
{
isPopulated && !items.length ?
<div>
No track files to manage.
</div> :
null
}
{
isPopulated && items.length ?
<Table
columns={columns}
selectAll={true}
allSelected={allSelected}
allUnselected={allUnselected}
onSelectAllChange={this.onSelectAllChange}
>
<TableBody>
{
items.map((item) => {
return (
<TrackFileEditorRow
key={item.id}
isSelected={selectedState[item.id]}
{...item}
onSelectedChange={this.onSelectedChange}
/>
);
})
}
</TableBody>
</Table> :
null
}
</ModalBody>
<ModalFooter>
<div className={styles.actions}>
<SpinnerButton
kind={kinds.DANGER}
isSpinning={isDeleting}
isDisabled={!hasSelectedFiles}
onPress={this.onDeletePress}
{
isPopulated && items.length ?
<Table
columns={columns}
selectAll={true}
allSelected={allSelected}
allUnselected={allUnselected}
onSelectAllChange={this.onSelectAllChange}
>
Delete
</SpinnerButton>
<TableBody>
{
items.map((item) => {
return (
<TrackFileEditorRow
key={item.id}
isSelected={selectedState[item.id]}
{...item}
onSelectedChange={this.onSelectedChange}
/>
);
})
}
</TableBody>
</Table> :
null
}
<div className={styles.selectInput}>
<SelectInput
name="quality"
value="selectQuality"
values={qualityOptions}
isDisabled={!hasSelectedFiles}
onChange={this.onQualityChange}
/>
</div>
</div>
<Button
onPress={onModalClose}
<div className={styles.actions}>
<SpinnerButton
kind={kinds.DANGER}
isSpinning={isDeleting}
isDisabled={!hasSelectedFiles}
onPress={this.onDeletePress}
>
Close
</Button>
</ModalFooter>
Delete
</SpinnerButton>
<div className={styles.selectInput}>
<SelectInput
name="quality"
value="selectQuality"
values={qualityOptions}
isDisabled={!hasSelectedFiles}
onChange={this.onQualityChange}
/>
</div>
</div>
<ConfirmModal
isOpen={isConfirmDeleteModalOpen}
@@ -242,12 +217,12 @@ class TrackFileEditorModalContent extends Component {
onConfirm={this.onConfirmDelete}
onCancel={this.onConfirmDeleteModalClose}
/>
</ModalContent>
</>
);
}
}
TrackFileEditorModalContent.propTypes = {
TrackFileEditorTableContent.propTypes = {
isDeleting: PropTypes.bool.isRequired,
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired,
@@ -255,8 +230,7 @@ TrackFileEditorModalContent.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
onDeletePress: PropTypes.func.isRequired,
onQualityChange: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
onQualityChange: PropTypes.func.isRequired
};
export default TrackFileEditorModalContent;
export default TrackFileEditorTableContent;
@@ -9,7 +9,7 @@ import createArtistSelector from 'Store/Selectors/createArtistSelector';
import { deleteTrackFiles, updateTrackFiles } from 'Store/Actions/trackFileActions';
import { fetchTracks, clearTracks } from 'Store/Actions/trackActions';
import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
import TrackFileEditorModalContent from './TrackFileEditorModalContent';
import TrackFileEditorTableContent from './TrackFileEditorTableContent';
function createSchemaSelector() {
return createSelector(
@@ -35,45 +35,19 @@ function createSchemaSelector() {
function createMapStateToProps() {
return createSelector(
(state, { albumId }) => albumId,
(state) => state.tracks,
(state, { bookId }) => bookId,
(state) => state.trackFiles,
createSchemaSelector(),
createArtistSelector(),
(
albumId,
tracks,
bookId,
trackFiles,
schema,
artist
) => {
const filtered = _.filter(tracks.items, (track) => {
if (albumId >= 0 && track.albumId !== albumId) {
return false;
}
if (!track.trackFileId) {
return false;
}
return _.some(trackFiles.items, { id: track.trackFileId });
});
const sorted = _.orderBy(filtered, ['albumId', 'absoluteTrackNumber'], ['desc', 'asc']);
const items = _.map(sorted, (track) => {
const trackFile = _.find(trackFiles.items, { id: track.trackFileId });
return {
path: trackFile.path,
quality: trackFile.quality,
...track
};
});
return {
...schema,
items,
items: trackFiles.items,
artistType: artist.artistType,
isDeleting: trackFiles.isDeleting,
isSaving: trackFiles.isSaving
@@ -106,24 +80,15 @@ function createMapDispatchToProps(dispatch, props) {
};
}
class TrackFileEditorModalContentConnector extends Component {
class TrackFileEditorTableContentConnector extends Component {
//
// Lifecycle
componentDidMount() {
const artistId = this.props.artistId;
const albumId = this.props.albumId;
this.props.dispatchFetchTracks({ artistId, albumId });
this.props.dispatchFetchQualityProfileSchema();
}
componentWillUnmount() {
this.props.dispatchClearTracks();
}
//
// Listeners
@@ -152,7 +117,7 @@ class TrackFileEditorModalContentConnector extends Component {
} = this.props;
return (
<TrackFileEditorModalContent
<TrackFileEditorTableContent
{...otherProps}
onQualityChange={this.onQualityChange}
/>
@@ -160,9 +125,9 @@ class TrackFileEditorModalContentConnector extends Component {
}
}
TrackFileEditorModalContentConnector.propTypes = {
artistId: PropTypes.number.isRequired,
albumId: PropTypes.number,
TrackFileEditorTableContentConnector.propTypes = {
authorId: PropTypes.number.isRequired,
bookId: PropTypes.number,
qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
dispatchFetchTracks: PropTypes.func.isRequired,
dispatchClearTracks: PropTypes.func.isRequired,
@@ -170,4 +135,4 @@ TrackFileEditorModalContentConnector.propTypes = {
dispatchUpdateTrackFiles: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, createMapDispatchToProps)(TrackFileEditorModalContentConnector);
export default connect(createMapStateToProps, createMapDispatchToProps)(TrackFileEditorTableContentConnector);
+1 -1
View File
@@ -135,7 +135,7 @@ function FileDetails(props) {
{
audioTags.artistMBId !== undefined &&
<Link
to={`https://musicbrainz.org/artist/${audioTags.artistMBId}`}
to={`https://musicbrainz.org/author/${audioTags.artistMBId}`}
>
<DescriptionListItem
title="MusicBrainz Artist ID"