mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-16 10:03:51 -07:00
New: Release Profiles, Frontend updates (#580)
* New: Release Profiles - UI Updates * New: Release Profiles - API Changes * New: Release Profiles - Test Updates * New: Release Profiles - Backend Updates * New: Interactive Artist Search * New: Change Montiored on Album Details Page * New: Show Duration on Album Details Page * Fixed: Manual Import not working if no albums are Missing * Fixed: Sort search input by sortTitle * Fixed: Queue columnLabel throwing JS error
This commit is contained in:
parent
f126eafd26
commit
3f064c94b9
409 changed files with 6882 additions and 3176 deletions
|
@ -3,7 +3,7 @@ import { set } from '../baseActions';
|
|||
|
||||
function createFetchSchemaHandler(section, url) {
|
||||
return function(getState, payload, dispatch) {
|
||||
dispatch(set({ section, isFetchingSchema: true }));
|
||||
dispatch(set({ section, isSchemaFetching: true }));
|
||||
|
||||
const promise = $.ajax({
|
||||
url
|
||||
|
@ -12,7 +12,7 @@ function createFetchSchemaHandler(section, url) {
|
|||
promise.done((data) => {
|
||||
dispatch(set({
|
||||
section,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: true,
|
||||
schemaError: null,
|
||||
schema: data
|
||||
|
@ -22,7 +22,7 @@ function createFetchSchemaHandler(section, url) {
|
|||
promise.fail((xhr) => {
|
||||
dispatch(set({
|
||||
section,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: true,
|
||||
schemaError: xhr
|
||||
}));
|
||||
|
|
|
@ -5,7 +5,7 @@ import findSelectedFilters from 'Utilities/Filter/findSelectedFilters';
|
|||
import getSectionState from 'Utilities/State/getSectionState';
|
||||
import { set, updateServerSideCollection } from '../baseActions';
|
||||
|
||||
function createFetchServerSideCollectionHandler(section, url) {
|
||||
function createFetchServerSideCollectionHandler(section, url, fetchDataAugmenter) {
|
||||
return function(getState, payload, dispatch) {
|
||||
dispatch(set({ section, isFetching: true }));
|
||||
|
||||
|
@ -19,6 +19,10 @@ function createFetchServerSideCollectionHandler(section, url) {
|
|||
'sortKey'
|
||||
]));
|
||||
|
||||
if (fetchDataAugmenter) {
|
||||
fetchDataAugmenter(getState, payload, data);
|
||||
}
|
||||
|
||||
const {
|
||||
selectedFilterKey,
|
||||
filters,
|
||||
|
|
|
@ -5,10 +5,10 @@ import createSetServerSideCollectionPageHandler from './createSetServerSideColle
|
|||
import createSetServerSideCollectionSortHandler from './createSetServerSideCollectionSortHandler';
|
||||
import createSetServerSideCollectionFilterHandler from './createSetServerSideCollectionFilterHandler';
|
||||
|
||||
function createServerSideCollectionHandlers(section, url, fetchThunk, handlers) {
|
||||
function createServerSideCollectionHandlers(section, url, fetchThunk, handlers, fetchDataAugmenter) {
|
||||
const actionHandlers = {};
|
||||
const fetchHandlerType = handlers[serverSideCollectionHandlers.FETCH];
|
||||
const fetchHandler = createFetchServerSideCollectionHandler(section, url);
|
||||
const fetchHandler = createFetchServerSideCollectionHandler(section, url, fetchDataAugmenter);
|
||||
actionHandlers[fetchHandlerType] = fetchHandler;
|
||||
|
||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.FIRST_PAGE)) {
|
||||
|
|
|
@ -70,7 +70,7 @@ export default {
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: [],
|
||||
|
|
|
@ -70,7 +70,7 @@ export default {
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: [],
|
||||
|
|
|
@ -70,7 +70,7 @@ export default {
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: [],
|
||||
|
|
|
@ -54,7 +54,7 @@ export default {
|
|||
error: null,
|
||||
isDeleting: false,
|
||||
deleteError: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: {},
|
||||
|
|
|
@ -54,7 +54,7 @@ export default {
|
|||
error: null,
|
||||
isDeleting: false,
|
||||
deleteError: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: {},
|
||||
|
|
|
@ -67,7 +67,7 @@ export default {
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: [],
|
||||
|
|
|
@ -54,7 +54,7 @@ export default {
|
|||
error: null,
|
||||
isDeleting: false,
|
||||
deleteError: null,
|
||||
isFetchingSchema: false,
|
||||
isSchemaFetching: false,
|
||||
isSchemaPopulated: false,
|
||||
schemaError: null,
|
||||
schema: {},
|
||||
|
|
71
frontend/src/Store/Actions/Settings/releaseProfiles.js
Normal file
71
frontend/src/Store/Actions/Settings/releaseProfiles.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
import { createAction } from 'redux-actions';
|
||||
import { createThunk } from 'Store/thunks';
|
||||
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
||||
const section = 'settings.releaseProfiles';
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
export const FETCH_RELEASE_PROFILES = 'settings/releaseProfiles/fetchReleaseProfiles';
|
||||
export const SAVE_RELEASE_PROFILE = 'settings/releaseProfiles/saveReleaseProfile';
|
||||
export const DELETE_RELEASE_PROFILE = 'settings/releaseProfiles/deleteReleaseProfile';
|
||||
export const SET_RELEASE_PROFILE_VALUE = 'settings/releaseProfiles/setReleaseProfileValue';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
||||
export const fetchReleaseProfiles = createThunk(FETCH_RELEASE_PROFILES);
|
||||
export const saveReleaseProfile = createThunk(SAVE_RELEASE_PROFILE);
|
||||
export const deleteReleaseProfile = createThunk(DELETE_RELEASE_PROFILE);
|
||||
|
||||
export const setReleaseProfileValue = createAction(SET_RELEASE_PROFILE_VALUE, (payload) => {
|
||||
return {
|
||||
section,
|
||||
...payload
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// Details
|
||||
|
||||
export default {
|
||||
|
||||
//
|
||||
// State
|
||||
|
||||
defaultState: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
isSaving: false,
|
||||
saveError: null,
|
||||
items: [],
|
||||
pendingChanges: {}
|
||||
},
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
actionHandlers: {
|
||||
[FETCH_RELEASE_PROFILES]: createFetchHandler(section, '/releaseprofile'),
|
||||
|
||||
[SAVE_RELEASE_PROFILE]: createSaveProviderHandler(section, '/releaseprofile'),
|
||||
|
||||
[DELETE_RELEASE_PROFILE]: createRemoveItemHandler(section, '/releaseprofile')
|
||||
},
|
||||
|
||||
//
|
||||
// Reducers
|
||||
|
||||
reducers: {
|
||||
[SET_RELEASE_PROFILE_VALUE]: createSetSettingValueReducer(section)
|
||||
}
|
||||
|
||||
};
|
|
@ -1,71 +0,0 @@
|
|||
import { createAction } from 'redux-actions';
|
||||
import { createThunk } from 'Store/thunks';
|
||||
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
||||
const section = 'settings.restrictions';
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
export const FETCH_RESTRICTIONS = 'settings/restrictions/fetchRestrictions';
|
||||
export const SAVE_RESTRICTION = 'settings/restrictions/saveRestriction';
|
||||
export const DELETE_RESTRICTION = 'settings/restrictions/deleteRestriction';
|
||||
export const SET_RESTRICTION_VALUE = 'settings/restrictions/setRestrictionValue';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
||||
export const fetchRestrictions = createThunk(FETCH_RESTRICTIONS);
|
||||
export const saveRestriction = createThunk(SAVE_RESTRICTION);
|
||||
export const deleteRestriction = createThunk(DELETE_RESTRICTION);
|
||||
|
||||
export const setRestrictionValue = createAction(SET_RESTRICTION_VALUE, (payload) => {
|
||||
return {
|
||||
section,
|
||||
...payload
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// Details
|
||||
|
||||
export default {
|
||||
|
||||
//
|
||||
// State
|
||||
|
||||
defaultState: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
isSaving: false,
|
||||
saveError: null,
|
||||
items: [],
|
||||
pendingChanges: {}
|
||||
},
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
actionHandlers: {
|
||||
[FETCH_RESTRICTIONS]: createFetchHandler(section, '/restriction'),
|
||||
|
||||
[SAVE_RESTRICTION]: createSaveProviderHandler(section, '/restriction'),
|
||||
|
||||
[DELETE_RESTRICTION]: createRemoveItemHandler(section, '/restriction')
|
||||
},
|
||||
|
||||
//
|
||||
// Reducers
|
||||
|
||||
reducers: {
|
||||
[SET_RESTRICTION_VALUE]: createSetSettingValueReducer(section)
|
||||
}
|
||||
|
||||
};
|
|
@ -2,11 +2,12 @@ import _ from 'lodash';
|
|||
import $ from 'jquery';
|
||||
import { createAction } from 'redux-actions';
|
||||
import { batchActions } from 'redux-batched-actions';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import monitorOptions from 'Utilities/Artist/monitorOptions';
|
||||
import getSectionState from 'Utilities/State/getSectionState';
|
||||
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
import getNewArtist from 'Utilities/Artist/getNewArtist';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
import { set, update, updateItem } from './baseActions';
|
||||
|
@ -31,7 +32,7 @@ export const defaultState = {
|
|||
|
||||
defaults: {
|
||||
rootFolderPath: '',
|
||||
monitor: 'allAlbums',
|
||||
monitor: monitorOptions[0].key,
|
||||
qualityProfileId: 0,
|
||||
languageProfileId: 0,
|
||||
metadataProfileId: 0,
|
||||
|
|
|
@ -189,13 +189,11 @@ export const actionHandlers = handleThunks({
|
|||
monitored
|
||||
} = payload;
|
||||
|
||||
const albumSection = _.last(albumEntity.split('.'));
|
||||
|
||||
dispatch(batchActions(
|
||||
albumIds.map((albumId) => {
|
||||
return updateItem({
|
||||
id: albumId,
|
||||
section: albumSection,
|
||||
section: albumEntity,
|
||||
isSaving: true
|
||||
});
|
||||
})
|
||||
|
@ -213,7 +211,7 @@ export const actionHandlers = handleThunks({
|
|||
albumIds.map((albumId) => {
|
||||
return updateItem({
|
||||
id: albumId,
|
||||
section: albumSection,
|
||||
section: albumEntity,
|
||||
isSaving: false,
|
||||
monitored
|
||||
});
|
||||
|
@ -226,7 +224,7 @@ export const actionHandlers = handleThunks({
|
|||
albumIds.map((albumId) => {
|
||||
return updateItem({
|
||||
id: albumId,
|
||||
section: albumSection,
|
||||
section: albumEntity,
|
||||
isSaving: false
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import { createAction } from 'redux-actions';
|
||||
import getMonitoringOptions from 'Utilities/Artist/getMonitoringOptions';
|
||||
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
||||
|
@ -9,7 +7,7 @@ import createSetClientSideCollectionFilterReducer from './Creators/Reducers/crea
|
|||
import createHandleActions from './Creators/createHandleActions';
|
||||
import { set } from './baseActions';
|
||||
import { fetchAlbums } from './albumActions';
|
||||
import { fetchArtist, filters, filterPredicates } from './artistActions';
|
||||
import { filters, filterPredicates } from './artistActions';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
@ -113,31 +111,15 @@ export const actionHandlers = handleThunks({
|
|||
monitor
|
||||
} = payload;
|
||||
|
||||
let monitoringOptions = null;
|
||||
const artist = [];
|
||||
const allArtists = getState().artist.items;
|
||||
|
||||
artistIds.forEach((id) => {
|
||||
const s = _.find(allArtists, { id });
|
||||
const artistToUpdate = { id };
|
||||
|
||||
if (payload.hasOwnProperty('monitored')) {
|
||||
artistToUpdate.monitored = monitored;
|
||||
}
|
||||
|
||||
if (monitor) {
|
||||
const {
|
||||
albums,
|
||||
options: artistMonitoringOptions
|
||||
} = getMonitoringOptions(monitor);
|
||||
|
||||
if (!monitoringOptions) {
|
||||
monitoringOptions = artistMonitoringOptions;
|
||||
}
|
||||
|
||||
artistToUpdate.albums = albums;
|
||||
}
|
||||
|
||||
artist.push(artistToUpdate);
|
||||
});
|
||||
|
||||
|
@ -151,7 +133,7 @@ export const actionHandlers = handleThunks({
|
|||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
artist,
|
||||
monitoringOptions
|
||||
monitoringOptions: { monitor }
|
||||
}),
|
||||
dataType: 'json'
|
||||
});
|
||||
|
|
|
@ -54,6 +54,7 @@ export const defaultState = {
|
|||
},
|
||||
|
||||
tableOptions: {
|
||||
showBanners: false,
|
||||
showSearchAction: false
|
||||
},
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import { createAction } from 'redux-actions';
|
|||
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import { sortDirections } from 'Helpers/Props';
|
||||
import createClearReducer from './Creators/Reducers/createClearReducer';
|
||||
import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
||||
|
@ -87,6 +88,7 @@ export const GOTO_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPage';
|
|||
export const SET_BLACKLIST_SORT = 'blacklist/setBlacklistSort';
|
||||
export const SET_BLACKLIST_TABLE_OPTION = 'blacklist/setBlacklistTableOption';
|
||||
export const REMOVE_FROM_BLACKLIST = 'blacklist/removeFromBlacklist';
|
||||
export const CLEAR_BLACKLIST = 'blacklist/clearBlacklist';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
@ -100,6 +102,7 @@ export const gotoBlacklistPage = createThunk(GOTO_BLACKLIST_PAGE);
|
|||
export const setBlacklistSort = createThunk(SET_BLACKLIST_SORT);
|
||||
export const setBlacklistTableOption = createAction(SET_BLACKLIST_TABLE_OPTION);
|
||||
export const removeFromBlacklist = createThunk(REMOVE_FROM_BLACKLIST);
|
||||
export const clearBlacklist = createAction(CLEAR_BLACKLIST);
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
@ -127,6 +130,15 @@ export const actionHandlers = handleThunks({
|
|||
|
||||
export const reducers = createHandleActions({
|
||||
|
||||
[SET_BLACKLIST_TABLE_OPTION]: createSetTableOptionReducer(section)
|
||||
[SET_BLACKLIST_TABLE_OPTION]: createSetTableOptionReducer(section),
|
||||
|
||||
[CLEAR_BLACKLIST]: createClearReducer(section, {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: [],
|
||||
totalPages: 0,
|
||||
totalRecords: 0
|
||||
})
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -6,8 +6,11 @@ import moment from 'moment';
|
|||
import { filterTypes } from 'Helpers/Props';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import * as calendarViews from 'Calendar/calendarViews';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import createClearReducer from './Creators/Reducers/createClearReducer';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
import { set, update } from './baseActions';
|
||||
import { executeCommandHelper } from './commandActions';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
@ -35,6 +38,12 @@ export const defaultState = {
|
|||
showUpcoming: true,
|
||||
error: null,
|
||||
items: [],
|
||||
searchMissingCommandId: null,
|
||||
|
||||
options: {
|
||||
collapseMultipleAlbums: false,
|
||||
showCutoffUnmetIcon: false
|
||||
},
|
||||
|
||||
selectedFilterKey: 'monitored',
|
||||
|
||||
|
@ -67,7 +76,7 @@ export const defaultState = {
|
|||
export const persistState = [
|
||||
'calendar.view',
|
||||
'calendar.selectedFilterKey',
|
||||
'calendar.showUpcoming'
|
||||
'calendar.options'
|
||||
];
|
||||
|
||||
//
|
||||
|
@ -78,9 +87,11 @@ export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount';
|
|||
export const SET_CALENDAR_FILTER = 'calendar/setCalendarFilter';
|
||||
export const SET_CALENDAR_VIEW = 'calendar/setCalendarView';
|
||||
export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday';
|
||||
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
|
||||
export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange';
|
||||
export const CLEAR_CALENDAR = 'calendar/clearCalendar';
|
||||
export const SET_CALENDAR_OPTION = 'calendar/setCalendarOption';
|
||||
export const SEARCH_MISSING = 'calendar/searchMissing';
|
||||
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
|
||||
|
||||
//
|
||||
// Helpers
|
||||
|
@ -188,6 +199,8 @@ export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY);
|
|||
export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE);
|
||||
export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE);
|
||||
export const clearCalendar = createAction(CLEAR_CALENDAR);
|
||||
export const setCalendarOption = createAction(SET_CALENDAR_OPTION);
|
||||
export const searchMissing = createThunk(SEARCH_MISSING);
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
@ -195,11 +208,12 @@ export const clearCalendar = createAction(CLEAR_CALENDAR);
|
|||
export const actionHandlers = handleThunks({
|
||||
[FETCH_CALENDAR]: function(getState, payload, dispatch) {
|
||||
const state = getState();
|
||||
const unmonitored = state.calendar.selectedFilterKey === 'all';
|
||||
const calendar = state.calendar;
|
||||
const unmonitored = calendar.selectedFilterKey === 'all';
|
||||
|
||||
const {
|
||||
time,
|
||||
view
|
||||
time = calendar.time,
|
||||
view = calendar.view
|
||||
} = payload;
|
||||
|
||||
const dayCount = state.calendar.dayCount;
|
||||
|
@ -328,6 +342,22 @@ export const actionHandlers = handleThunks({
|
|||
const time = moment(state.calendar.time).add(amount, viewRanges[view]);
|
||||
|
||||
dispatch(fetchCalendar({ time, view }));
|
||||
},
|
||||
|
||||
[SEARCH_MISSING]: function(getState, payload, dispatch) {
|
||||
const { albumIds } = payload;
|
||||
|
||||
const commandPayload = {
|
||||
name: commandNames.ALBUM_SEARCH,
|
||||
albumIds
|
||||
};
|
||||
|
||||
executeCommandHelper(commandPayload, dispatch).then((data) => {
|
||||
dispatch(set({
|
||||
section,
|
||||
searchMissingCommandId: data.id
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -336,15 +366,23 @@ export const actionHandlers = handleThunks({
|
|||
|
||||
export const reducers = createHandleActions({
|
||||
|
||||
[CLEAR_CALENDAR]: (state) => {
|
||||
const {
|
||||
view,
|
||||
selectedFilterKey,
|
||||
showUpcoming,
|
||||
...otherDefaultState
|
||||
} = defaultState;
|
||||
[CLEAR_CALENDAR]: createClearReducer(section, {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
}),
|
||||
|
||||
return Object.assign({}, state, otherDefaultState);
|
||||
[SET_CALENDAR_OPTION]: function(state, { payload }) {
|
||||
const options = state.options;
|
||||
|
||||
return {
|
||||
...state,
|
||||
options: {
|
||||
...options,
|
||||
...payload
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -121,6 +121,34 @@ function scheduleRemoveCommand(command, dispatch) {
|
|||
}, 60000 * 5);
|
||||
}
|
||||
|
||||
export function executeCommandHelper( payload, dispatch) {
|
||||
// TODO: show a message for the user
|
||||
if (lastCommand && isSameCommand(lastCommand, payload)) {
|
||||
console.warn('Please wait at least 5 seconds before running this command again');
|
||||
}
|
||||
|
||||
lastCommand = payload;
|
||||
|
||||
// clear last command after 5 seconds.
|
||||
if (lastCommandTimeout) {
|
||||
clearTimeout(lastCommandTimeout);
|
||||
}
|
||||
|
||||
lastCommandTimeout = setTimeout(() => {
|
||||
lastCommand = null;
|
||||
}, 5000);
|
||||
|
||||
const promise = $.ajax({
|
||||
url: '/command',
|
||||
method: 'POST',
|
||||
data: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
return promise.then((data) => {
|
||||
dispatch(addCommand(data));
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
|
@ -128,31 +156,7 @@ export const actionHandlers = handleThunks({
|
|||
[FETCH_COMMANDS]: createFetchHandler('commands', '/command'),
|
||||
|
||||
[EXECUTE_COMMAND]: function(getState, payload, dispatch) {
|
||||
// TODO: show a message for the user
|
||||
if (lastCommand && isSameCommand(lastCommand, payload)) {
|
||||
console.warn('Please wait at least 5 seconds before running this command again');
|
||||
}
|
||||
|
||||
lastCommand = payload;
|
||||
|
||||
// clear last command after 5 seconds.
|
||||
if (lastCommandTimeout) {
|
||||
clearTimeout(lastCommandTimeout);
|
||||
}
|
||||
|
||||
lastCommandTimeout = setTimeout(() => {
|
||||
lastCommand = null;
|
||||
}, 5000);
|
||||
|
||||
const promise = $.ajax({
|
||||
url: '/command',
|
||||
method: 'POST',
|
||||
data: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
promise.done((data) => {
|
||||
dispatch(addCommand(data));
|
||||
});
|
||||
executeCommandHelper(payload, dispatch);
|
||||
},
|
||||
|
||||
[CANCEL_COMMAND]: createRemoveItemHandler(section, '/command'),
|
||||
|
|
|
@ -278,11 +278,13 @@ export const reducers = createHandleActions({
|
|||
|
||||
[SET_HISTORY_TABLE_OPTION]: createSetTableOptionReducer(section),
|
||||
|
||||
[CLEAR_HISTORY]: createClearReducer('history', {
|
||||
[CLEAR_HISTORY]: createClearReducer(section, {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
items: [],
|
||||
totalPages: 0,
|
||||
totalRecords: 0
|
||||
})
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -36,6 +36,7 @@ export const defaultState = {
|
|||
export const QUEUE_LOOKUP_ARTIST = 'importArtist/queueLookupArtist';
|
||||
export const START_LOOKUP_ARTIST = 'importArtist/startLookupArtist';
|
||||
export const CANCEL_LOOKUP_ARTIST = 'importArtist/cancelLookupArtist';
|
||||
export const LOOKUP_UNSEARCHED_ARTIST = 'importArtist/lookupUnsearchedArtist';
|
||||
export const CLEAR_IMPORT_ARTIST = 'importArtist/clearImportArtist';
|
||||
export const SET_IMPORT_ARTIST_VALUE = 'importArtist/setImportArtistValue';
|
||||
export const IMPORT_ARTIST = 'importArtist/importArtist';
|
||||
|
@ -46,6 +47,7 @@ export const IMPORT_ARTIST = 'importArtist/importArtist';
|
|||
export const queueLookupArtist = createThunk(QUEUE_LOOKUP_ARTIST);
|
||||
export const startLookupArtist = createThunk(START_LOOKUP_ARTIST);
|
||||
export const importArtist = createThunk(IMPORT_ARTIST);
|
||||
export const lookupUnsearchedArtist = createThunk(LOOKUP_UNSEARCHED_ARTIST);
|
||||
export const clearImportArtist = createAction(CLEAR_IMPORT_ARTIST);
|
||||
export const cancelLookupArtist = createAction(CANCEL_LOOKUP_ARTIST);
|
||||
|
||||
|
@ -83,7 +85,7 @@ export const actionHandlers = handleThunks({
|
|||
section,
|
||||
...item,
|
||||
term,
|
||||
queued: true,
|
||||
isQueued: true,
|
||||
items: []
|
||||
}));
|
||||
|
||||
|
@ -155,7 +157,7 @@ export const actionHandlers = handleThunks({
|
|||
isPopulated: true,
|
||||
error: null,
|
||||
items: data,
|
||||
queued: false,
|
||||
isQueued: false,
|
||||
selectedArtist: queued.selectedArtist || data[0],
|
||||
updateOnly: true
|
||||
}));
|
||||
|
@ -168,7 +170,7 @@ export const actionHandlers = handleThunks({
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: xhr,
|
||||
queued: false,
|
||||
isQueued: false,
|
||||
updateOnly: true
|
||||
}));
|
||||
});
|
||||
|
@ -180,6 +182,29 @@ export const actionHandlers = handleThunks({
|
|||
});
|
||||
},
|
||||
|
||||
[LOOKUP_UNSEARCHED_ARTIST]: function(getState, payload, dispatch) {
|
||||
const state = getState().importArtist;
|
||||
|
||||
if (state.isLookingUpArtist) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.items.forEach((item) => {
|
||||
const id = item.id;
|
||||
|
||||
if (
|
||||
!item.isPopulated &&
|
||||
!queue.includes(id)
|
||||
) {
|
||||
queue.push(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
if (queue.length) {
|
||||
dispatch(startLookupArtist({ start: true }));
|
||||
}
|
||||
},
|
||||
|
||||
[IMPORT_ARTIST]: function(getState, payload, dispatch) {
|
||||
dispatch(set({ section, isImporting: true }));
|
||||
|
||||
|
@ -251,7 +276,23 @@ export const actionHandlers = handleThunks({
|
|||
export const reducers = createHandleActions({
|
||||
|
||||
[CANCEL_LOOKUP_ARTIST]: function(state) {
|
||||
return Object.assign({}, state, { isLookingUpArtist: false });
|
||||
queue.splice(0, queue.length);
|
||||
|
||||
const items = state.items.map((item) => {
|
||||
if (item.isQueued) {
|
||||
return {
|
||||
...item,
|
||||
isQueued: false
|
||||
};
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
isLookingUpArtist: false,
|
||||
items
|
||||
});
|
||||
},
|
||||
|
||||
[CLEAR_IMPORT_ARTIST]: function(state) {
|
||||
|
|
|
@ -24,6 +24,10 @@ const paged = `${section}.paged`;
|
|||
// State
|
||||
|
||||
export const defaultState = {
|
||||
options: {
|
||||
includeUnknownArtistItems: false
|
||||
},
|
||||
|
||||
status: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
|
@ -54,6 +58,7 @@ export const defaultState = {
|
|||
{
|
||||
name: 'status',
|
||||
columnLabel: 'Status',
|
||||
isSortable: true,
|
||||
isVisible: true,
|
||||
isModifiable: false
|
||||
},
|
||||
|
@ -75,6 +80,12 @@ export const defaultState = {
|
|||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'language',
|
||||
label: 'Language',
|
||||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'quality',
|
||||
label: 'Quality',
|
||||
|
@ -122,12 +133,20 @@ export const defaultState = {
|
|||
};
|
||||
|
||||
export const persistState = [
|
||||
'queue.options',
|
||||
'queue.paged.pageSize',
|
||||
'queue.paged.sortKey',
|
||||
'queue.paged.sortDirection',
|
||||
'queue.paged.columns'
|
||||
];
|
||||
|
||||
//
|
||||
// Helpers
|
||||
|
||||
function fetchDataAugmenter(getState, payload, data) {
|
||||
data.includeUnknownArtistItems = getState().queue.options.includeUnknownArtistItems;
|
||||
}
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
|
@ -144,6 +163,7 @@ export const GOTO_LAST_QUEUE_PAGE = 'queue/gotoQueueLastPage';
|
|||
export const GOTO_QUEUE_PAGE = 'queue/gotoQueuePage';
|
||||
export const SET_QUEUE_SORT = 'queue/setQueueSort';
|
||||
export const SET_QUEUE_TABLE_OPTION = 'queue/setQueueTableOption';
|
||||
export const SET_QUEUE_OPTION = 'queue/setQueueOption';
|
||||
export const CLEAR_QUEUE = 'queue/clearQueue';
|
||||
|
||||
export const GRAB_QUEUE_ITEM = 'queue/grabQueueItem';
|
||||
|
@ -167,6 +187,7 @@ export const gotoQueueLastPage = createThunk(GOTO_LAST_QUEUE_PAGE);
|
|||
export const gotoQueuePage = createThunk(GOTO_QUEUE_PAGE);
|
||||
export const setQueueSort = createThunk(SET_QUEUE_SORT);
|
||||
export const setQueueTableOption = createAction(SET_QUEUE_TABLE_OPTION);
|
||||
export const setQueueOption = createAction(SET_QUEUE_OPTION);
|
||||
export const clearQueue = createAction(CLEAR_QUEUE);
|
||||
|
||||
export const grabQueueItem = createThunk(GRAB_QUEUE_ITEM);
|
||||
|
@ -217,7 +238,9 @@ export const actionHandlers = handleThunks({
|
|||
[serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_QUEUE_PAGE,
|
||||
[serverSideCollectionHandlers.EXACT_PAGE]: GOTO_QUEUE_PAGE,
|
||||
[serverSideCollectionHandlers.SORT]: SET_QUEUE_SORT
|
||||
}),
|
||||
},
|
||||
fetchDataAugmenter
|
||||
),
|
||||
|
||||
[GRAB_QUEUE_ITEM]: function(getState, payload, dispatch) {
|
||||
const id = payload.id;
|
||||
|
@ -392,11 +415,25 @@ export const reducers = createHandleActions({
|
|||
|
||||
[SET_QUEUE_TABLE_OPTION]: createSetTableOptionReducer(paged),
|
||||
|
||||
[SET_QUEUE_OPTION]: function(state, { payload }) {
|
||||
const queueOptions = state.options;
|
||||
|
||||
return {
|
||||
...state,
|
||||
options: {
|
||||
...queueOptions,
|
||||
...payload
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
[CLEAR_QUEUE]: createClearReducer(paged, {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
items: [],
|
||||
totalPages: 0,
|
||||
totalRecords: 0
|
||||
})
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -11,6 +11,9 @@ import createHandleActions from './Creators/createHandleActions';
|
|||
// Variables
|
||||
|
||||
export const section = 'releases';
|
||||
export const albumSection = 'releases.album';
|
||||
export const artistSection = 'releases.artist';
|
||||
|
||||
let abortCurrentRequest = null;
|
||||
|
||||
//
|
||||
|
@ -139,12 +142,21 @@ export const defaultState = {
|
|||
label: 'Rejections',
|
||||
type: filterBuilderTypes.NUMBER
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
album: {
|
||||
selectedFilterKey: 'all'
|
||||
},
|
||||
|
||||
artist: {
|
||||
selectedFilterKey: 'discography-pack'
|
||||
}
|
||||
};
|
||||
|
||||
export const persistState = [
|
||||
'releases.selectedFilterKey',
|
||||
'releases.customFilters'
|
||||
'releases.album.customFilters',
|
||||
'releases.artist.customFilters'
|
||||
];
|
||||
|
||||
//
|
||||
|
@ -156,7 +168,8 @@ export const SET_RELEASES_SORT = 'releases/setReleasesSort';
|
|||
export const CLEAR_RELEASES = 'releases/clearReleases';
|
||||
export const GRAB_RELEASE = 'releases/grabRelease';
|
||||
export const UPDATE_RELEASE = 'releases/updateRelease';
|
||||
export const SET_RELEASES_FILTER = 'releases/setReleasesFilter';
|
||||
export const SET_ALBUM_RELEASES_FILTER = 'releases/setAlbumReleasesFilter';
|
||||
export const SET_ARTIST_RELEASES_FILTER = 'releases/setArtistReleasesFilter';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
@ -167,7 +180,8 @@ export const setReleasesSort = createAction(SET_RELEASES_SORT);
|
|||
export const clearReleases = createAction(CLEAR_RELEASES);
|
||||
export const grabRelease = createThunk(GRAB_RELEASE);
|
||||
export const updateRelease = createAction(UPDATE_RELEASE);
|
||||
export const setReleasesFilter = createAction(SET_RELEASES_FILTER);
|
||||
export const setAlbumReleasesFilter = createAction(SET_ALBUM_RELEASES_FILTER);
|
||||
export const setArtistReleasesFilter = createAction(SET_ARTIST_RELEASES_FILTER);
|
||||
|
||||
//
|
||||
// Helpers
|
||||
|
@ -231,7 +245,13 @@ export const actionHandlers = handleThunks({
|
|||
export const reducers = createHandleActions({
|
||||
|
||||
[CLEAR_RELEASES]: (state) => {
|
||||
return Object.assign({}, state, defaultState);
|
||||
const {
|
||||
album,
|
||||
artist,
|
||||
...otherDefaultState
|
||||
} = defaultState;
|
||||
|
||||
return Object.assign({}, state, otherDefaultState);
|
||||
},
|
||||
|
||||
[UPDATE_RELEASE]: (state, { payload }) => {
|
||||
|
@ -254,6 +274,7 @@ export const reducers = createHandleActions({
|
|||
},
|
||||
|
||||
[SET_RELEASES_SORT]: createSetClientSideCollectionSortReducer(section),
|
||||
[SET_RELEASES_FILTER]: createSetClientSideCollectionFilterReducer(section)
|
||||
[SET_ALBUM_RELEASES_FILTER]: createSetClientSideCollectionFilterReducer(albumSection),
|
||||
[SET_ARTIST_RELEASES_FILTER]: createSetClientSideCollectionFilterReducer(artistSection)
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -18,8 +18,8 @@ import namingExamples from './Settings/namingExamples';
|
|||
import notifications from './Settings/notifications';
|
||||
import qualityDefinitions from './Settings/qualityDefinitions';
|
||||
import qualityProfiles from './Settings/qualityProfiles';
|
||||
import releaseProfiles from './Settings/releaseProfiles';
|
||||
import remotePathMappings from './Settings/remotePathMappings';
|
||||
import restrictions from './Settings/restrictions';
|
||||
import ui from './Settings/ui';
|
||||
|
||||
export * from './Settings/delayProfiles';
|
||||
|
@ -39,8 +39,8 @@ export * from './Settings/namingExamples';
|
|||
export * from './Settings/notifications';
|
||||
export * from './Settings/qualityDefinitions';
|
||||
export * from './Settings/qualityProfiles';
|
||||
export * from './Settings/releaseProfiles';
|
||||
export * from './Settings/remotePathMappings';
|
||||
export * from './Settings/restrictions';
|
||||
export * from './Settings/ui';
|
||||
|
||||
//
|
||||
|
@ -71,8 +71,8 @@ export const defaultState = {
|
|||
notifications: notifications.defaultState,
|
||||
qualityDefinitions: qualityDefinitions.defaultState,
|
||||
qualityProfiles: qualityProfiles.defaultState,
|
||||
releaseProfiles: releaseProfiles.defaultState,
|
||||
remotePathMappings: remotePathMappings.defaultState,
|
||||
restrictions: restrictions.defaultState,
|
||||
ui: ui.defaultState
|
||||
};
|
||||
|
||||
|
@ -111,8 +111,8 @@ export const actionHandlers = handleThunks({
|
|||
...notifications.actionHandlers,
|
||||
...qualityDefinitions.actionHandlers,
|
||||
...qualityProfiles.actionHandlers,
|
||||
...releaseProfiles.actionHandlers,
|
||||
...remotePathMappings.actionHandlers,
|
||||
...restrictions.actionHandlers,
|
||||
...ui.actionHandlers
|
||||
});
|
||||
|
||||
|
@ -142,8 +142,8 @@ export const reducers = createHandleActions({
|
|||
...notifications.reducers,
|
||||
...qualityDefinitions.reducers,
|
||||
...qualityProfiles.reducers,
|
||||
...releaseProfiles.reducers,
|
||||
...remotePathMappings.reducers,
|
||||
...restrictions.reducers,
|
||||
...ui.reducers
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -5,6 +5,7 @@ import { filterTypes, sortDirections } from 'Helpers/Props';
|
|||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import { setAppValue } from 'Store/Actions/appActions';
|
||||
import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
|
||||
import createClearReducer from './Creators/Reducers/createClearReducer';
|
||||
import createFetchHandler from './Creators/createFetchHandler';
|
||||
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
|
@ -79,25 +80,30 @@ export const defaultState = {
|
|||
columns: [
|
||||
{
|
||||
name: 'level',
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
columnLabel: 'Level',
|
||||
isSortable: false,
|
||||
isVisible: true,
|
||||
isModifiable: false
|
||||
},
|
||||
{
|
||||
name: 'logger',
|
||||
label: 'Component',
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
isSortable: false,
|
||||
isVisible: true,
|
||||
isModifiable: false
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
label: 'Message',
|
||||
isVisible: true
|
||||
isVisible: true,
|
||||
isModifiable: false
|
||||
},
|
||||
{
|
||||
name: 'time',
|
||||
label: 'Time',
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
isVisible: true,
|
||||
isModifiable: false
|
||||
},
|
||||
{
|
||||
name: 'actions',
|
||||
|
@ -199,7 +205,8 @@ export const GOTO_LAST_LOGS_PAGE = 'system/logs/gotoLogsLastPage';
|
|||
export const GOTO_LOGS_PAGE = 'system/logs/gotoLogsPage';
|
||||
export const SET_LOGS_SORT = 'system/logs/setLogsSort';
|
||||
export const SET_LOGS_FILTER = 'system/logs/setLogsFilter';
|
||||
export const SET_LOGS_TABLE_OPTION = 'system/logs/ssetLogsTableOption';
|
||||
export const SET_LOGS_TABLE_OPTION = 'system/logs/setLogsTableOption';
|
||||
export const CLEAR_LOGS_TABLE = 'system/logs/clearLogsTable';
|
||||
|
||||
export const FETCH_LOG_FILES = 'system/logFiles/fetchLogFiles';
|
||||
export const FETCH_UPDATE_LOG_FILES = 'system/updateLogFiles/fetchUpdateLogFiles';
|
||||
|
@ -233,6 +240,7 @@ export const gotoLogsPage = createThunk(GOTO_LOGS_PAGE);
|
|||
export const setLogsSort = createThunk(SET_LOGS_SORT);
|
||||
export const setLogsFilter = createThunk(SET_LOGS_FILTER);
|
||||
export const setLogsTableOption = createAction(SET_LOGS_TABLE_OPTION);
|
||||
export const clearLogsTable = createAction(CLEAR_LOGS_TABLE);
|
||||
|
||||
export const fetchLogFiles = createThunk(FETCH_LOG_FILES);
|
||||
export const fetchUpdateLogFiles = createThunk(FETCH_UPDATE_LOG_FILES);
|
||||
|
@ -370,6 +378,15 @@ export const reducers = createHandleActions({
|
|||
};
|
||||
},
|
||||
|
||||
[SET_LOGS_TABLE_OPTION]: createSetTableOptionReducer('logs')
|
||||
[SET_LOGS_TABLE_OPTION]: createSetTableOptionReducer('logs'),
|
||||
|
||||
[CLEAR_LOGS_TABLE]: createClearReducer(section, {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: [],
|
||||
totalPages: 0,
|
||||
totalRecords: 0
|
||||
})
|
||||
|
||||
}, defaultState, section);
|
||||
|
|
|
@ -33,11 +33,6 @@ export const defaultState = {
|
|||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
// {
|
||||
// name: 'episode',
|
||||
// label: 'Episode',
|
||||
// isVisible: true
|
||||
// },
|
||||
{
|
||||
name: 'albumTitle',
|
||||
label: 'Album Title',
|
||||
|
@ -112,11 +107,6 @@ export const defaultState = {
|
|||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
// {
|
||||
// name: 'episode',
|
||||
// label: 'Episode',
|
||||
// isVisible: true
|
||||
// },
|
||||
{
|
||||
name: 'albumTitle',
|
||||
label: 'Album Title',
|
||||
|
@ -310,7 +300,9 @@ export const reducers = createHandleActions({
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
items: [],
|
||||
totalPages: 0,
|
||||
totalRecords: 0
|
||||
}
|
||||
),
|
||||
|
||||
|
@ -320,7 +312,9 @@ export const reducers = createHandleActions({
|
|||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
items: [],
|
||||
totalPages: 0,
|
||||
totalRecords: 0
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import _ from 'lodash';
|
||||
import persistState from 'redux-localstorage';
|
||||
import actions from 'Store/Actions';
|
||||
import migrate from 'Store/Migrators/migrate';
|
||||
|
||||
const columnPaths = [];
|
||||
|
||||
|
@ -90,4 +91,11 @@ const config = {
|
|||
key: 'lidarr'
|
||||
};
|
||||
|
||||
export default persistState(paths, config);
|
||||
export default function createPersistState() {
|
||||
// Migrate existing local storage before proceeding
|
||||
const persistedState = JSON.parse(localStorage.getItem(config.key));
|
||||
migrate(persistedState);
|
||||
localStorage.setItem(config.key, serialize(persistedState));
|
||||
|
||||
return persistState(paths, config);
|
||||
}
|
|
@ -2,7 +2,7 @@ import { applyMiddleware, compose } from 'redux';
|
|||
import thunk from 'redux-thunk';
|
||||
import { routerMiddleware } from 'react-router-redux';
|
||||
import createSentryMiddleware from './createSentryMiddleware';
|
||||
import persistState from './persistState';
|
||||
import createPersistState from './createPersistState';
|
||||
|
||||
export default function(history) {
|
||||
const middlewares = [];
|
||||
|
@ -20,6 +20,6 @@ export default function(history) {
|
|||
|
||||
return composeEnhancers(
|
||||
applyMiddleware(...middlewares),
|
||||
persistState
|
||||
createPersistState()
|
||||
);
|
||||
}
|
||||
|
|
5
frontend/src/Store/Migrators/migrate.js
Normal file
5
frontend/src/Store/Migrators/migrate.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import migrateAddArtistDefaults from './migrateAddArtistDefaults';
|
||||
|
||||
export default function migrate(persistedState) {
|
||||
migrateAddArtistDefaults(persistedState);
|
||||
}
|
14
frontend/src/Store/Migrators/migrateAddArtistDefaults.js
Normal file
14
frontend/src/Store/Migrators/migrateAddArtistDefaults.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { get } from 'lodash';
|
||||
import monitorOptions from 'Utilities/Artist/monitorOptions';
|
||||
|
||||
export default function migrateAddArtistDefaults(persistedState) {
|
||||
const monitor = get(persistedState, 'addArtist.defaults.monitor');
|
||||
|
||||
if (!monitor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!monitorOptions.find((option) => option.key === monitor)) {
|
||||
persistedState.addArtist.defaults.monitor = monitorOptions[0].key;
|
||||
}
|
||||
}
|
|
@ -4,8 +4,8 @@ import createAllArtistSelector from './createAllArtistSelector';
|
|||
function createArtistCountSelector() {
|
||||
return createSelector(
|
||||
createAllArtistSelector(),
|
||||
(series) => {
|
||||
return series.length;
|
||||
(artists) => {
|
||||
return artists.length;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -52,7 +52,14 @@ function filter(items, state) {
|
|||
const predicate = filterTypePredicates[type];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
accepted = value.some((v) => predicate(item[key], v));
|
||||
if (
|
||||
type === filterTypes.NOT_CONTAINS ||
|
||||
type === filterTypes.NOT_EQUAL
|
||||
) {
|
||||
accepted = value.every((v) => predicate(item[key], v));
|
||||
} else {
|
||||
accepted = value.some((v) => predicate(item[key], v));
|
||||
}
|
||||
} else {
|
||||
accepted = predicate(item[key], value);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ function createProviderSettingsSelector(sectionName) {
|
|||
const settings = selectSettings(Object.assign({ name: '' }, item), section.pendingChanges, section.saveError);
|
||||
|
||||
const {
|
||||
isFetchingSchema: isFetching,
|
||||
isSchemaFetching: isFetching,
|
||||
isSchemaPopulated: isPopulated,
|
||||
schemaError: error,
|
||||
isSaving,
|
||||
|
|
|
@ -3,14 +3,18 @@ import { createSelector } from 'reselect';
|
|||
function createQueueItemSelector() {
|
||||
return createSelector(
|
||||
(state, { albumId }) => albumId,
|
||||
(state) => state.queue.details,
|
||||
(state) => state.queue.details.items,
|
||||
(albumId, details) => {
|
||||
if (!albumId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return details.items.find((item) => {
|
||||
return item.album.id === albumId;
|
||||
return details.find((item) => {
|
||||
if (item.album) {
|
||||
return item.album.id === albumId;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -6,7 +6,7 @@ function createTrackFileSelector() {
|
|||
(state) => state.trackFiles,
|
||||
(trackFileId, trackFiles) => {
|
||||
if (!trackFileId) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
return trackFiles.items.find((trackFile) => trackFile.id === trackFileId);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue