AlbumStudio and ArtistEditor Fixes

pull/6/head
Qstick 7 years ago
parent 49309125b6
commit 70cc2ed8a5

@ -4,6 +4,7 @@ import { createSelector } from 'reselect';
import connectSection from 'Store/connectSection'; import connectSection from 'Store/connectSection';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import { setAlbumStudioSort, setAlbumStudioFilter, saveAlbumStudio } from 'Store/Actions/albumStudioActions'; import { setAlbumStudioSort, setAlbumStudioFilter, saveAlbumStudio } from 'Store/Actions/albumStudioActions';
import { fetchEpisodes, clearEpisodes } from 'Store/Actions/episodeActions';
import AlbumStudio from './AlbumStudio'; import AlbumStudio from './AlbumStudio';
function createMapStateToProps() { function createMapStateToProps() {
@ -18,6 +19,8 @@ function createMapStateToProps() {
} }
const mapDispatchToProps = { const mapDispatchToProps = {
fetchEpisodes,
clearEpisodes,
setAlbumStudioSort, setAlbumStudioSort,
setAlbumStudioFilter, setAlbumStudioFilter,
saveAlbumStudio saveAlbumStudio
@ -25,6 +28,28 @@ const mapDispatchToProps = {
class AlbumStudioConnector extends Component { class AlbumStudioConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.populate();
}
componentWillUnmount() {
this.unpopulate();
}
//
// Control
populate = () => {
this.props.fetchEpisodes();
}
unpopulate = () => {
this.props.clearEpisodes();
}
// //
// Listeners // Listeners
@ -58,6 +83,8 @@ class AlbumStudioConnector extends Component {
AlbumStudioConnector.propTypes = { AlbumStudioConnector.propTypes = {
setAlbumStudioSort: PropTypes.func.isRequired, setAlbumStudioSort: PropTypes.func.isRequired,
setAlbumStudioFilter: PropTypes.func.isRequired, setAlbumStudioFilter: PropTypes.func.isRequired,
fetchEpisodes: PropTypes.func.isRequired,
clearEpisodes: PropTypes.func.isRequired,
saveAlbumStudio: PropTypes.func.isRequired saveAlbumStudio: PropTypes.func.isRequired
}; };

@ -10,16 +10,22 @@ import AlbumStudioRow from './AlbumStudioRow';
function createMapStateToProps() { function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.episodes,
createArtistSelector(), createArtistSelector(),
(artist) => { (episodes, artist) => {
return _.pick(artist, [ const albumsInArtist = _.filter(episodes.items, { artistId: artist.id });
'status', const sortedAlbums = _.orderBy(albumsInArtist, 'releaseDate', 'desc');
'nameSlug',
'artistName', return {
'monitored', ...artist,
'albums', artistId: artist.id,
'isSaving' artistName: artist.artistName,
]); nameSlug: artist.nameSlug,
monitored: artist.monitored,
status: artist.status,
isSaving: artist.isSaving,
albums: sortedAlbums
};
} }
); );
} }
@ -50,7 +56,7 @@ class AlbumStudioRowConnector extends Component {
onAlbumMonitoredPress = (albumId, monitored) => { onAlbumMonitoredPress = (albumId, monitored) => {
this.props.toggleEpisodeMonitored({ this.props.toggleEpisodeMonitored({
albumId, albumId,
monitored: !monitored monitored
}); });
} }

@ -135,7 +135,7 @@ class AlbumRow extends Component {
return ( return (
<TableRowCell key={name}> <TableRowCell key={name}>
{ {
statistics.trackCount statistics.totalTrackCount
} }
</TableRowCell> </TableRowCell>
); );

@ -66,7 +66,7 @@ class ArtistEditorFooter extends Component {
case 'monitored': case 'monitored':
this.props.onSaveSelected({ [name]: value === 'monitored' }); this.props.onSaveSelected({ [name]: value === 'monitored' });
break; break;
case 'seasonFolder': case 'albumFolder':
this.props.onSaveSelected({ [name]: value === 'yes' }); this.props.onSaveSelected({ [name]: value === 'yes' });
break; break;
default: default:

@ -16,7 +16,7 @@ class ArtistEditorRow extends Component {
// //
// Listeners // Listeners
onSeasonFolderChange = () => { onAlbumFolderChange = () => {
// Mock handler to satisfy `onChange` being required for `CheckInput`. // Mock handler to satisfy `onChange` being required for `CheckInput`.
// //
} }
@ -77,7 +77,7 @@ class ArtistEditorRow extends Component {
name="albumFolder" name="albumFolder"
value={albumFolder} value={albumFolder}
isDisabled={true} isDisabled={true}
onChange={this.onSeasonFolderChange} onChange={this.onAlbumFolderChange}
/> />
</TableRowCell> </TableRowCell>

@ -71,9 +71,9 @@ export const BULK_DELETE_ARTIST = 'BULK_DELETE_ARTIST';
// //
// Season Pass // Season Pass
export const SET_SEASON_PASS_SORT = 'SET_SEASON_PASS_SORT'; export const SET_ALBUM_STUDIO_SORT = 'SET_ALBUM_STUDIO_SORT';
export const SET_SEASON_PASS_FILTER = 'SET_SEASON_PASS_FILTER'; export const SET_ALBUM_STUDIO_FILTER = 'SET_ALBUM_STUDIO_FILTER';
export const SAVE_SEASON_PASS = 'SAVE_SEASON_PASS'; export const SAVE_ALBUM_STUDIO = 'SAVE_ALBUM_STUDIO';
// //
// Episodes // Episodes

@ -8,7 +8,7 @@ import { fetchArtist } from './artistActions';
const section = 'albumStudio'; const section = 'albumStudio';
const albumStudioActionHandlers = { const albumStudioActionHandlers = {
[types.SAVE_SEASON_PASS]: function(payload) { [types.SAVE_ALBUM_STUDIO]: function(payload) {
return function(dispatch, getState) { return function(dispatch, getState) {
const { const {
artistIds, artistIds,
@ -30,15 +30,15 @@ const albumStudioActionHandlers = {
if (monitor) { if (monitor) {
const { const {
seasons, albums,
options: artistMonitoringOptions options: artistMonitoringOptions
} = getMonitoringOptions(_.cloneDeep(s.seasons), monitor); } = getMonitoringOptions(_.cloneDeep(s.albums), monitor);
if (!monitoringOptions) { if (!monitoringOptions) {
monitoringOptions = artistMonitoringOptions; monitoringOptions = artistMonitoringOptions;
} }
artistToUpdate.seasons = seasons; artistToUpdate.albums = albums;
} }
artist.push(artistToUpdate); artist.push(artistToUpdate);

@ -2,6 +2,6 @@ import { createAction } from 'redux-actions';
import * as types from './actionTypes'; import * as types from './actionTypes';
import albumStudioActionHandlers from './albumStudioActionHandlers'; import albumStudioActionHandlers from './albumStudioActionHandlers';
export const setAlbumStudioSort = createAction(types.SET_SEASON_PASS_SORT); export const setAlbumStudioSort = createAction(types.SET_ALBUM_STUDIO_SORT);
export const setAlbumStudioFilter = createAction(types.SET_SEASON_PASS_FILTER); export const setAlbumStudioFilter = createAction(types.SET_ALBUM_STUDIO_FILTER);
export const saveAlbumStudio = albumStudioActionHandlers[types.SAVE_SEASON_PASS]; export const saveAlbumStudio = albumStudioActionHandlers[types.SAVE_ALBUM_STUDIO];

@ -14,7 +14,7 @@ const episodeActionHandlers = {
[types.TOGGLE_EPISODE_MONITORED]: function(payload) { [types.TOGGLE_EPISODE_MONITORED]: function(payload) {
return function(dispatch, getState) { return function(dispatch, getState) {
const { const {
albumId: id, albumId,
episodeEntity = episodeEntities.EPISODES, episodeEntity = episodeEntities.EPISODES,
monitored monitored
} = payload; } = payload;
@ -22,13 +22,13 @@ const episodeActionHandlers = {
const episodeSection = _.last(episodeEntity.split('.')); const episodeSection = _.last(episodeEntity.split('.'));
dispatch(updateItem({ dispatch(updateItem({
id, id: albumId,
section: episodeSection, section: episodeSection,
isSaving: true isSaving: true
})); }));
const promise = $.ajax({ const promise = $.ajax({
url: `/album/${id}`, url: `/album/${albumId}`,
method: 'PUT', method: 'PUT',
data: JSON.stringify({ monitored }), data: JSON.stringify({ monitored }),
dataType: 'json' dataType: 'json'
@ -36,7 +36,7 @@ const episodeActionHandlers = {
promise.done((data) => { promise.done((data) => {
dispatch(updateItem({ dispatch(updateItem({
id, id: albumId,
section: episodeSection, section: episodeSection,
isSaving: false, isSaving: false,
monitored monitored
@ -45,7 +45,7 @@ const episodeActionHandlers = {
promise.fail((xhr) => { promise.fail((xhr) => {
dispatch(updateItem({ dispatch(updateItem({
id, id: albumId,
section: episodeSection, section: episodeSection,
isSaving: false isSaving: false
})); }));

@ -31,8 +31,8 @@ const albumStudioReducers = handleActions({
[types.SET]: createSetReducer(reducerSection), [types.SET]: createSetReducer(reducerSection),
[types.SET_SEASON_PASS_SORT]: createSetClientSideCollectionSortReducer(reducerSection), [types.SET_ALBUM_STUDIO_SORT]: createSetClientSideCollectionSortReducer(reducerSection),
[types.SET_SEASON_PASS_FILTER]: createSetClientSideCollectionFilterReducer(reducerSection) [types.SET_ALBUM_STUDIO_FILTER]: createSetClientSideCollectionFilterReducer(reducerSection)
}, defaultState); }, defaultState);

@ -10,10 +10,10 @@ function monitorSeasons(seasons, startingSeason) {
}); });
} }
function getMonitoringOptions(seasons, monitor) { function getMonitoringOptions(albums, monitor) {
if (!seasons.length) { if (!albums.length) {
return { return {
seasons: [], albums: [],
options: { options: {
ignoreEpisodesWithFiles: false, ignoreEpisodesWithFiles: false,
ignoreEpisodesWithoutFiles: false ignoreEpisodesWithoutFiles: false
@ -21,10 +21,10 @@ function getMonitoringOptions(seasons, monitor) {
}; };
} }
const firstSeason = _.minBy(_.reject(seasons, { seasonNumber: 0 }), 'seasonNumber').seasonNumber; const firstSeason = _.minBy(_.reject(albums, { seasonNumber: 0 }), 'seasonNumber').seasonNumber;
const lastSeason = _.maxBy(seasons, 'seasonNumber').seasonNumber; const lastSeason = _.maxBy(albums, 'seasonNumber').seasonNumber;
monitorSeasons(seasons, firstSeason); monitorSeasons(albums, firstSeason);
const monitoringOptions = { const monitoringOptions = {
ignoreEpisodesWithFiles: false, ignoreEpisodesWithFiles: false,
@ -37,11 +37,11 @@ function getMonitoringOptions(seasons, monitor) {
monitoringOptions.ignoreEpisodesWithoutFiles = true; monitoringOptions.ignoreEpisodesWithoutFiles = true;
break; break;
case 'latest': case 'latest':
monitorSeasons(seasons, lastSeason); monitorSeasons(albums, lastSeason);
break; break;
case 'first': case 'first':
monitorSeasons(seasons, lastSeason + 1); monitorSeasons(albums, lastSeason + 1);
_.find(seasons, { seasonNumber: firstSeason }).monitored = true; _.find(albums, { seasonNumber: firstSeason }).monitored = true;
break; break;
case 'missing': case 'missing':
monitoringOptions.ignoreEpisodesWithFiles = true; monitoringOptions.ignoreEpisodesWithFiles = true;
@ -50,14 +50,14 @@ function getMonitoringOptions(seasons, monitor) {
monitoringOptions.ignoreEpisodesWithoutFiles = true; monitoringOptions.ignoreEpisodesWithoutFiles = true;
break; break;
case 'none': case 'none':
monitorSeasons(seasons, lastSeason + 1); monitorSeasons(albums, lastSeason + 1);
break; break;
default: default:
break; break;
} }
return { return {
seasons: _.map(seasons, (season) => { seasons: _.map(albums, (season) => {
return _.pick(season, [ return _.pick(season, [
'seasonNumber', 'seasonNumber',
'monitored' 'monitored'

@ -32,7 +32,7 @@ namespace Lidarr.Api.V3.Albums
if (!Request.Query.ArtistId.HasValue && !albumIdsQuery.HasValue) if (!Request.Query.ArtistId.HasValue && !albumIdsQuery.HasValue)
{ {
throw new BadRequestException("artistId or albumIds must be provided"); return MapToResource(_albumService.GetAllAlbums(), false);
} }
if (artistIdQuery.HasValue) if (artistIdQuery.HasValue)

@ -15,7 +15,7 @@ namespace Lidarr.Api.V3.Artist
{ {
_artistService = artistService; _artistService = artistService;
Put["/"] = artist => SaveAll(); Put["/"] = artist => SaveAll();
Delete["/"] = artist => DeleteSeries(); Delete["/"] = artist => DeleteArtist();
} }
private Response SaveAll() private Response SaveAll()
@ -70,7 +70,7 @@ namespace Lidarr.Api.V3.Artist
.AsResponse(HttpStatusCode.Accepted); .AsResponse(HttpStatusCode.Accepted);
} }
private Response DeleteSeries() private Response DeleteArtist()
{ {
var resource = Request.Body.FromJson<ArtistEditorResource>(); var resource = Request.Body.FromJson<ArtistEditorResource>();

@ -99,7 +99,7 @@ namespace Lidarr.Api.V3.Artist
var resource = artist.ToResource(); var resource = artist.ToResource();
MapCoversToLocal(resource); MapCoversToLocal(resource);
MapAlbums(resource); //MapAlbums(resource);
FetchAndLinkArtistStatistics(resource); FetchAndLinkArtistStatistics(resource);
//PopulateAlternateTitles(resource); //PopulateAlternateTitles(resource);
@ -112,7 +112,7 @@ namespace Lidarr.Api.V3.Artist
var artistsResources = _artistService.GetAllArtists().ToResource(); var artistsResources = _artistService.GetAllArtists().ToResource();
MapCoversToLocal(artistsResources.ToArray()); MapCoversToLocal(artistsResources.ToArray());
MapAlbums(artistsResources.ToArray()); //MapAlbums(artistsResources.ToArray());
LinkArtistStatistics(artistsResources, artistStats); LinkArtistStatistics(artistsResources, artistStats);
//PopulateAlternateTitles(seriesResources); //PopulateAlternateTitles(seriesResources);

@ -164,12 +164,28 @@ namespace NzbDrone.Core.Music
var album = _albumRepository.Get(albumId); var album = _albumRepository.Get(albumId);
_albumRepository.SetMonitoredFlat(album, monitored); _albumRepository.SetMonitoredFlat(album, monitored);
var tracks = _trackService.GetTracksByAlbum(albumId);
foreach (var track in tracks)
{
track.Monitored = monitored;
}
_trackService.UpdateTracks(tracks);
_logger.Debug("Monitored flag for Album:{0} was set to {1}", albumId, monitored); _logger.Debug("Monitored flag for Album:{0} was set to {1}", albumId, monitored);
} }
public void SetMonitored(IEnumerable<int> ids, bool monitored) public void SetMonitored(IEnumerable<int> ids, bool monitored)
{ {
_albumRepository.SetMonitored(ids, monitored); _albumRepository.SetMonitored(ids, monitored);
foreach (var id in ids)
{
var tracks = _trackService.GetTracksByAlbum(id);
foreach (var track in tracks)
{
track.Monitored = monitored;
}
_trackService.UpdateTracks(tracks);
}
} }
public List<Album> UpdateAlbums(List<Album> album) public List<Album> UpdateAlbums(List<Album> album)

Loading…
Cancel
Save