mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-18 21:35:27 -04:00
Use react-query for series import
This commit is contained in:
@@ -1,336 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import { createAction } from 'redux-actions';
|
||||
import { batchActions } from 'redux-batched-actions';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
import getNewSeries from 'Utilities/Series/getNewSeries';
|
||||
import * as seriesTypes from 'Utilities/Series/seriesTypes';
|
||||
import getSectionState from 'Utilities/State/getSectionState';
|
||||
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||
import { removeItem, set, updateItem } from './baseActions';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
||||
export const section = 'importSeries';
|
||||
let concurrentLookups = 0;
|
||||
let abortCurrentLookup = null;
|
||||
const queue = [];
|
||||
|
||||
//
|
||||
// State
|
||||
|
||||
export const defaultState = {
|
||||
isLookingUpSeries: false,
|
||||
isImporting: false,
|
||||
isImported: false,
|
||||
importError: null,
|
||||
items: []
|
||||
};
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
export const QUEUE_LOOKUP_SERIES = 'importSeries/queueLookupSeries';
|
||||
export const START_LOOKUP_SERIES = 'importSeries/startLookupSeries';
|
||||
export const CANCEL_LOOKUP_SERIES = 'importSeries/cancelLookupSeries';
|
||||
export const LOOKUP_UNSEARCHED_SERIES = 'importSeries/lookupUnsearchedSeries';
|
||||
export const CLEAR_IMPORT_SERIES = 'importSeries/clearImportSeries';
|
||||
export const SET_IMPORT_SERIES_VALUE = 'importSeries/setImportSeriesValue';
|
||||
export const IMPORT_SERIES = 'importSeries/importSeries';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
||||
export const queueLookupSeries = createThunk(QUEUE_LOOKUP_SERIES);
|
||||
export const startLookupSeries = createThunk(START_LOOKUP_SERIES);
|
||||
export const importSeries = createThunk(IMPORT_SERIES);
|
||||
export const lookupUnsearchedSeries = createThunk(LOOKUP_UNSEARCHED_SERIES);
|
||||
export const clearImportSeries = createAction(CLEAR_IMPORT_SERIES);
|
||||
export const cancelLookupSeries = createAction(CANCEL_LOOKUP_SERIES);
|
||||
|
||||
export const setImportSeriesValue = createAction(SET_IMPORT_SERIES_VALUE, (payload) => {
|
||||
return {
|
||||
section,
|
||||
...payload
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
export const actionHandlers = handleThunks({
|
||||
|
||||
[QUEUE_LOOKUP_SERIES]: function(getState, payload, dispatch) {
|
||||
const {
|
||||
name,
|
||||
path,
|
||||
relativePath,
|
||||
term,
|
||||
topOfQueue = false
|
||||
} = payload;
|
||||
|
||||
const state = getState().importSeries;
|
||||
const item = _.find(state.items, { id: name }) || {
|
||||
id: name,
|
||||
term,
|
||||
path,
|
||||
relativePath,
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null
|
||||
};
|
||||
|
||||
dispatch(updateItem({
|
||||
section,
|
||||
...item,
|
||||
term,
|
||||
isQueued: true,
|
||||
items: []
|
||||
}));
|
||||
|
||||
const itemIndex = queue.indexOf(item.id);
|
||||
|
||||
if (itemIndex >= 0) {
|
||||
queue.splice(itemIndex, 1);
|
||||
}
|
||||
|
||||
if (topOfQueue) {
|
||||
queue.unshift(item.id);
|
||||
} else {
|
||||
queue.push(item.id);
|
||||
}
|
||||
|
||||
if (term && term.length > 2) {
|
||||
dispatch(startLookupSeries({ start: true }));
|
||||
}
|
||||
},
|
||||
|
||||
[START_LOOKUP_SERIES]: function(getState, payload, dispatch) {
|
||||
if (concurrentLookups >= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const state = getState().importSeries;
|
||||
|
||||
const {
|
||||
isLookingUpSeries,
|
||||
items
|
||||
} = state;
|
||||
|
||||
const queueId = queue[0];
|
||||
|
||||
if (payload.start && !isLookingUpSeries) {
|
||||
dispatch(set({ section, isLookingUpSeries: true }));
|
||||
} else if (!isLookingUpSeries) {
|
||||
return;
|
||||
} else if (!queueId) {
|
||||
dispatch(set({ section, isLookingUpSeries: false }));
|
||||
return;
|
||||
}
|
||||
|
||||
concurrentLookups++;
|
||||
queue.splice(0, 1);
|
||||
|
||||
const queued = items.find((i) => i.id === queueId);
|
||||
|
||||
dispatch(updateItem({
|
||||
section,
|
||||
id: queued.id,
|
||||
isFetching: true
|
||||
}));
|
||||
|
||||
const { request, abortRequest } = createAjaxRequest({
|
||||
url: '/series/lookup',
|
||||
data: {
|
||||
term: queued.term
|
||||
}
|
||||
});
|
||||
|
||||
abortCurrentLookup = abortRequest;
|
||||
|
||||
request.done((data) => {
|
||||
const selectedSeries = queued.selectedSeries || data[0];
|
||||
|
||||
const itemProps = {
|
||||
section,
|
||||
id: queued.id,
|
||||
isFetching: false,
|
||||
isPopulated: true,
|
||||
error: null,
|
||||
items: data,
|
||||
isQueued: false,
|
||||
selectedSeries,
|
||||
updateOnly: true
|
||||
};
|
||||
|
||||
if (selectedSeries && selectedSeries.seriesType !== seriesTypes.STANDARD) {
|
||||
itemProps.seriesType = selectedSeries.seriesType;
|
||||
}
|
||||
|
||||
dispatch(updateItem(itemProps));
|
||||
});
|
||||
|
||||
request.fail((xhr) => {
|
||||
dispatch(updateItem({
|
||||
section,
|
||||
id: queued.id,
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: xhr,
|
||||
isQueued: false,
|
||||
updateOnly: true
|
||||
}));
|
||||
});
|
||||
|
||||
request.always(() => {
|
||||
concurrentLookups--;
|
||||
|
||||
dispatch(startLookupSeries());
|
||||
});
|
||||
},
|
||||
|
||||
[LOOKUP_UNSEARCHED_SERIES]: function(getState, payload, dispatch) {
|
||||
const state = getState().importSeries;
|
||||
|
||||
if (state.isLookingUpSeries) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.items.forEach((item) => {
|
||||
const id = item.id;
|
||||
|
||||
if (
|
||||
!item.isPopulated &&
|
||||
!queue.includes(id)
|
||||
) {
|
||||
queue.push(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
if (queue.length) {
|
||||
dispatch(startLookupSeries({ start: true }));
|
||||
}
|
||||
},
|
||||
|
||||
[IMPORT_SERIES]: function(getState, payload, dispatch) {
|
||||
dispatch(set({ section, isImporting: true }));
|
||||
|
||||
const ids = payload.ids;
|
||||
const items = getState().importSeries.items;
|
||||
const addedIds = [];
|
||||
|
||||
const allNewSeries = ids.reduce((acc, id) => {
|
||||
const item = items.find((i) => i.id === id);
|
||||
const selectedSeries = item.selectedSeries;
|
||||
|
||||
// Make sure we have a selected series and
|
||||
// the same series hasn't been added yet.
|
||||
if (selectedSeries && !acc.some((a) => a.tvdbId === selectedSeries.tvdbId)) {
|
||||
const newSeries = getNewSeries(_.cloneDeep(selectedSeries), item);
|
||||
newSeries.path = item.path;
|
||||
|
||||
addedIds.push(id);
|
||||
acc.push(newSeries);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const promise = createAjaxRequest({
|
||||
url: '/series/import',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(allNewSeries)
|
||||
}).request;
|
||||
|
||||
promise.done((data) => {
|
||||
dispatch(batchActions([
|
||||
set({
|
||||
section,
|
||||
isImporting: false,
|
||||
isImported: true,
|
||||
importError: null
|
||||
}),
|
||||
|
||||
...data.map((series) => updateItem({ section: 'series', ...series })),
|
||||
|
||||
...addedIds.map((id) => removeItem({ section, id }))
|
||||
]));
|
||||
});
|
||||
|
||||
promise.fail((xhr) => {
|
||||
dispatch(batchActions([
|
||||
set({
|
||||
section,
|
||||
isImporting: false,
|
||||
isImported: true,
|
||||
importError: xhr
|
||||
}),
|
||||
|
||||
...addedIds.map((id) => updateItem({
|
||||
section,
|
||||
id
|
||||
}))
|
||||
]));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Reducers
|
||||
|
||||
export const reducers = createHandleActions({
|
||||
|
||||
[CANCEL_LOOKUP_SERIES]: function(state) {
|
||||
queue.splice(0, queue.length);
|
||||
|
||||
const items = state.items.map((item) => {
|
||||
if (item.isQueued) {
|
||||
return {
|
||||
...item,
|
||||
isQueued: false
|
||||
};
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
isLookingUpSeries: false,
|
||||
items
|
||||
});
|
||||
},
|
||||
|
||||
[CLEAR_IMPORT_SERIES]: function(state) {
|
||||
if (abortCurrentLookup) {
|
||||
abortCurrentLookup();
|
||||
|
||||
abortCurrentLookup = null;
|
||||
}
|
||||
|
||||
queue.splice(0, queue.length);
|
||||
|
||||
return Object.assign({}, state, defaultState);
|
||||
},
|
||||
|
||||
[SET_IMPORT_SERIES_VALUE]: function(state, { payload }) {
|
||||
const newState = getSectionState(state, section);
|
||||
const items = newState.items;
|
||||
const index = items.findIndex((item) => item.id === payload.id);
|
||||
|
||||
newState.items = [...items];
|
||||
|
||||
if (index >= 0) {
|
||||
const item = items[index];
|
||||
|
||||
newState.items.splice(index, 1, { ...item, ...payload });
|
||||
} else {
|
||||
newState.items.push({ ...payload });
|
||||
}
|
||||
|
||||
return updateSectionState(state, section, newState);
|
||||
}
|
||||
|
||||
}, defaultState, section);
|
||||
@@ -1,9 +1,7 @@
|
||||
import * as captcha from './captchaActions';
|
||||
import * as importSeries from './importSeriesActions';
|
||||
import * as settings from './settingsActions';
|
||||
|
||||
export default [
|
||||
captcha,
|
||||
importSeries,
|
||||
settings
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user