mirror of
https://github.com/lidarr/Lidarr
synced 2025-03-15 08:19:05 +00:00
[UI] Refactor TrackFile Modal
This commit is contained in:
parent
e3c6bc3263
commit
9be4ec4c15
43 changed files with 280 additions and 290 deletions
|
@ -156,7 +156,7 @@ function HistoryDetails(props) {
|
|||
);
|
||||
}
|
||||
|
||||
if (eventType === 'episodeFileDeleted') {
|
||||
if (eventType === 'trackFileDeleted') {
|
||||
const {
|
||||
reason
|
||||
} = data;
|
||||
|
@ -192,7 +192,7 @@ function HistoryDetails(props) {
|
|||
);
|
||||
}
|
||||
|
||||
if (eventType === 'episodeFileRenamed') {
|
||||
if (eventType === 'trackFileRenamed') {
|
||||
const {
|
||||
sourcePath,
|
||||
sourceRelativePath,
|
||||
|
|
|
@ -19,9 +19,9 @@ function getHeaderTitle(eventType) {
|
|||
return 'Download Failed';
|
||||
case 'downloadFolderImported':
|
||||
return 'Episode Imported';
|
||||
case 'episodeFileDeleted':
|
||||
case 'trackFileDeleted':
|
||||
return 'Episode File Deleted';
|
||||
case 'episodeFileRenamed':
|
||||
case 'trackFileRenamed':
|
||||
return 'Episode File Renamed';
|
||||
default:
|
||||
return 'Unknown';
|
||||
|
|
|
@ -15,9 +15,9 @@ function getIconName(eventType) {
|
|||
return icons.DOWNLOADED;
|
||||
case 'downloadFailed':
|
||||
return icons.DOWNLOADING;
|
||||
case 'episodeFileDeleted':
|
||||
case 'trackFileDeleted':
|
||||
return icons.DELETE;
|
||||
case 'episodeFileRenamed':
|
||||
case 'trackFileRenamed':
|
||||
return icons.ORGANIZE;
|
||||
default:
|
||||
return icons.UNKNOWN;
|
||||
|
@ -43,9 +43,9 @@ function getTooltip(eventType, data) {
|
|||
return 'Album downloaded successfully and picked up from download client';
|
||||
case 'downloadFailed':
|
||||
return 'Album download failed';
|
||||
case 'episodeFileDeleted':
|
||||
case 'trackFileDeleted':
|
||||
return 'Track file deleted';
|
||||
case 'episodeFileRenamed':
|
||||
case 'trackFileRenamed':
|
||||
return 'Track file renamed';
|
||||
default:
|
||||
return 'Unknown event';
|
||||
|
|
|
@ -160,7 +160,7 @@ class QueueRow extends Component {
|
|||
<EpisodeTitleLink
|
||||
episodeId={episode.id}
|
||||
artistId={series.id}
|
||||
episodeFileId={episode.episodeFileId}
|
||||
trackFileId={episode.trackFileId}
|
||||
episodeEntity={episodeEntity}
|
||||
episodeTitle={episode.title}
|
||||
showOpenArtistButton={true}
|
||||
|
|
|
@ -12,8 +12,8 @@ import EpisodeTitleLink from 'Episode/EpisodeTitleLink';
|
|||
|
||||
import styles from './AlbumRow.css';
|
||||
|
||||
function getEpisodeCountKind(monitored, episodeFileCount, episodeCount) {
|
||||
if (episodeFileCount === episodeCount && episodeCount > 0) {
|
||||
function getEpisodeCountKind(monitored, trackFileCount, episodeCount) {
|
||||
if (trackFileCount === episodeCount && episodeCount > 0) {
|
||||
return kinds.SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import _ from 'lodash';
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||
import createEpisodeFileSelector from 'Store/Selectors/createEpisodeFileSelector';
|
||||
import createTrackFileSelector from 'Store/Selectors/createTrackFileSelector';
|
||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||
import AlbumRow from './AlbumRow';
|
||||
|
||||
|
@ -11,16 +11,16 @@ function createMapStateToProps() {
|
|||
(state, { id }) => id,
|
||||
(state, { sceneSeasonNumber }) => sceneSeasonNumber,
|
||||
createArtistSelector(),
|
||||
createEpisodeFileSelector(),
|
||||
createTrackFileSelector(),
|
||||
createCommandsSelector(),
|
||||
(id, sceneSeasonNumber, series, episodeFile, commands) => {
|
||||
(id, sceneSeasonNumber, series, trackFile, commands) => {
|
||||
const alternateTitles = sceneSeasonNumber ? _.filter(series.alternateTitles, { sceneSeasonNumber }) : [];
|
||||
|
||||
return {
|
||||
artistMonitored: series.monitored,
|
||||
seriesType: series.seriesType,
|
||||
episodeFilePath: episodeFile ? episodeFile.path : null,
|
||||
episodeFileRelativePath: episodeFile ? episodeFile.relativePath : null,
|
||||
trackFilePath: trackFile ? trackFile.path : null,
|
||||
trackFileRelativePath: trackFile ? trackFile.relativePath : null,
|
||||
alternateTitles
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
|||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import Tooltip from 'Components/Tooltip/Tooltip';
|
||||
import EpisodeFileEditorModal from 'EpisodeFile/Editor/EpisodeFileEditorModal';
|
||||
import TrackFileEditorModal from 'TrackFile/Editor/TrackFileEditorModal';
|
||||
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
|
||||
import QualityProfileNameConnector from 'Settings/Profiles/Quality/QualityProfileNameConnector';
|
||||
import ArtistPoster from 'Artist/ArtistPoster';
|
||||
|
@ -179,7 +179,7 @@ class ArtistDetails extends Component {
|
|||
isFetching,
|
||||
isPopulated,
|
||||
episodesError,
|
||||
episodeFilesError,
|
||||
trackFilesError,
|
||||
previousArtist,
|
||||
nextArtist,
|
||||
onRefreshPress,
|
||||
|
@ -198,12 +198,12 @@ class ArtistDetails extends Component {
|
|||
|
||||
const continuing = status === 'continuing';
|
||||
|
||||
let episodeFilesCountMessage = 'No track files';
|
||||
let trackFilesCountMessage = 'No track files';
|
||||
|
||||
if (trackFileCount === 1) {
|
||||
episodeFilesCountMessage = '1 track file';
|
||||
trackFilesCountMessage = '1 track file';
|
||||
} else if (trackFileCount > 1) {
|
||||
episodeFilesCountMessage = `${trackFileCount} track files`;
|
||||
trackFilesCountMessage = `${trackFileCount} track files`;
|
||||
}
|
||||
|
||||
let expandIcon = icons.EXPAND_INDETERMINATE;
|
||||
|
@ -345,7 +345,7 @@ class ArtistDetails extends Component {
|
|||
<div className={styles.detailsLabels}>
|
||||
<Label
|
||||
className={styles.detailsLabel}
|
||||
title={episodeFilesCountMessage}
|
||||
title={trackFilesCountMessage}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
<Icon
|
||||
|
@ -469,7 +469,7 @@ class ArtistDetails extends Component {
|
|||
|
||||
<div className={styles.contentContainer}>
|
||||
{
|
||||
!isPopulated && !episodesError && !episodeFilesError &&
|
||||
!isPopulated && !episodesError && !trackFilesError &&
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
|
@ -479,7 +479,7 @@ class ArtistDetails extends Component {
|
|||
}
|
||||
|
||||
{
|
||||
!isFetching && episodeFilesError &&
|
||||
!isFetching && trackFilesError &&
|
||||
<div>Loading episode files failed</div>
|
||||
}
|
||||
|
||||
|
@ -518,7 +518,7 @@ class ArtistDetails extends Component {
|
|||
onModalClose={this.onOrganizeModalClose}
|
||||
/>
|
||||
|
||||
<EpisodeFileEditorModal
|
||||
<TrackFileEditorModal
|
||||
isOpen={isManageEpisodesOpen}
|
||||
artistId={id}
|
||||
onModalClose={this.onManageEpisodesModalClose}
|
||||
|
@ -563,7 +563,7 @@ ArtistDetails.propTypes = {
|
|||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
episodesError: PropTypes.object,
|
||||
episodeFilesError: PropTypes.object,
|
||||
trackFilesError: PropTypes.object,
|
||||
previousArtist: PropTypes.object.isRequired,
|
||||
nextArtist: PropTypes.object.isRequired,
|
||||
onRefreshPress: PropTypes.func.isRequired,
|
||||
|
|
|
@ -7,7 +7,7 @@ import { findCommand } from 'Utilities/Command';
|
|||
import createAllArtistSelector from 'Store/Selectors/createAllArtistSelector';
|
||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||
import { fetchEpisodes, clearEpisodes } from 'Store/Actions/episodeActions';
|
||||
import { fetchEpisodeFiles, clearEpisodeFiles } from 'Store/Actions/episodeFileActions';
|
||||
import { fetchTrackFiles, clearTrackFiles } from 'Store/Actions/trackFileActions';
|
||||
import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
|
@ -17,10 +17,10 @@ function createMapStateToProps() {
|
|||
return createSelector(
|
||||
(state, { nameSlug }) => nameSlug,
|
||||
(state) => state.episodes,
|
||||
(state) => state.episodeFiles,
|
||||
(state) => state.trackFiles,
|
||||
createAllArtistSelector(),
|
||||
createCommandsSelector(),
|
||||
(nameSlug, episodes, episodeFiles, allArtists, commands) => {
|
||||
(nameSlug, episodes, trackFiles, allArtists, commands) => {
|
||||
const sortedArtist = _.orderBy(allArtists, 'sortName');
|
||||
const artistIndex = _.findIndex(sortedArtist, { nameSlug });
|
||||
const series = sortedArtist[artistIndex];
|
||||
|
@ -39,10 +39,10 @@ function createMapStateToProps() {
|
|||
const isRenamingArtistCommand = findCommand(commands, { name: commandNames.RENAME_ARTIST });
|
||||
const isRenamingArtist = !!(isRenamingArtistCommand && isRenamingArtistCommand.body.artistId.indexOf(series.id) > -1);
|
||||
|
||||
const isFetching = episodes.isFetching || episodeFiles.isFetching;
|
||||
const isPopulated = episodes.isPopulated && episodeFiles.isPopulated;
|
||||
const isFetching = episodes.isFetching || trackFiles.isFetching;
|
||||
const isPopulated = episodes.isPopulated && trackFiles.isPopulated;
|
||||
const episodesError = episodes.error;
|
||||
const episodeFilesError = episodeFiles.error;
|
||||
const trackFilesError = trackFiles.error;
|
||||
const alternateTitles = _.reduce(series.alternateTitles, (acc, alternateTitle) => {
|
||||
if ((alternateTitle.seasonNumber === -1 || alternateTitle.seasonNumber === undefined) &&
|
||||
(alternateTitle.sceneSeasonNumber === -1 || alternateTitle.sceneSeasonNumber === undefined)) {
|
||||
|
@ -62,7 +62,7 @@ function createMapStateToProps() {
|
|||
isFetching,
|
||||
isPopulated,
|
||||
episodesError,
|
||||
episodeFilesError,
|
||||
trackFilesError,
|
||||
previousArtist,
|
||||
nextArtist
|
||||
};
|
||||
|
@ -73,8 +73,8 @@ function createMapStateToProps() {
|
|||
const mapDispatchToProps = {
|
||||
fetchEpisodes,
|
||||
clearEpisodes,
|
||||
fetchEpisodeFiles,
|
||||
clearEpisodeFiles,
|
||||
fetchTrackFiles,
|
||||
clearTrackFiles,
|
||||
fetchQueueDetails,
|
||||
clearQueueDetails,
|
||||
executeCommand
|
||||
|
@ -125,13 +125,13 @@ class ArtistDetailsConnector extends Component {
|
|||
const artistId = this.props.id;
|
||||
|
||||
this.props.fetchEpisodes({ artistId });
|
||||
this.props.fetchEpisodeFiles({ artistId });
|
||||
this.props.fetchTrackFiles({ artistId });
|
||||
this.props.fetchQueueDetails({ artistId });
|
||||
}
|
||||
|
||||
_unpopulate() {
|
||||
this.props.clearEpisodes();
|
||||
this.props.clearEpisodeFiles();
|
||||
this.props.clearTrackFiles();
|
||||
this.props.clearQueueDetails();
|
||||
}
|
||||
|
||||
|
@ -174,8 +174,8 @@ ArtistDetailsConnector.propTypes = {
|
|||
isRenamingArtist: PropTypes.bool.isRequired,
|
||||
fetchEpisodes: PropTypes.func.isRequired,
|
||||
clearEpisodes: PropTypes.func.isRequired,
|
||||
fetchEpisodeFiles: PropTypes.func.isRequired,
|
||||
clearEpisodeFiles: PropTypes.func.isRequired,
|
||||
fetchTrackFiles: PropTypes.func.isRequired,
|
||||
clearTrackFiles: PropTypes.func.isRequired,
|
||||
fetchQueueDetails: PropTypes.func.isRequired,
|
||||
clearQueueDetails: PropTypes.func.isRequired,
|
||||
executeCommand: PropTypes.func.isRequired
|
||||
|
|
|
@ -16,7 +16,7 @@ import MenuContent from 'Components/Menu/MenuContent';
|
|||
import MenuItem from 'Components/Menu/MenuItem';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import EpisodeFileEditorModal from 'EpisodeFile/Editor/EpisodeFileEditorModal';
|
||||
import TrackFileEditorModal from 'TrackFile/Editor/TrackFileEditorModal';
|
||||
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
|
||||
import AlbumRowConnector from './AlbumRowConnector';
|
||||
import styles from './ArtistDetailsSeason.css';
|
||||
|
@ -287,7 +287,7 @@ class ArtistDetailsSeason extends Component {
|
|||
onModalClose={this.onOrganizeModalClose}
|
||||
/>
|
||||
|
||||
<EpisodeFileEditorModal
|
||||
<TrackFileEditorModal
|
||||
isOpen={isManageEpisodesOpen}
|
||||
artistId={artistId}
|
||||
onModalClose={this.onManageEpisodesModalClose}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { createSelector } from 'reselect';
|
|||
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||
import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
|
||||
import * as calendarActions from 'Store/Actions/calendarActions';
|
||||
import { fetchEpisodeFiles, clearEpisodeFiles } from 'Store/Actions/episodeFileActions';
|
||||
import { fetchTrackFiles, clearTrackFiles } from 'Store/Actions/trackFileActions';
|
||||
import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions';
|
||||
import Calendar from './Calendar';
|
||||
|
||||
|
@ -22,8 +22,8 @@ function createMapStateToProps() {
|
|||
|
||||
const mapDispatchToProps = {
|
||||
...calendarActions,
|
||||
fetchEpisodeFiles,
|
||||
clearEpisodeFiles,
|
||||
fetchTrackFiles,
|
||||
clearTrackFiles,
|
||||
fetchQueueDetails,
|
||||
clearQueueDetails
|
||||
};
|
||||
|
@ -52,12 +52,12 @@ class CalendarConnector extends Component {
|
|||
|
||||
if (hasDifferentItems(prevProps.items, items)) {
|
||||
const albumIds = selectUniqueIds(items, 'id');
|
||||
// const episodeFileIds = selectUniqueIds(items, 'episodeFileId');
|
||||
// const trackFileIds = selectUniqueIds(items, 'trackFileId');
|
||||
|
||||
this.props.fetchQueueDetails({ albumIds });
|
||||
|
||||
// if (episodeFileIds.length) {
|
||||
// this.props.fetchEpisodeFiles({ episodeFileIds });
|
||||
// if (trackFileIds.length) {
|
||||
// this.props.fetchTrackFiles({ trackFileIds });
|
||||
// }
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ class CalendarConnector extends Component {
|
|||
componentWillUnmount() {
|
||||
this.props.clearCalendar();
|
||||
this.props.clearQueueDetails();
|
||||
this.props.clearEpisodeFiles();
|
||||
this.props.clearTrackFiles();
|
||||
this.clearUpdateTimeout();
|
||||
}
|
||||
|
||||
|
@ -136,8 +136,8 @@ CalendarConnector.propTypes = {
|
|||
gotoCalendarPreviousRange: PropTypes.func.isRequired,
|
||||
gotoCalendarNextRange: PropTypes.func.isRequired,
|
||||
clearCalendar: PropTypes.func.isRequired,
|
||||
fetchEpisodeFiles: PropTypes.func.isRequired,
|
||||
clearEpisodeFiles: PropTypes.func.isRequired,
|
||||
fetchTrackFiles: PropTypes.func.isRequired,
|
||||
clearTrackFiles: PropTypes.func.isRequired,
|
||||
fetchQueueDetails: PropTypes.func.isRequired,
|
||||
clearQueueDetails: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ export const CLEAR_LOGS = 'ClearLog';
|
|||
export const CUTOFF_UNMET_EPISODE_SEARCH = 'CutoffUnmetEpisodeSearch';
|
||||
export const DELETE_LOG_FILES = 'DeleteLogFiles';
|
||||
export const DELETE_UPDATE_LOG_FILES = 'DeleteUpdateLogFiles';
|
||||
export const DOWNLOADED_EPSIODES_SCAN = 'DownloadedEpisodesScan';
|
||||
export const DOWNLOADED_ALBUMS_SCAN = 'DownloadedAlbumsScan';
|
||||
export const EPISODE_SEARCH = 'AlbumSearch';
|
||||
export const INTERACTIVE_IMPORT = 'ManualImport';
|
||||
export const MISSING_ALBUM_SEARCH = 'MissingAlbumSearch';
|
||||
|
|
|
@ -120,7 +120,7 @@ class SignalRConnector extends Component {
|
|||
}
|
||||
|
||||
if (name === 'episodefile') {
|
||||
this.handleEpisodeFile(body);
|
||||
this.handleTrackFile(body);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,10 +206,10 @@ class SignalRConnector extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleEpisodeFile = (body) => {
|
||||
handleTrackFile = (body) => {
|
||||
if (body.action === 'updated') {
|
||||
this.props.updateItem({
|
||||
section: 'episodeFiles',
|
||||
section: 'trackFiles',
|
||||
...body.resource });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import createEpisodeSelector from 'Store/Selectors/createEpisodeSelector';
|
|||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||
import episodeEntities from 'Episode/episodeEntities';
|
||||
import { fetchTracks, clearTracks } from 'Store/Actions/trackActions';
|
||||
import { fetchEpisodeFiles, clearEpisodeFiles } from 'Store/Actions/episodeFileActions';
|
||||
import { fetchTrackFiles, clearTrackFiles } from 'Store/Actions/trackFileActions';
|
||||
import EpisodeDetailsModalContent from './EpisodeDetailsModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
@ -38,8 +38,8 @@ const mapDispatchToProps = {
|
|||
clearReleases,
|
||||
fetchTracks,
|
||||
clearTracks,
|
||||
fetchEpisodeFiles,
|
||||
clearEpisodeFiles,
|
||||
fetchTrackFiles,
|
||||
clearTrackFiles,
|
||||
toggleEpisodeMonitored
|
||||
};
|
||||
|
||||
|
@ -65,15 +65,14 @@ class EpisodeDetailsModalContentConnector extends Component {
|
|||
const artistId = this.props.artistId;
|
||||
const albumId = this.props.episodeId;
|
||||
this.props.fetchTracks({ artistId, albumId });
|
||||
// this.props.fetchEpisodeFiles({ artistId, albumId });
|
||||
// this.props.fetchTrackFiles({ artistId, albumId });
|
||||
}
|
||||
|
||||
_unpopulate() {
|
||||
this.props.clearTracks();
|
||||
// this.props.clearEpisodeFiles();
|
||||
// this.props.clearTrackFiles();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
|
@ -109,8 +108,8 @@ EpisodeDetailsModalContentConnector.propTypes = {
|
|||
artistId: PropTypes.number.isRequired,
|
||||
fetchTracks: PropTypes.func.isRequired,
|
||||
clearTracks: PropTypes.func.isRequired,
|
||||
fetchEpisodeFiles: PropTypes.func.isRequired,
|
||||
clearEpisodeFiles: PropTypes.func.isRequired,
|
||||
fetchTrackFiles: PropTypes.func.isRequired,
|
||||
clearTrackFiles: PropTypes.func.isRequired,
|
||||
clearReleases: PropTypes.func.isRequired,
|
||||
toggleEpisodeMonitored: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -14,10 +14,10 @@ function EpisodeStatus(props) {
|
|||
monitored,
|
||||
grabbed,
|
||||
queueItem,
|
||||
episodeFile
|
||||
trackFile
|
||||
} = props;
|
||||
|
||||
const hasEpisodeFile = !!episodeFile;
|
||||
const hasTrackFile = !!trackFile;
|
||||
const isQueued = !!queueItem;
|
||||
const hasAired = isBefore(airDateUtc);
|
||||
|
||||
|
@ -57,15 +57,15 @@ function EpisodeStatus(props) {
|
|||
);
|
||||
}
|
||||
|
||||
if (hasEpisodeFile) {
|
||||
const quality = episodeFile.quality;
|
||||
const isCutoffNotMet = episodeFile.qualityCutoffNotMet;
|
||||
if (hasTrackFile) {
|
||||
const quality = trackFile.quality;
|
||||
const isCutoffNotMet = trackFile.qualityCutoffNotMet;
|
||||
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<EpisodeQuality
|
||||
quality={quality}
|
||||
size={episodeFile.size}
|
||||
size={trackFile.size}
|
||||
isCutoffNotMet={isCutoffNotMet}
|
||||
title="Episode Downloaded"
|
||||
/>
|
||||
|
@ -121,7 +121,7 @@ EpisodeStatus.propTypes = {
|
|||
monitored: PropTypes.bool,
|
||||
grabbed: PropTypes.bool,
|
||||
queueItem: PropTypes.object,
|
||||
episodeFile: PropTypes.object
|
||||
trackFile: PropTypes.object
|
||||
};
|
||||
|
||||
export default EpisodeStatus;
|
||||
|
|
|
@ -5,15 +5,15 @@ import { connect } from 'react-redux';
|
|||
import { createSelector } from 'reselect';
|
||||
import createEpisodeSelector from 'Store/Selectors/createEpisodeSelector';
|
||||
import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector';
|
||||
import createEpisodeFileSelector from 'Store/Selectors/createEpisodeFileSelector';
|
||||
import createTrackFileSelector from 'Store/Selectors/createTrackFileSelector';
|
||||
import EpisodeStatus from './EpisodeStatus';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createEpisodeSelector(),
|
||||
createQueueItemSelector(),
|
||||
createEpisodeFileSelector(),
|
||||
(episode, queueItem, episodeFile) => {
|
||||
createTrackFileSelector(),
|
||||
(episode, queueItem, trackFile) => {
|
||||
const result = _.pick(episode, [
|
||||
'airDateUtc',
|
||||
'monitored',
|
||||
|
@ -21,7 +21,7 @@ function createMapStateToProps() {
|
|||
]);
|
||||
|
||||
result.queueItem = queueItem;
|
||||
result.episodeFile = episodeFile;
|
||||
result.trackFile = trackFile;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class EpisodeStatusConnector extends Component {
|
|||
|
||||
EpisodeStatusConnector.propTypes = {
|
||||
episodeId: PropTypes.number.isRequired,
|
||||
episodeFileId: PropTypes.number.isRequired
|
||||
trackFileId: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(EpisodeStatusConnector);
|
||||
|
|
|
@ -22,24 +22,24 @@ class EpisodeSummary extends Component {
|
|||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isRemoveEpisodeFileModalOpen: false
|
||||
isRemoveTrackFileModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onRemoveEpisodeFilePress = () => {
|
||||
this.setState({ isRemoveEpisodeFileModalOpen: true });
|
||||
onRemoveTrackFilePress = () => {
|
||||
this.setState({ isRemoveTrackFileModalOpen: true });
|
||||
}
|
||||
|
||||
onConfirmRemoveEpisodeFile = () => {
|
||||
this.props.onDeleteEpisodeFile();
|
||||
this.setState({ isRemoveEpisodeFileModalOpen: false });
|
||||
onConfirmRemoveTrackFile = () => {
|
||||
this.props.onDeleteTrackFile();
|
||||
this.setState({ isRemoveTrackFileModalOpen: false });
|
||||
}
|
||||
|
||||
onRemoveEpisodeFileModalClose = () => {
|
||||
this.setState({ isRemoveEpisodeFileModalOpen: false });
|
||||
onRemoveTrackFileModalClose = () => {
|
||||
this.setState({ isRemoveTrackFileModalOpen: false });
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -125,13 +125,13 @@ class EpisodeSummary extends Component {
|
|||
</div>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isRemoveEpisodeFileModalOpen}
|
||||
isOpen={this.state.isRemoveTrackFileModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title="Delete Episode File"
|
||||
message={`Are you sure you want to delete '${path}'?`}
|
||||
confirmLabel="Delete"
|
||||
onConfirm={this.onConfirmRemoveEpisodeFile}
|
||||
onCancel={this.onRemoveEpisodeFileModalClose}
|
||||
onConfirm={this.onConfirmRemoveTrackFile}
|
||||
onCancel={this.onRemoveTrackFileModalClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -149,7 +149,7 @@ EpisodeSummary.propTypes = {
|
|||
size: PropTypes.number,
|
||||
quality: PropTypes.object,
|
||||
qualityCutoffNotMet: PropTypes.bool,
|
||||
onDeleteEpisodeFile: PropTypes.func.isRequired
|
||||
onDeleteTrackFile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EpisodeSummary;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import _ from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { deleteEpisodeFile } from 'Store/Actions/episodeFileActions';
|
||||
import { deleteTrackFile } from 'Store/Actions/trackFileActions';
|
||||
import createEpisodeSelector from 'Store/Selectors/createEpisodeSelector';
|
||||
import createTrackSelector from 'Store/Selectors/createTrackSelector';
|
||||
import createEpisodeFileSelector from 'Store/Selectors/createEpisodeFileSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||
|
@ -11,18 +10,19 @@ import EpisodeSummary from './EpisodeSummary';
|
|||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { episode }) => episode,
|
||||
(state) => state.tracks,
|
||||
createEpisodeSelector(),
|
||||
createCommandsSelector(),
|
||||
createDimensionsSelector(),
|
||||
(albumId, tracks, episode, commands, dimensions) => {
|
||||
(tracks, episode, commands, dimensions) => {
|
||||
const items = _.filter(tracks.items, { albumId: episode.id });
|
||||
|
||||
return {
|
||||
network: episode.label,
|
||||
qualityProfileId: episode.profileId,
|
||||
airDateUtc: episode.releaseDate,
|
||||
overview: episode.overview,
|
||||
items: tracks.items,
|
||||
items,
|
||||
columns: tracks.columns
|
||||
};
|
||||
}
|
||||
|
@ -31,9 +31,9 @@ function createMapStateToProps() {
|
|||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
onDeleteEpisodeFile() {
|
||||
dispatch(deleteEpisodeFile({
|
||||
id: props.episodeFileId,
|
||||
onDeleteTrackFile() {
|
||||
dispatch(deleteTrackFile({
|
||||
id: props.trackFileId,
|
||||
episodeEntity: props.episodeEntity
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ import React, { Component } from 'react';
|
|||
import TableRow from 'Components/Table/TableRow';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
|
||||
import MediaInfoConnector from 'EpisodeFile/MediaInfoConnector';
|
||||
import * as mediaInfoTypes from 'EpisodeFile/mediaInfoTypes';
|
||||
import MediaInfoConnector from 'TrackFile/MediaInfoConnector';
|
||||
import * as mediaInfoTypes from 'TrackFile/mediaInfoTypes';
|
||||
import EpisodeStatusConnector from 'Episode/EpisodeStatusConnector';
|
||||
|
||||
import styles from './TrackDetailRow.css';
|
||||
|
@ -83,7 +83,7 @@ class TrackDetailRow extends Component {
|
|||
>
|
||||
<MediaInfoConnector
|
||||
type={mediaInfoTypes.AUDIO}
|
||||
episodeFileId={trackFileId}
|
||||
trackFileId={trackFileId}
|
||||
/>
|
||||
</TableRowCell>
|
||||
);
|
||||
|
@ -97,7 +97,7 @@ class TrackDetailRow extends Component {
|
|||
>
|
||||
<EpisodeStatusConnector
|
||||
episodeId={id}
|
||||
episodeFileId={trackFileId}
|
||||
trackFileId={trackFileId}
|
||||
/>
|
||||
</TableRowCell>
|
||||
);
|
||||
|
|
|
@ -32,7 +32,7 @@ class InteractiveImportSelectFolderModalContentConnector extends Component {
|
|||
this.props.addRecentFolder({ folder });
|
||||
|
||||
this.props.executeCommand({
|
||||
name: commandNames.DOWNLOADED_EPSIODES_SCAN,
|
||||
name: commandNames.DOWNLOADED_ALBUMS_SCAN,
|
||||
path: folder
|
||||
});
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ class InteractiveImportModalContent extends Component {
|
|||
|
||||
{
|
||||
isPopulated && !items.length &&
|
||||
'No video files were found in the selected folder'
|
||||
'No audio files were found in the selected folder'
|
||||
}
|
||||
</ModalBody>
|
||||
|
||||
|
|
|
@ -95,11 +95,11 @@ export const CLEAR_TRACKS = 'CLEAR_TRACKS';
|
|||
//
|
||||
// Episode Files
|
||||
|
||||
export const FETCH_EPISODE_FILES = 'FETCH_EPISODE_FILES';
|
||||
export const CLEAR_EPISODE_FILES = 'CLEAR_EPISODE_FILES';
|
||||
export const DELETE_EPISODE_FILE = 'DELETE_EPISODE_FILE';
|
||||
export const DELETE_EPISODE_FILES = 'DELETE_EPISODE_FILES';
|
||||
export const UPDATE_EPISODE_FILES = 'UPDATE_EPISODE_FILES';
|
||||
export const FETCH_TRACK_FILES = 'FETCH_TRACK_FILES';
|
||||
export const CLEAR_TRACK_FILES = 'CLEAR_TRACK_FILES';
|
||||
export const DELETE_TRACK_FILE = 'DELETE_TRACK_FILE';
|
||||
export const DELETE_TRACK_FILES = 'DELETE_TRACK_FILES';
|
||||
export const UPDATE_TRACK_FILES = 'UPDATE_TRACK_FILES';
|
||||
|
||||
//
|
||||
// Episode History
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import { createAction } from 'redux-actions';
|
||||
import * as types from './actionTypes';
|
||||
import episodeFileActionHandlers from './episodeFileActionHandlers';
|
||||
|
||||
export const fetchEpisodeFiles = episodeFileActionHandlers[types.FETCH_EPISODE_FILES];
|
||||
export const deleteEpisodeFile = episodeFileActionHandlers[types.DELETE_EPISODE_FILE];
|
||||
export const deleteEpisodeFiles = episodeFileActionHandlers[types.DELETE_EPISODE_FILES];
|
||||
export const updateEpisodeFiles = episodeFileActionHandlers[types.UPDATE_EPISODE_FILES];
|
||||
export const clearEpisodeFiles = createAction(types.CLEAR_EPISODE_FILES);
|
|
@ -7,33 +7,33 @@ import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
|||
import * as types from './actionTypes';
|
||||
import { set, removeItem, updateItem } from './baseActions';
|
||||
|
||||
const section = 'episodeFiles';
|
||||
const deleteEpisodeFile = createRemoveItemHandler(section, '/trackFile');
|
||||
const section = 'trackFiles';
|
||||
const deleteTrackFile = createRemoveItemHandler(section, '/trackFile');
|
||||
|
||||
const episodeFileActionHandlers = {
|
||||
[types.FETCH_EPISODE_FILES]: createFetchHandler(section, '/trackFile'),
|
||||
const trackFileActionHandlers = {
|
||||
[types.FETCH_TRACK_FILES]: createFetchHandler(section, '/trackFile'),
|
||||
|
||||
[types.DELETE_EPISODE_FILE]: function(payload) {
|
||||
[types.DELETE_TRACK_FILE]: function(payload) {
|
||||
return function(dispatch, getState) {
|
||||
const {
|
||||
id: episodeFileId,
|
||||
id: trackFileId,
|
||||
episodeEntity = episodeEntities.EPISODES
|
||||
} = payload;
|
||||
|
||||
const episodeSection = _.last(episodeEntity.split('.'));
|
||||
|
||||
const deletePromise = deleteEpisodeFile(payload)(dispatch, getState);
|
||||
const deletePromise = deleteTrackFile(payload)(dispatch, getState);
|
||||
|
||||
deletePromise.done(() => {
|
||||
const episodes = getState().episodes.items;
|
||||
const episodesWithRemovedFiles = _.filter(episodes, { episodeFileId });
|
||||
const episodesWithRemovedFiles = _.filter(episodes, { trackFileId });
|
||||
|
||||
dispatch(batchActions([
|
||||
...episodesWithRemovedFiles.map((episode) => {
|
||||
return updateItem({
|
||||
section: episodeSection,
|
||||
...episode,
|
||||
episodeFileId: 0,
|
||||
trackFileId: 0,
|
||||
hasFile: false
|
||||
});
|
||||
})
|
||||
|
@ -42,31 +42,31 @@ const episodeFileActionHandlers = {
|
|||
};
|
||||
},
|
||||
|
||||
[types.DELETE_EPISODE_FILES]: function(payload) {
|
||||
[types.DELETE_TRACK_FILES]: function(payload) {
|
||||
return function(dispatch, getState) {
|
||||
const {
|
||||
episodeFileIds
|
||||
trackFileIds
|
||||
} = payload;
|
||||
|
||||
dispatch(set({ section, isDeleting: true }));
|
||||
|
||||
const promise = $.ajax({
|
||||
url: '/episodeFile/bulk',
|
||||
url: '/trackFile/bulk',
|
||||
method: 'DELETE',
|
||||
dataType: 'json',
|
||||
data: JSON.stringify({ episodeFileIds })
|
||||
data: JSON.stringify({ trackFileIds })
|
||||
});
|
||||
|
||||
promise.done(() => {
|
||||
const episodes = getState().episodes.items;
|
||||
const episodesWithRemovedFiles = episodeFileIds.reduce((acc, episodeFileId) => {
|
||||
acc.push(..._.filter(episodes, { episodeFileId }));
|
||||
const episodesWithRemovedFiles = trackFileIds.reduce((acc, trackFileId) => {
|
||||
acc.push(..._.filter(episodes, { trackFileId }));
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
dispatch(batchActions([
|
||||
...episodeFileIds.map((id) => {
|
||||
...trackFileIds.map((id) => {
|
||||
return removeItem({ section, id });
|
||||
}),
|
||||
|
||||
|
@ -74,7 +74,7 @@ const episodeFileActionHandlers = {
|
|||
return updateItem({
|
||||
section: 'episodes',
|
||||
...episode,
|
||||
episodeFileId: 0,
|
||||
trackFileId: 0,
|
||||
hasFile: false
|
||||
});
|
||||
}),
|
||||
|
@ -97,10 +97,10 @@ const episodeFileActionHandlers = {
|
|||
};
|
||||
},
|
||||
|
||||
[types.UPDATE_EPISODE_FILES]: function(payload) {
|
||||
[types.UPDATE_TRACK_FILES]: function(payload) {
|
||||
return function(dispatch, getState) {
|
||||
const {
|
||||
episodeFileIds,
|
||||
trackFileIds,
|
||||
language,
|
||||
quality
|
||||
} = payload;
|
||||
|
@ -108,7 +108,7 @@ const episodeFileActionHandlers = {
|
|||
dispatch(set({ section, isSaving: true }));
|
||||
|
||||
const data = {
|
||||
episodeFileIds
|
||||
trackFileIds
|
||||
};
|
||||
|
||||
if (language) {
|
||||
|
@ -120,7 +120,7 @@ const episodeFileActionHandlers = {
|
|||
}
|
||||
|
||||
const promise = $.ajax({
|
||||
url: '/episodeFile/editor',
|
||||
url: '/trackFile/editor',
|
||||
method: 'PUT',
|
||||
dataType: 'json',
|
||||
data: JSON.stringify(data)
|
||||
|
@ -128,7 +128,7 @@ const episodeFileActionHandlers = {
|
|||
|
||||
promise.done(() => {
|
||||
dispatch(batchActions([
|
||||
...episodeFileIds.map((id) => {
|
||||
...trackFileIds.map((id) => {
|
||||
const props = {};
|
||||
|
||||
if (language) {
|
||||
|
@ -161,4 +161,4 @@ const episodeFileActionHandlers = {
|
|||
}
|
||||
};
|
||||
|
||||
export default episodeFileActionHandlers;
|
||||
export default trackFileActionHandlers;
|
9
frontend/src/Store/Actions/trackFileActions.js
Normal file
9
frontend/src/Store/Actions/trackFileActions.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { createAction } from 'redux-actions';
|
||||
import * as types from './actionTypes';
|
||||
import trackFileActionHandlers from './trackFileActionHandlers';
|
||||
|
||||
export const fetchTrackFiles = trackFileActionHandlers[types.FETCH_TRACK_FILES];
|
||||
export const deleteTrackFile = trackFileActionHandlers[types.DELETE_TRACK_FILE];
|
||||
export const deleteTrackFiles = trackFileActionHandlers[types.DELETE_TRACK_FILES];
|
||||
export const updateTrackFiles = trackFileActionHandlers[types.UPDATE_TRACK_FILES];
|
||||
export const clearTrackFiles = createAction(types.CLEAR_TRACK_FILES);
|
|
@ -14,7 +14,7 @@ import queue, { defaultState as defaultQueueState } from './queueReducers';
|
|||
import blacklist, { defaultState as defaultBlacklistState } from './blacklistReducers';
|
||||
import episodes, { defaultState as defaultEpisodesState } from './episodeReducers';
|
||||
import tracks, { defaultState as defaultTracksState } from './trackReducers';
|
||||
import episodeFiles, { defaultState as defaultEpisodeFilesState } from './episodeFileReducers';
|
||||
import trackFiles, { defaultState as defaultTrackFilesState } from './trackFileReducers';
|
||||
import albumHistory, { defaultState as defaultAlbumHistoryState } from './albumHistoryReducers';
|
||||
import releases, { defaultState as defaultReleasesState } from './releaseReducers';
|
||||
import wanted, { defaultState as defaultWantedState } from './wantedReducers';
|
||||
|
@ -43,7 +43,7 @@ export const defaultState = {
|
|||
blacklist: defaultBlacklistState,
|
||||
episodes: defaultEpisodesState,
|
||||
tracks: defaultTracksState,
|
||||
episodeFiles: defaultEpisodeFilesState,
|
||||
trackFiles: defaultTrackFilesState,
|
||||
albumHistory: defaultAlbumHistoryState,
|
||||
releases: defaultReleasesState,
|
||||
wanted: defaultWantedState,
|
||||
|
@ -73,7 +73,7 @@ export default enableBatching(combineReducers({
|
|||
blacklist,
|
||||
episodes,
|
||||
tracks,
|
||||
episodeFiles,
|
||||
trackFiles,
|
||||
albumHistory,
|
||||
releases,
|
||||
wanted,
|
||||
|
|
|
@ -16,19 +16,19 @@ export const defaultState = {
|
|||
items: []
|
||||
};
|
||||
|
||||
const reducerSection = 'episodeFiles';
|
||||
const reducerSection = 'trackFiles';
|
||||
|
||||
const episodeFileReducers = handleActions({
|
||||
const trackFileReducers = handleActions({
|
||||
|
||||
[types.SET]: createSetReducer(reducerSection),
|
||||
[types.UPDATE]: createUpdateReducer(reducerSection),
|
||||
[types.UPDATE_ITEM]: createUpdateItemReducer(reducerSection),
|
||||
[types.REMOVE_ITEM]: createRemoveItemReducer(reducerSection),
|
||||
|
||||
[types.CLEAR_EPISODE_FILES]: (state) => {
|
||||
[types.CLEAR_TRACK_FILES]: (state) => {
|
||||
return Object.assign({}, state, defaultState);
|
||||
}
|
||||
|
||||
}, defaultState);
|
||||
|
||||
export default episodeFileReducers;
|
||||
export default trackFileReducers;
|
|
@ -1,18 +0,0 @@
|
|||
import _ from 'lodash';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
function createEpisodeFileSelector() {
|
||||
return createSelector(
|
||||
(state, { episodeFileId }) => episodeFileId,
|
||||
(state) => state.episodeFiles,
|
||||
(episodeFileId, episodeFiles) => {
|
||||
if (!episodeFileId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _.find(episodeFiles.items, { id: episodeFileId });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default createEpisodeFileSelector;
|
18
frontend/src/Store/Selectors/createTrackFileSelector.js
Normal file
18
frontend/src/Store/Selectors/createTrackFileSelector.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import _ from 'lodash';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
function createTrackFileSelector() {
|
||||
return createSelector(
|
||||
(state, { trackFileId }) => trackFileId,
|
||||
(state) => state.trackFiles,
|
||||
(trackFileId, trackFiles) => {
|
||||
if (!trackFileId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _.find(trackFiles.items, { id: trackFileId });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default createTrackFileSelector;
|
|
@ -1,9 +1,9 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import EpisodeFileEditorModalContentConnector from './EpisodeFileEditorModalContentConnector';
|
||||
import TrackFileEditorModalContentConnector from './TrackFileEditorModalContentConnector';
|
||||
|
||||
function EpisodeFileEditorModal(props) {
|
||||
function TrackFileEditorModal(props) {
|
||||
const {
|
||||
isOpen,
|
||||
onModalClose,
|
||||
|
@ -17,7 +17,7 @@ function EpisodeFileEditorModal(props) {
|
|||
>
|
||||
{
|
||||
isOpen &&
|
||||
<EpisodeFileEditorModalContentConnector
|
||||
<TrackFileEditorModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
|
@ -26,9 +26,9 @@ function EpisodeFileEditorModal(props) {
|
|||
);
|
||||
}
|
||||
|
||||
EpisodeFileEditorModal.propTypes = {
|
||||
TrackFileEditorModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EpisodeFileEditorModal;
|
||||
export default TrackFileEditorModal;
|
|
@ -15,13 +15,13 @@ 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 EpisodeFileEditorRow from './EpisodeFileEditorRow';
|
||||
import styles from './EpisodeFileEditorModalContent.css';
|
||||
import TrackFileEditorRow from './TrackFileEditorRow';
|
||||
import styles from './TrackFileEditorModalContent.css';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'episodeNumber',
|
||||
label: 'Episode',
|
||||
name: 'trackNumber',
|
||||
label: 'Track',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
|
@ -29,11 +29,6 @@ const columns = [
|
|||
label: 'Relative Path',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'airDateUtc',
|
||||
label: 'Air Date',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'language',
|
||||
label: 'Language',
|
||||
|
@ -46,7 +41,7 @@ const columns = [
|
|||
}
|
||||
];
|
||||
|
||||
class EpisodeFileEditorModalContent extends Component {
|
||||
class TrackFileEditorModalContent extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -76,7 +71,7 @@ class EpisodeFileEditorModalContent extends Component {
|
|||
const selectedIds = getSelectedIds(this.state.selectedState);
|
||||
|
||||
return _.uniq(_.map(selectedIds, (id) => {
|
||||
return _.find(this.props.items, { id }).episodeFileId;
|
||||
return _.find(this.props.items, { id }).trackFileId;
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -135,7 +130,6 @@ class EpisodeFileEditorModalContent extends Component {
|
|||
items,
|
||||
languages,
|
||||
qualities,
|
||||
seriesType,
|
||||
onModalClose
|
||||
} = this.props;
|
||||
|
||||
|
@ -169,14 +163,14 @@ class EpisodeFileEditorModalContent extends Component {
|
|||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
Manage Episodes
|
||||
Manage Tracks
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
{
|
||||
!items.length &&
|
||||
<div>
|
||||
No episode files to manage.
|
||||
No track files to manage.
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -193,9 +187,8 @@ class EpisodeFileEditorModalContent extends Component {
|
|||
{
|
||||
items.map((item) => {
|
||||
return (
|
||||
<EpisodeFileEditorRow
|
||||
<TrackFileEditorRow
|
||||
key={item.id}
|
||||
seriesType={seriesType}
|
||||
isSelected={selectedState[item.id]}
|
||||
{...item}
|
||||
onSelectedChange={this.onSelectedChange}
|
||||
|
@ -250,8 +243,8 @@ class EpisodeFileEditorModalContent extends Component {
|
|||
<ConfirmModal
|
||||
isOpen={isConfirmDeleteModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title="Delete Selected Episode Files"
|
||||
message={'Are you sure you want to delete the selected episode files?'}
|
||||
title="Delete Selected Track Files"
|
||||
message={'Are you sure you want to delete the selected track files?'}
|
||||
confirmLabel="Delete"
|
||||
onConfirm={this.onConfirmDelete}
|
||||
onCancel={this.onConfirmDeleteModalClose}
|
||||
|
@ -261,16 +254,15 @@ class EpisodeFileEditorModalContent extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
EpisodeFileEditorModalContent.propTypes = {
|
||||
TrackFileEditorModalContent.propTypes = {
|
||||
isDeleting: PropTypes.bool.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
seriesType: PropTypes.string.isRequired,
|
||||
onDeletePress: PropTypes.func.isRequired,
|
||||
onLanguageChange: PropTypes.func.isRequired,
|
||||
onQualityChange: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EpisodeFileEditorModalContent;
|
||||
export default TrackFileEditorModalContent;
|
|
@ -4,48 +4,49 @@ import React, { Component } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||
import { deleteEpisodeFiles, updateEpisodeFiles } from 'Store/Actions/episodeFileActions';
|
||||
import { deleteTrackFiles, updateTrackFiles } from 'Store/Actions/trackFileActions';
|
||||
import { fetchTracks, clearTracks } from 'Store/Actions/trackActions';
|
||||
import { fetchLanguageProfileSchema, fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
|
||||
import EpisodeFileEditorModalContent from './EpisodeFileEditorModalContent';
|
||||
import TrackFileEditorModalContent from './TrackFileEditorModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { seasonNumber }) => seasonNumber,
|
||||
(state) => state.episodes,
|
||||
(state) => state.episodeFiles,
|
||||
(state, { albumId }) => albumId,
|
||||
(state) => state.tracks,
|
||||
(state) => state.trackFiles,
|
||||
(state) => state.settings.languageProfiles.schema,
|
||||
(state) => state.settings.qualityProfiles.schema,
|
||||
createArtistSelector(),
|
||||
(
|
||||
seasonNumber,
|
||||
episodes,
|
||||
episodeFiles,
|
||||
albumId,
|
||||
tracks,
|
||||
trackFiles,
|
||||
languageProfilesSchema,
|
||||
qualityProfileSchema,
|
||||
series
|
||||
) => {
|
||||
const filtered = _.filter(episodes.items, (episode) => {
|
||||
if (seasonNumber >= 0 && episode.seasonNumber !== seasonNumber) {
|
||||
const filtered = _.filter(tracks.items, (track) => {
|
||||
if (albumId >= 0 && track.albumId !== albumId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!episode.episodeFileId) {
|
||||
if (!track.trackFileId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _.some(episodeFiles.items, { id: episode.episodeFileId });
|
||||
return _.some(trackFiles.items, { id: track.trackFileId });
|
||||
});
|
||||
|
||||
const sorted = _.orderBy(filtered, ['seasonNumber', 'episodeNumber'], ['desc', 'desc']);
|
||||
const sorted = _.orderBy(filtered, ['albumId', 'trackNumber'], ['desc', 'asc']);
|
||||
|
||||
const items = _.map(sorted, (episode) => {
|
||||
const episodeFile = _.find(episodeFiles.items, { id: episode.episodeFileId });
|
||||
const items = _.map(sorted, (track) => {
|
||||
const trackFile = _.find(trackFiles.items, { id: track.trackFileId });
|
||||
|
||||
return {
|
||||
relativePath: episodeFile.relativePath,
|
||||
language: episodeFile.language,
|
||||
quality: episodeFile.quality,
|
||||
...episode
|
||||
relativePath: trackFile.relativePath,
|
||||
language: trackFile.language,
|
||||
quality: trackFile.quality,
|
||||
...track
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -55,8 +56,8 @@ function createMapStateToProps() {
|
|||
return {
|
||||
items,
|
||||
seriesType: series.seriesType,
|
||||
isDeleting: episodeFiles.isDeleting,
|
||||
isSaving: episodeFiles.isSaving,
|
||||
isDeleting: trackFiles.isDeleting,
|
||||
isSaving: trackFiles.isSaving,
|
||||
languages,
|
||||
qualities
|
||||
};
|
||||
|
@ -66,6 +67,14 @@ function createMapStateToProps() {
|
|||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
dispatchClearTracks() {
|
||||
dispatch(clearTracks());
|
||||
},
|
||||
|
||||
dispatchFetchTracks(updateProps) {
|
||||
dispatch(fetchTracks(updateProps));
|
||||
},
|
||||
|
||||
dispatchFetchLanguageProfileSchema(name, path) {
|
||||
dispatch(fetchLanguageProfileSchema());
|
||||
},
|
||||
|
@ -74,16 +83,15 @@ function createMapDispatchToProps(dispatch, props) {
|
|||
dispatch(fetchQualityProfileSchema());
|
||||
},
|
||||
|
||||
dispatchUpdateEpisodeFiles(updateProps) {
|
||||
dispatch(updateEpisodeFiles(updateProps));
|
||||
dispatchUpdateTrackFiles(updateProps) {
|
||||
dispatch(updateTrackFiles(updateProps));
|
||||
},
|
||||
|
||||
onDeletePress(episodeFileIds) {
|
||||
dispatch(deleteEpisodeFiles({ episodeFileIds }));
|
||||
onDeletePress(trackFileIds) {
|
||||
dispatch(deleteTrackFiles({ trackFileIds }));
|
||||
},
|
||||
|
||||
|
||||
onQualityChange(episodeFileIds, qualityId) {
|
||||
onQualityChange(trackFileIds, qualityId) {
|
||||
const quality = {
|
||||
quality: _.find(this.props.qualities, { id: qualityId }),
|
||||
revision: {
|
||||
|
@ -92,34 +100,42 @@ function createMapDispatchToProps(dispatch, props) {
|
|||
}
|
||||
};
|
||||
|
||||
dispatch(updateEpisodeFiles({ episodeFileIds, quality }));
|
||||
dispatch(updateTrackFiles({ trackFileIds, quality }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class EpisodeFileEditorModalContentConnector extends Component {
|
||||
class TrackFileEditorModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
const artistId = this.props.artistId;
|
||||
|
||||
this.props.dispatchFetchTracks({ artistId });
|
||||
|
||||
this.props.dispatchFetchLanguageProfileSchema();
|
||||
this.props.dispatchFetchQualityProfileSchema();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.dispatchClearTracks();
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onLanguageChange = (episodeFileIds, languageId) => {
|
||||
onLanguageChange = (trackFileIds, languageId) => {
|
||||
const language = _.find(this.props.languages, { id: languageId });
|
||||
|
||||
this.props.dispatchUpdateEpisodeFiles({ episodeFileIds, language });
|
||||
this.props.dispatchUpdateTrackFiles({ trackFileIds, language });
|
||||
}
|
||||
|
||||
onQualityChange = (episodeFileIds, qualityId) => {
|
||||
onQualityChange = (trackFileIds, qualityId) => {
|
||||
const quality = {
|
||||
quality: _.find(this.props.qualities, { id: qualityId }),
|
||||
revision: {
|
||||
|
@ -128,19 +144,21 @@ class EpisodeFileEditorModalContentConnector extends Component {
|
|||
}
|
||||
};
|
||||
|
||||
this.props.dispatchUpdateEpisodeFiles({ episodeFileIds, quality });
|
||||
this.props.dispatchUpdateTrackFiles({ trackFileIds, quality });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
dispatchFetchLanguageProfileSchema,
|
||||
dispatchFetchQualityProfileSchema,
|
||||
dispatchUpdateEpisodeFiles,
|
||||
dispatchUpdateTrackFiles,
|
||||
dispatchFetchTracks,
|
||||
dispatchClearTracks,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<EpisodeFileEditorModalContent
|
||||
<TrackFileEditorModalContent
|
||||
{...otherProps}
|
||||
onLanguageChange={this.onLanguageChange}
|
||||
onQualityChange={this.onQualityChange}
|
||||
|
@ -149,14 +167,16 @@ class EpisodeFileEditorModalContentConnector extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
EpisodeFileEditorModalContentConnector.propTypes = {
|
||||
TrackFileEditorModalContentConnector.propTypes = {
|
||||
artistId: PropTypes.number.isRequired,
|
||||
seasonNumber: PropTypes.number,
|
||||
albumId: PropTypes.number,
|
||||
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
dispatchFetchTracks: PropTypes.func.isRequired,
|
||||
dispatchClearTracks: PropTypes.func.isRequired,
|
||||
dispatchFetchLanguageProfileSchema: PropTypes.func.isRequired,
|
||||
dispatchFetchQualityProfileSchema: PropTypes.func.isRequired,
|
||||
dispatchUpdateEpisodeFiles: PropTypes.func.isRequired
|
||||
dispatchUpdateTrackFiles: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(EpisodeFileEditorModalContentConnector);
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(TrackFileEditorModalContentConnector);
|
|
@ -7,17 +7,13 @@ import TableRow from 'Components/Table/TableRow';
|
|||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||
import EpisodeQuality from 'Episode/EpisodeQuality';
|
||||
import styles from './EpisodeFileEditorRow';
|
||||
import styles from './TrackFileEditorRow';
|
||||
|
||||
function EpisodeFileEditorRow(props) {
|
||||
function TrackFileEditorRow(props) {
|
||||
const {
|
||||
id,
|
||||
seriesType,
|
||||
seasonNumber,
|
||||
episodeNumber,
|
||||
absoluteEpisodeNumber,
|
||||
trackNumber,
|
||||
relativePath,
|
||||
airDateUtc,
|
||||
language,
|
||||
quality,
|
||||
isSelected,
|
||||
|
@ -33,24 +29,13 @@ function EpisodeFileEditorRow(props) {
|
|||
/>
|
||||
|
||||
<TableRowCell>
|
||||
{seasonNumber}x{padNumber(episodeNumber, 2)}
|
||||
|
||||
{
|
||||
seriesType === 'anime' && !!absoluteEpisodeNumber &&
|
||||
<span className={styles.absoluteEpisodeNumber}>
|
||||
({absoluteEpisodeNumber})
|
||||
</span>
|
||||
}
|
||||
{padNumber(trackNumber, 2)}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell>
|
||||
{relativePath}
|
||||
</TableRowCell>
|
||||
|
||||
<RelativeDateCellConnector
|
||||
date={airDateUtc}
|
||||
/>
|
||||
|
||||
<TableRowCell>
|
||||
<Label>
|
||||
{language.name}
|
||||
|
@ -66,18 +51,14 @@ function EpisodeFileEditorRow(props) {
|
|||
);
|
||||
}
|
||||
|
||||
EpisodeFileEditorRow.propTypes = {
|
||||
TrackFileEditorRow.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
seriesType: PropTypes.string.isRequired,
|
||||
seasonNumber: PropTypes.number.isRequired,
|
||||
episodeNumber: PropTypes.number.isRequired,
|
||||
absoluteEpisodeNumber: PropTypes.number,
|
||||
trackNumber: PropTypes.number.isRequired,
|
||||
relativePath: PropTypes.string.isRequired,
|
||||
airDateUtc: PropTypes.string.isRequired,
|
||||
language: PropTypes.object.isRequired,
|
||||
quality: PropTypes.object.isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EpisodeFileEditorRow;
|
||||
export default TrackFileEditorRow;
|
|
@ -39,7 +39,6 @@ function MediaInfo(props) {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createEpisodeFileSelector from 'Store/Selectors/createEpisodeFileSelector';
|
||||
import createTrackFileSelector from 'Store/Selectors/createTrackFileSelector';
|
||||
import MediaInfo from './MediaInfo';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createEpisodeFileSelector(),
|
||||
(episodeFile) => {
|
||||
if (episodeFile) {
|
||||
createTrackFileSelector(),
|
||||
(trackFile) => {
|
||||
if (trackFile) {
|
||||
return {
|
||||
...episodeFile.mediaInfo
|
||||
...trackFile.mediaInfo
|
||||
};
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createEpisodeFileSelector from 'Store/Selectors/createEpisodeFileSelector';
|
||||
import createTrackFileSelector from 'Store/Selectors/createTrackFileSelector';
|
||||
import EpisodeLanguage from 'Episode/EpisodeLanguage';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createEpisodeFileSelector(),
|
||||
(episodeFile) => {
|
||||
createTrackFileSelector(),
|
||||
(trackFile) => {
|
||||
return {
|
||||
language: episodeFile ? episodeFile.language : undefined
|
||||
language: trackFile ? trackFile.language : undefined
|
||||
};
|
||||
}
|
||||
);
|
|
@ -9,7 +9,7 @@ import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
|||
import * as wantedActions from 'Store/Actions/wantedActions';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions';
|
||||
import { fetchEpisodeFiles, clearEpisodeFiles } from 'Store/Actions/episodeFileActions';
|
||||
import { fetchTrackFiles, clearTrackFiles } from 'Store/Actions/trackFileActions';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import CutoffUnmet from './CutoffUnmet';
|
||||
|
||||
|
@ -36,8 +36,8 @@ const mapDispatchToProps = {
|
|||
executeCommand,
|
||||
fetchQueueDetails,
|
||||
clearQueueDetails,
|
||||
fetchEpisodeFiles,
|
||||
clearEpisodeFiles
|
||||
fetchTrackFiles,
|
||||
clearTrackFiles
|
||||
};
|
||||
|
||||
class CutoffUnmetConnector extends Component {
|
||||
|
@ -52,12 +52,12 @@ class CutoffUnmetConnector extends Component {
|
|||
componentDidUpdate(prevProps) {
|
||||
if (hasDifferentItems(prevProps.items, this.props.items)) {
|
||||
const albumIds = selectUniqueIds(this.props.items, 'id');
|
||||
const episodeFileIds = selectUniqueIds(this.props.items, 'episodeFileId');
|
||||
const trackFileIds = selectUniqueIds(this.props.items, 'trackFileId');
|
||||
|
||||
this.props.fetchQueueDetails({ albumIds });
|
||||
|
||||
if (episodeFileIds.length) {
|
||||
this.props.fetchEpisodeFiles({ episodeFileIds });
|
||||
if (trackFileIds.length) {
|
||||
this.props.fetchTrackFiles({ trackFileIds });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class CutoffUnmetConnector extends Component {
|
|||
componentWillUnmount() {
|
||||
this.props.clearCutoffUnmet();
|
||||
this.props.clearQueueDetails();
|
||||
this.props.clearEpisodeFiles();
|
||||
this.props.clearTrackFiles();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -173,8 +173,8 @@ CutoffUnmetConnector.propTypes = {
|
|||
executeCommand: PropTypes.func.isRequired,
|
||||
fetchQueueDetails: PropTypes.func.isRequired,
|
||||
clearQueueDetails: PropTypes.func.isRequired,
|
||||
fetchEpisodeFiles: PropTypes.func.isRequired,
|
||||
clearEpisodeFiles: PropTypes.func.isRequired
|
||||
fetchTrackFiles: PropTypes.func.isRequired,
|
||||
clearTrackFiles: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(CutoffUnmetConnector);
|
||||
|
|
|
@ -5,7 +5,7 @@ import EpisodeTitleLink from 'Episode/EpisodeTitleLink';
|
|||
import EpisodeStatusConnector from 'Episode/EpisodeStatusConnector';
|
||||
import SeasonEpisodeNumber from 'Episode/SeasonEpisodeNumber';
|
||||
import EpisodeSearchCellConnector from 'Episode/EpisodeSearchCellConnector';
|
||||
import EpisodeFileLanguageConnector from 'EpisodeFile/EpisodeFileLanguageConnector';
|
||||
import TrackFileLanguageConnector from 'TrackFile/TrackFileLanguageConnector';
|
||||
import ArtistNameLink from 'Artist/ArtistNameLink';
|
||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
|
@ -16,7 +16,7 @@ import styles from './CutoffUnmetRow.css';
|
|||
function CutoffUnmetRow(props) {
|
||||
const {
|
||||
id,
|
||||
episodeFileId,
|
||||
trackFileId,
|
||||
series,
|
||||
seasonNumber,
|
||||
episodeNumber,
|
||||
|
@ -109,8 +109,8 @@ function CutoffUnmetRow(props) {
|
|||
key={name}
|
||||
className={styles.language}
|
||||
>
|
||||
<EpisodeFileLanguageConnector
|
||||
episodeFileId={episodeFileId}
|
||||
<TrackFileLanguageConnector
|
||||
trackFileId={trackFileId}
|
||||
/>
|
||||
</TableRowCell>
|
||||
);
|
||||
|
@ -124,7 +124,7 @@ function CutoffUnmetRow(props) {
|
|||
>
|
||||
<EpisodeStatusConnector
|
||||
episodeId={id}
|
||||
episodeFileId={episodeFileId}
|
||||
trackFileId={trackFileId}
|
||||
episodeEntity={episodeEntities.WANTED_CUTOFF_UNMET}
|
||||
/>
|
||||
</TableRowCell>
|
||||
|
@ -151,7 +151,7 @@ function CutoffUnmetRow(props) {
|
|||
|
||||
CutoffUnmetRow.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
episodeFileId: PropTypes.number,
|
||||
trackFileId: PropTypes.number,
|
||||
series: PropTypes.object.isRequired,
|
||||
seasonNumber: PropTypes.number.isRequired,
|
||||
episodeNumber: PropTypes.number.isRequired,
|
||||
|
|
|
@ -15,7 +15,7 @@ import styles from './MissingRow.css';
|
|||
function MissingRow(props) {
|
||||
const {
|
||||
id,
|
||||
// episodeFileId,
|
||||
// trackFileId,
|
||||
artist,
|
||||
// seasonNumber,
|
||||
// episodeNumber,
|
||||
|
@ -110,7 +110,7 @@ function MissingRow(props) {
|
|||
// >
|
||||
// <EpisodeStatusConnector
|
||||
// episodeId={id}
|
||||
// episodeFileId={episodeFileId}
|
||||
// trackFileId={trackFileId}
|
||||
// episodeEntity={episodeEntities.WANTED_MISSING}
|
||||
// />
|
||||
// </TableRowCell>
|
||||
|
@ -137,7 +137,7 @@ function MissingRow(props) {
|
|||
|
||||
MissingRow.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
// episodeFileId: PropTypes.number,
|
||||
// trackFileId: PropTypes.number,
|
||||
artist: PropTypes.object.isRequired,
|
||||
// seasonNumber: PropTypes.number.isRequired,
|
||||
// episodeNumber: PropTypes.number.isRequired,
|
||||
|
|
|
@ -11,7 +11,6 @@ using NzbDrone.Core.MediaFiles.Events;
|
|||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.SignalR;
|
||||
using Lidarr.Api.V3.Series;
|
||||
using Lidarr.Http;
|
||||
using Lidarr.Http.Extensions;
|
||||
using Lidarr.Http.REST;
|
||||
|
@ -49,16 +48,16 @@ namespace Lidarr.Api.V3.TrackFiles
|
|||
UpdateResource = SetQuality;
|
||||
DeleteResource = DeleteTrackFile;
|
||||
|
||||
Put["/editor"] = episodeFiles => SetQuality();
|
||||
Delete["/bulk"] = episodeFiles => DeleteTrackFiles();
|
||||
Put["/editor"] = trackFiles => SetQuality();
|
||||
Delete["/bulk"] = trackFiles => DeleteTrackFiles();
|
||||
}
|
||||
|
||||
private TrackFileResource GetTrackFile(int id)
|
||||
{
|
||||
var trackFile = _mediaFileService.Get(id);
|
||||
var series = _artistService.GetArtist(trackFile.ArtistId);
|
||||
var artist = _artistService.GetArtist(trackFile.ArtistId);
|
||||
|
||||
return trackFile.ToResource(series, _upgradableSpecification);
|
||||
return trackFile.ToResource(artist, _upgradableSpecification);
|
||||
}
|
||||
|
||||
private List<TrackFileResource> GetTrackFiles()
|
||||
|
@ -72,7 +71,7 @@ namespace Lidarr.Api.V3.TrackFiles
|
|||
throw new BadRequestException("artistId, albumId, or trackFileIds must be provided");
|
||||
}
|
||||
|
||||
if (artistIdQuery.HasValue)
|
||||
if (artistIdQuery.HasValue && !albumIdQuery.HasValue)
|
||||
{
|
||||
int artistId = Convert.ToInt32(artistIdQuery.Value);
|
||||
var artist = _artistService.GetArtist(artistId);
|
||||
|
|
|
@ -18,10 +18,10 @@ namespace Lidarr.Api.V3.Tracks
|
|||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(trackService, artistService, upgradableSpecification, signalRBroadcaster)
|
||||
{
|
||||
GetResourceAll = GetEpisodes;
|
||||
GetResourceAll = GetTracks;
|
||||
}
|
||||
|
||||
private List<TrackResource> GetEpisodes()
|
||||
private List<TrackResource> GetTracks()
|
||||
{
|
||||
var artistIdQuery = Request.Query.ArtistId;
|
||||
var albumIdQuery = Request.Query.AlbumId;
|
||||
|
|
Loading…
Add table
Reference in a new issue