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