mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-24 22:35:39 -04:00
242 lines
5.5 KiB
JavaScript
242 lines
5.5 KiB
JavaScript
import _ from 'lodash';
|
|
import $ from 'jquery';
|
|
import { createAction } from 'redux-actions';
|
|
import { batchActions } from 'redux-batched-actions';
|
|
import getSectionState from 'Utilities/State/getSectionState';
|
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
|
import getNewArtist from 'Utilities/Artist/getNewArtist';
|
|
import { createThunk, handleThunks } from 'Store/thunks';
|
|
import createHandleActions from './Creators/createHandleActions';
|
|
import { set, removeItem, updateItem } from './baseActions';
|
|
import { fetchRootFolders } from './rootFolderActions';
|
|
|
|
//
|
|
// Variables
|
|
|
|
export const section = 'importArtist';
|
|
let concurrentLookups = 0;
|
|
|
|
//
|
|
// State
|
|
|
|
export const defaultState = {
|
|
isFetching: false,
|
|
isPopulated: false,
|
|
error: null,
|
|
isImporting: false,
|
|
isImported: false,
|
|
importError: null,
|
|
items: []
|
|
};
|
|
|
|
//
|
|
// Actions Types
|
|
|
|
export const QUEUE_LOOKUP_ARTIST = 'importArtist/queueLookupArtist';
|
|
export const START_LOOKUP_ARTIST = 'importArtist/startLookupArtist';
|
|
export const CLEAR_IMPORT_ARTIST = 'importArtist/importArtist';
|
|
export const SET_IMPORT_ARTIST_VALUE = 'importArtist/clearImportArtist';
|
|
export const IMPORT_ARTIST = 'importArtist/setImportArtistValue';
|
|
|
|
//
|
|
// Action Creators
|
|
|
|
export const queueLookupArtist = createThunk(QUEUE_LOOKUP_ARTIST);
|
|
export const startLookupArtist = createThunk(START_LOOKUP_ARTIST);
|
|
export const importArtist = createThunk(IMPORT_ARTIST);
|
|
export const clearImportArtist = createAction(CLEAR_IMPORT_ARTIST);
|
|
|
|
export const setImportArtistValue = createAction(SET_IMPORT_ARTIST_VALUE, (payload) => {
|
|
return {
|
|
|
|
section,
|
|
...payload
|
|
};
|
|
});
|
|
|
|
//
|
|
// Action Handlers
|
|
|
|
export const actionHandlers = handleThunks({
|
|
|
|
[QUEUE_LOOKUP_ARTIST]: function(getState, payload, dispatch) {
|
|
const {
|
|
name,
|
|
path,
|
|
term
|
|
} = payload;
|
|
|
|
const state = getState().importArtist;
|
|
const item = _.find(state.items, { id: name }) || {
|
|
id: name,
|
|
term,
|
|
path,
|
|
isFetching: false,
|
|
isPopulated: false,
|
|
error: null
|
|
};
|
|
|
|
dispatch(updateItem({
|
|
section,
|
|
...item,
|
|
term,
|
|
queued: true,
|
|
items: []
|
|
}));
|
|
|
|
if (term && term.length > 2) {
|
|
dispatch(startLookupArtist());
|
|
}
|
|
},
|
|
|
|
[START_LOOKUP_ARTIST]: function(getState, payload, dispatch) {
|
|
if (concurrentLookups >= 1) {
|
|
return;
|
|
}
|
|
|
|
const state = getState().importArtist;
|
|
const queued = _.find(state.items, { queued: true });
|
|
|
|
if (!queued) {
|
|
return;
|
|
}
|
|
|
|
concurrentLookups++;
|
|
|
|
dispatch(updateItem({
|
|
section,
|
|
id: queued.id,
|
|
isFetching: true
|
|
}));
|
|
|
|
const promise = $.ajax({
|
|
url: '/artist/lookup',
|
|
data: {
|
|
term: queued.term
|
|
}
|
|
});
|
|
|
|
promise.done((data) => {
|
|
dispatch(updateItem({
|
|
section,
|
|
id: queued.id,
|
|
isFetching: false,
|
|
isPopulated: true,
|
|
error: null,
|
|
items: data,
|
|
queued: false,
|
|
selectedArtist: queued.selectedArtist || data[0]
|
|
}));
|
|
});
|
|
|
|
promise.fail((xhr) => {
|
|
dispatch(updateItem({
|
|
section,
|
|
id: queued.id,
|
|
isFetching: false,
|
|
isPopulated: false,
|
|
error: xhr,
|
|
queued: false
|
|
}));
|
|
});
|
|
|
|
promise.always(() => {
|
|
concurrentLookups--;
|
|
dispatch(startLookupArtist());
|
|
});
|
|
},
|
|
|
|
[IMPORT_ARTIST]: function(getState, payload, dispatch) {
|
|
dispatch(set({ section, isImporting: true }));
|
|
|
|
const ids = payload.ids;
|
|
const items = getState().importArtist.items;
|
|
const addedIds = [];
|
|
|
|
const allNewArtist = ids.reduce((acc, id) => {
|
|
const item = _.find(items, { id });
|
|
const selectedArtist = item.selectedArtist;
|
|
|
|
// Make sure we have a selected artist and
|
|
// the same artist hasn't been added yet.
|
|
if (selectedArtist && !_.some(acc, { tvdbId: selectedArtist.tvdbId })) {
|
|
const newArtist = getNewArtist(_.cloneDeep(selectedArtist), item);
|
|
newArtist.path = item.path;
|
|
|
|
addedIds.push(id);
|
|
acc.push(newArtist);
|
|
}
|
|
|
|
return acc;
|
|
}, []);
|
|
|
|
const promise = $.ajax({
|
|
url: '/artist/import',
|
|
method: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(allNewArtist)
|
|
});
|
|
|
|
promise.done((data) => {
|
|
dispatch(batchActions([
|
|
set({
|
|
section,
|
|
isImporting: false,
|
|
isImported: true
|
|
}),
|
|
|
|
...data.map((artist) => updateItem({ section: 'artist', ...artist })),
|
|
|
|
...addedIds.map((id) => removeItem({ section, id }))
|
|
]));
|
|
|
|
dispatch(fetchRootFolders());
|
|
});
|
|
|
|
promise.fail((xhr) => {
|
|
dispatch(batchActions(
|
|
set({
|
|
section,
|
|
isImporting: false,
|
|
isImported: true
|
|
}),
|
|
|
|
addedIds.map((id) => updateItem({
|
|
section,
|
|
id,
|
|
importError: xhr
|
|
}))
|
|
));
|
|
});
|
|
}
|
|
});
|
|
|
|
//
|
|
// Reducers
|
|
|
|
export const reducers = createHandleActions({
|
|
|
|
[CLEAR_IMPORT_ARTIST]: function(state) {
|
|
return Object.assign({}, state, defaultState);
|
|
},
|
|
|
|
[SET_IMPORT_ARTIST_VALUE]: function(state, { payload }) {
|
|
const newState = getSectionState(state, section);
|
|
const items = newState.items;
|
|
const index = _.findIndex(items, { 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);
|