New: Load all books on page load and store in the browser

pull/1205/head
ta264 3 years ago
parent 2558660b7b
commit 468ebc3307

@ -12,33 +12,11 @@ import TableBody from 'Components/Table/TableBody';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import TablePager from 'Components/Table/TablePager';
import { align, icons } from 'Helpers/Props';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import translate from 'Utilities/String/translate';
import HistoryRowConnector from './HistoryRowConnector';
class History extends Component {
//
// Lifecycle
shouldComponentUpdate(nextProps) {
// Don't update when fetching has completed if items have changed,
// before books start fetching or when books start fetching.
if (
(
this.props.isFetching &&
nextProps.isPopulated &&
hasDifferentItems(this.props.items, nextProps.items)
) ||
(!this.props.isBooksFetching && nextProps.isBooksFetching)
) {
return false;
}
return true;
}
//
// Render

@ -3,10 +3,7 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import withCurrentPage from 'Components/withCurrentPage';
import { clearBooks, fetchBooks } from 'Store/Actions/bookActions';
import * as historyActions from 'Store/Actions/historyActions';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
import History from './History';
@ -29,9 +26,7 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
...historyActions,
fetchBooks,
clearBooks
...historyActions
};
class HistoryConnector extends Component {
@ -55,21 +50,9 @@ class HistoryConnector extends Component {
}
}
componentDidUpdate(prevProps) {
if (hasDifferentItems(prevProps.items, this.props.items)) {
const bookIds = selectUniqueIds(this.props.items, 'bookId');
if (bookIds.length) {
this.props.fetchBooks({ bookIds });
} else {
this.props.clearBooks();
}
}
}
componentWillUnmount() {
unregisterPagePopulator(this.repopulate);
this.props.clearHistory();
this.props.clearBooks();
}
//
@ -150,9 +133,7 @@ HistoryConnector.propTypes = {
setHistorySort: PropTypes.func.isRequired,
setHistoryFilter: PropTypes.func.isRequired,
setHistoryTableOption: PropTypes.func.isRequired,
clearHistory: PropTypes.func.isRequired,
fetchBooks: PropTypes.func.isRequired,
clearBooks: PropTypes.func.isRequired
clearHistory: PropTypes.func.isRequired
};
export default withCurrentPage(

@ -4,12 +4,9 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import withCurrentPage from 'Components/withCurrentPage';
import { clearBooks, fetchBooks } from 'Store/Actions/bookActions';
import { executeCommand } from 'Store/Actions/commandActions';
import * as queueActions from 'Store/Actions/queueActions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
import Queue from './Queue';
@ -37,8 +34,6 @@ function createMapStateToProps() {
const mapDispatchToProps = {
...queueActions,
fetchBooks,
clearBooks,
executeCommand
};
@ -67,16 +62,6 @@ class QueueConnector extends Component {
}
componentDidUpdate(prevProps) {
if (hasDifferentItems(prevProps.items, this.props.items)) {
const bookIds = selectUniqueIds(this.props.items, 'bookId');
if (bookIds.length) {
this.props.fetchBooks({ bookIds });
} else {
this.props.clearBooks();
}
}
if (
this.props.includeUnknownAuthorItems !==
prevProps.includeUnknownAuthorItems
@ -87,8 +72,6 @@ class QueueConnector extends Component {
componentWillUnmount() {
unregisterPagePopulator(this.repopulate);
this.props.clearQueue();
this.props.clearBooks();
}
//
@ -185,8 +168,6 @@ QueueConnector.propTypes = {
clearQueue: PropTypes.func.isRequired,
grabQueueItems: PropTypes.func.isRequired,
removeQueueItems: PropTypes.func.isRequired,
fetchBooks: PropTypes.func.isRequired,
clearBooks: PropTypes.func.isRequired,
executeCommand: PropTypes.func.isRequired
};

@ -88,11 +88,13 @@ function AppRoutes(props) {
/>
<Route
path="/bookshelf"
exact={true}
path="/shelf"
component={BookshelfConnector}
/>
<Route
exact={true}
path="/books"
component={BookIndexConnector}
/>

@ -6,7 +6,6 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import { toggleAuthorMonitored } from 'Store/Actions/authorActions';
import { clearBooks, fetchBooks } from 'Store/Actions/bookActions';
import { clearBookFiles, fetchBookFiles } from 'Store/Actions/bookFileActions';
import { executeCommand } from 'Store/Actions/commandActions';
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
@ -186,8 +185,6 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
fetchBooks,
clearBooks,
fetchSeries,
clearSeries,
fetchBookFiles,
@ -248,7 +245,6 @@ class AuthorDetailsConnector extends Component {
populate = () => {
const authorId = this.props.id;
this.props.fetchBooks({ authorId });
this.props.fetchSeries({ authorId });
this.props.fetchBookFiles({ authorId });
this.props.fetchQueueDetails({ authorId });
@ -256,7 +252,6 @@ class AuthorDetailsConnector extends Component {
unpopulate = () => {
this.props.cancelFetchReleases();
this.props.clearBooks();
this.props.clearSeries();
this.props.clearBookFiles();
this.props.clearQueueDetails();
@ -310,8 +305,6 @@ AuthorDetailsConnector.propTypes = {
isRefreshing: PropTypes.bool.isRequired,
isRenamingFiles: PropTypes.bool.isRequired,
isRenamingAuthor: PropTypes.bool.isRequired,
fetchBooks: PropTypes.func.isRequired,
clearBooks: PropTypes.func.isRequired,
fetchSeries: PropTypes.func.isRequired,
clearSeries: PropTypes.func.isRequired,
fetchBookFiles: PropTypes.func.isRequired,

@ -4,24 +4,22 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setBooksSort, setBooksTableOption, toggleBooksMonitored } from 'Store/Actions/bookActions';
import { setAuthorDetailsId, setAuthorDetailsSort } from 'Store/Actions/authorDetailsActions';
import { setBooksTableOption, toggleBooksMonitored } from 'Store/Actions/bookActions';
import { executeCommand } from 'Store/Actions/commandActions';
import createAuthorSelector from 'Store/Selectors/createAuthorSelector';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import AuthorDetailsSeason from './AuthorDetailsSeason';
function createMapStateToProps() {
return createSelector(
(state, { label }) => label,
createClientSideCollectionSelector('books'),
createClientSideCollectionSelector('books', 'authorDetails'),
createAuthorSelector(),
createCommandsSelector(),
createDimensionsSelector(),
createUISettingsSelector(),
(label, books, author, commands, dimensions, uiSettings) => {
(books, author, dimensions, uiSettings) => {
const booksInGroup = books.items;
@ -47,14 +45,22 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
setAuthorDetailsId,
setAuthorDetailsSort,
toggleBooksMonitored,
setBooksTableOption,
dispatchSetBookSort: setBooksSort,
executeCommand
};
class AuthorDetailsSeasonConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.props.setAuthorDetailsId({ authorId: this.props.authorId });
}
//
// Listeners
@ -63,7 +69,7 @@ class AuthorDetailsSeasonConnector extends Component {
}
onSortPress = (sortKey) => {
this.props.dispatchSetBookSort({ sortKey });
this.props.setAuthorDetailsSort({ sortKey });
}
onMonitorBookPress = (bookIds, monitored) => {
@ -92,7 +98,8 @@ AuthorDetailsSeasonConnector.propTypes = {
authorId: PropTypes.number.isRequired,
toggleBooksMonitored: PropTypes.func.isRequired,
setBooksTableOption: PropTypes.func.isRequired,
dispatchSetBookSort: PropTypes.func.isRequired,
setAuthorDetailsId: PropTypes.func.isRequired,
setAuthorDetailsSort: PropTypes.func.isRequired,
executeCommand: PropTypes.func.isRequired
};

@ -48,10 +48,11 @@ function createMapStateToProps() {
createUISettingsSelector(),
createDimensionsSelector(),
(titleSlug, bookFiles, books, authors, commands, uiSettings, dimensions) => {
const sortedBooks = _.orderBy(books.items, 'releaseDate');
const bookIndex = _.findIndex(sortedBooks, { titleSlug });
const book = sortedBooks[bookIndex];
const author = _.find(authors, { id: book.authorId });
const book = books.items.find((b) => b.titleSlug === titleSlug);
const author = authors.find((a) => a.id === book.authorId);
const sortedBooks = books.items.filter((b) => b.authorId === book.authorId);
sortedBooks.sort((a, b) => ((a.releaseDate > b.releaseDate) ? 1 : -1));
const bookIndex = sortedBooks.findIndex((b) => b.id === book.id);
if (!book) {
return {};

@ -8,7 +8,6 @@ import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import NotFound from 'Components/NotFound';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
import { clearBooks, fetchBooks } from 'Store/Actions/bookActions';
import translate from 'Utilities/String/translate';
import BookDetailsConnector from './BookDetailsConnector';
@ -44,9 +43,7 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
push,
fetchBooks,
clearBooks
push
};
class BookDetailsPageConnector extends Component {
@ -62,24 +59,11 @@ class BookDetailsPageConnector extends Component {
this.populate();
}
componentWillUnmount() {
this.unpopulate();
}
//
// Control
populate = () => {
const titleSlug = this.props.titleSlug;
this.setState({ hasMounted: true });
this.props.fetchBooks({
titleSlug,
includeAllAuthorBooks: true
});
}
unpopulate = () => {
this.props.clearBooks();
}
//
@ -125,8 +109,6 @@ BookDetailsPageConnector.propTypes = {
titleSlug: PropTypes.string,
match: PropTypes.shape({ params: PropTypes.shape({ titleSlug: PropTypes.string.isRequired }).isRequired }).isRequired,
push: PropTypes.func.isRequired,
fetchBooks: PropTypes.func.isRequired,
clearBooks: PropTypes.func.isRequired,
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired
};

@ -5,7 +5,6 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import withScrollPosition from 'Components/withScrollPosition';
import { clearBooks, fetchBooks } from 'Store/Actions/bookActions';
import { setBookFilter, setBookSort, setBookTableOption, setBookView } from 'Store/Actions/bookIndexActions';
import { executeCommand } from 'Store/Actions/commandActions';
import scrollPositions from 'Store/scrollPositions';
@ -67,42 +66,12 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(executeCommand({
name: commandNames.RSS_SYNC
}));
},
dispatchFetchBooks() {
dispatch(fetchBooks());
},
dispatchClearBooks() {
dispatch(clearBooks());
}
};
}
class BookIndexConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.populate();
}
componentWillUnmount() {
this.unpopulate();
}
//
// Control
populate = () => {
this.props.dispatchFetchBooks();
}
unpopulate = () => {
this.props.dispatchClearBooks();
}
//
// Listeners
@ -131,8 +100,6 @@ class BookIndexConnector extends Component {
BookIndexConnector.propTypes = {
isSmallScreen: PropTypes.bool.isRequired,
view: PropTypes.string.isRequired,
dispatchFetchBooks: PropTypes.func.isRequired,
dispatchClearBooks: PropTypes.func.isRequired,
dispatchSetBookView: PropTypes.func.isRequired
};

@ -308,19 +308,6 @@ class Bookshelf extends Component {
this.cache.clearAll();
}
// onSectionRendered = ({ rowStartIndex }) => {
// console.log(`rendered starting ${rowStartIndex}, aiming for ${this.state.scrollIndex}`);
// const {
// scrollIndex
// } = this.state;
// if (rowStartIndex === scrollIndex) {
// console.log('resetting scrollindex');
// this.setState({ scrollIndex: null });
// }
// }
//
// Render
@ -385,7 +372,7 @@ class Bookshelf extends Component {
}
{
!error && isPopulated && !!items.length &&
!error && isPopulated && !!items.length && scroller &&
<div className={styles.contentBodyContainer}>
<VirtualTable
items={items}

@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearBooks, fetchBooks } from 'Store/Actions/bookActions';
import { saveBookshelf, setBookshelfFilter, setBookshelfSort } from 'Store/Actions/bookshelfActions';
import createAuthorClientSideCollectionItemsSelector from 'Store/Selectors/createAuthorClientSideCollectionItemsSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
@ -44,8 +43,6 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
fetchBooks,
clearBooks,
setBookshelfSort,
setBookshelfFilter,
saveBookshelf
@ -53,28 +50,6 @@ const mapDispatchToProps = {
class BookshelfConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.populate();
}
componentWillUnmount() {
this.unpopulate();
}
//
// Control
populate = () => {
this.props.fetchBooks();
}
unpopulate = () => {
this.props.clearBooks();
}
//
// Listeners
@ -108,8 +83,6 @@ class BookshelfConnector extends Component {
BookshelfConnector.propTypes = {
setBookshelfSort: PropTypes.func.isRequired,
setBookshelfFilter: PropTypes.func.isRequired,
fetchBooks: PropTypes.func.isRequired,
clearBooks: PropTypes.func.isRequired,
saveBookshelf: PropTypes.func.isRequired
};

@ -5,6 +5,7 @@ import { withRouter } from 'react-router-dom';
import { createSelector } from 'reselect';
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
import { fetchAuthor } from 'Store/Actions/authorActions';
import { fetchBooks } from 'Store/Actions/bookActions';
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
import { fetchImportLists, fetchLanguages, fetchMetadataProfiles, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
import { fetchStatus } from 'Store/Actions/systemActions';
@ -148,6 +149,9 @@ function createMapDispatchToProps(dispatch, props) {
dispatchFetchAuthor() {
dispatch(fetchAuthor());
},
dispatchFetchBooks() {
dispatch(fetchBooks());
},
dispatchFetchCustomFilters() {
dispatch(fetchCustomFilters());
},
@ -197,6 +201,7 @@ class PageConnector extends Component {
componentDidMount() {
if (!this.props.isPopulated) {
this.props.dispatchFetchAuthor();
this.props.dispatchFetchBooks();
this.props.dispatchFetchCustomFilters();
this.props.dispatchFetchTags();
this.props.dispatchFetchLanguages();
@ -223,6 +228,7 @@ class PageConnector extends Component {
isPopulated,
hasError,
dispatchFetchAuthor,
dispatchFetchBooks,
dispatchFetchTags,
dispatchFetchLanguages,
dispatchFetchQualityProfiles,
@ -262,6 +268,7 @@ PageConnector.propTypes = {
hasError: PropTypes.bool.isRequired,
isSidebarVisible: PropTypes.bool.isRequired,
dispatchFetchAuthor: PropTypes.func.isRequired,
dispatchFetchBooks: PropTypes.func.isRequired,
dispatchFetchCustomFilters: PropTypes.func.isRequired,
dispatchFetchTags: PropTypes.func.isRequired,
dispatchFetchLanguages: PropTypes.func.isRequired,

@ -42,7 +42,7 @@ const links = [
},
{
title: 'Bookshelf',
to: '/bookshelf'
to: '/shelf'
},
{
title: 'Unmapped Files',

@ -6,6 +6,7 @@ import { createSelector } from 'reselect';
import { setAppValue, setVersion } from 'Store/Actions/appActions';
import { fetchAuthor } from 'Store/Actions/authorActions';
import { removeItem, update, updateItem } from 'Store/Actions/baseActions';
import { deleteAuthorBooks } from 'Store/Actions/bookActions';
import { fetchCommands, finishCommand, updateCommand } from 'Store/Actions/commandActions';
import { fetchQueue, fetchQueueDetails } from 'Store/Actions/queueActions';
import { fetchRootFolders } from 'Store/Actions/settingsActions';
@ -45,6 +46,7 @@ const mapDispatchToProps = {
dispatchUpdate: update,
dispatchUpdateItem: updateItem,
dispatchRemoveItem: removeItem,
dispatchDeleteAuthorBooks: deleteAuthorBooks,
dispatchFetchAuthor: fetchAuthor,
dispatchFetchHealth: fetchHealth,
dispatchFetchQueue: fetchQueue,
@ -182,7 +184,6 @@ class SignalRConnector extends Component {
if (action === 'updated') {
this.props.dispatchUpdateItem({
section,
updateOnly: true,
...body.resource
});
} else if (action === 'deleted') {
@ -218,6 +219,7 @@ class SignalRConnector extends Component {
this.props.dispatchUpdateItem({ section, ...body.resource });
} else if (action === 'deleted') {
this.props.dispatchRemoveItem({ section, id: body.resource.id });
this.props.dispatchDeleteAuthorBooks({ authorId: body.resource.id });
}
}
@ -365,6 +367,7 @@ SignalRConnector.propTypes = {
dispatchUpdate: PropTypes.func.isRequired,
dispatchUpdateItem: PropTypes.func.isRequired,
dispatchRemoveItem: PropTypes.func.isRequired,
dispatchDeleteAuthorBooks: PropTypes.func.isRequired,
dispatchFetchAuthor: PropTypes.func.isRequired,
dispatchFetchHealth: PropTypes.func.isRequired,
dispatchFetchQueue: PropTypes.func.isRequired,

@ -0,0 +1,97 @@
import { createAction } from 'redux-actions';
import { sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import { set } from './baseActions';
import { filterPredicates, sortPredicates } from './bookActions';
import createHandleActions from './Creators/createHandleActions';
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
//
// Variables
export const section = 'authorDetails';
//
// State
export const defaultState = {
sortKey: 'releaseDate',
sortDirection: sortDirections.DESCENDING,
secondarySortKey: 'releaseDate',
secondarySortDirection: sortDirections.DESCENDING,
selectedFilterKey: 'authorId',
sortPredicates: {
...sortPredicates
},
filters: [
{
key: 'authorId',
label: 'Author',
filters: [
{
key: 'authorId',
value: 0
}
]
}
],
filterPredicates
};
export const persistState = [
'authorDetails.sortKey',
'authorDetails.sortDirection'
];
//
// Actions Types
export const SET_AUTHOR_DETAILS_SORT = 'authorIndex/setAuthorDetailsSort';
export const SET_AUTHOR_DETAILS_ID = 'authorIndex/setAuthorDetailsId';
//
// Action Creators
export const setAuthorDetailsSort = createAction(SET_AUTHOR_DETAILS_SORT);
export const setAuthorDetailsId = createThunk(SET_AUTHOR_DETAILS_ID);
//
// Action Handlers
export const actionHandlers = handleThunks({
[SET_AUTHOR_DETAILS_ID]: function(getState, payload, dispatch) {
const {
authorId
} = payload;
dispatch(set({
section,
filters: [
{
key: 'authorId',
label: 'Author',
filters: [
{
key: 'authorId',
value: authorId
}
]
}
]
}));
}
});
//
// Reducers
export const reducers = createHandleActions({
[SET_AUTHOR_DETAILS_SORT]: createSetClientSideCollectionSortReducer(section)
}, defaultState, section);

@ -6,7 +6,7 @@ import { filterTypePredicates, filterTypes, sortDirections } from 'Helpers/Props
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import dateFilterPredicate from 'Utilities/Date/dateFilterPredicate';
import { updateItem } from './baseActions';
import { removeItem, updateItem } from './baseActions';
import createFetchHandler from './Creators/createFetchHandler';
import createHandleActions from './Creators/createHandleActions';
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
@ -213,6 +213,7 @@ export const CLEAR_BOOKS = 'books/clearBooks';
export const SET_BOOK_VALUE = 'books/setBookValue';
export const SAVE_BOOK = 'books/saveBook';
export const DELETE_BOOK = 'books/deleteBook';
export const DELETE_AUTHOR_BOOKS = 'books/deleteAuthorBooks';
export const TOGGLE_BOOK_MONITORED = 'books/toggleBookMonitored';
export const TOGGLE_BOOKS_MONITORED = 'books/toggleBooksMonitored';
@ -238,6 +239,15 @@ export const deleteBook = createThunk(DELETE_BOOK, (payload) => {
};
});
export const deleteAuthorBooks = createThunk(DELETE_AUTHOR_BOOKS, (payload) => {
return {
...payload,
queryParams: {
authorId: payload.authorId
}
};
});
export const setBookValue = createAction(SET_BOOK_VALUE, (payload) => {
return {
section: 'books',
@ -253,6 +263,15 @@ export const actionHandlers = handleThunks({
[SAVE_BOOK]: createSaveProviderHandler(section, '/book'),
[DELETE_BOOK]: createRemoveItemHandler(section, '/book'),
[DELETE_AUTHOR_BOOKS]: function(getState, payload, dispatch) {
const { authorId } = payload;
const books = getState().books.items;
const toDelete = books.filter((x) => x.authorId === authorId);
dispatch(batchActions(toDelete.map((b) => removeItem({ section, id: b.id }))));
},
[TOGGLE_BOOK_MONITORED]: function(getState, payload, dispatch) {
const {
bookId,

@ -1,5 +1,6 @@
import * as app from './appActions';
import * as author from './authorActions';
import * as authorDetails from './authorDetailsActions';
import * as authorEditor from './authorEditorActions';
import * as authorHistory from './authorHistoryActions';
import * as authorIndex from './authorIndexActions';
@ -31,31 +32,32 @@ import * as wanted from './wantedActions';
export default [
app,
author,
authorDetails,
authorEditor,
authorHistory,
authorIndex,
blacklist,
captcha,
calendar,
commands,
customFilters,
books,
bookFiles,
bookHistory,
bookIndex,
books,
bookStudio,
calendar,
captcha,
commands,
customFilters,
history,
interactiveImportActions,
oAuth,
organizePreview,
retagPreview,
paths,
providerOptions,
queue,
releases,
bookStudio,
author,
authorEditor,
authorHistory,
authorIndex,
series,
retagPreview,
search,
series,
settings,
system,
tags,

@ -163,6 +163,7 @@ export const actionHandlers = handleThunks({
itemToAdd.book = data;
dispatch(batchActions([
updateItem({ section: 'authors', ...data.author }),
updateItem({ section: 'books', ...data }),
updateItem({ section, ...itemToAdd }),
set({

Loading…
Cancel
Save