diff --git a/frontend/src/Series/Index/SeriesIndex.js b/frontend/src/Series/Index/SeriesIndex.js index f8d50a37a..3dcfdcb43 100644 --- a/frontend/src/Series/Index/SeriesIndex.js +++ b/frontend/src/Series/Index/SeriesIndex.js @@ -22,7 +22,7 @@ import SeriesIndexOverviewsConnector from './Overview/SeriesIndexOverviewsConnec import SeriesIndexFilterMenu from './Menus/SeriesIndexFilterMenu'; import SeriesIndexSortMenu from './Menus/SeriesIndexSortMenu'; import SeriesIndexViewMenu from './Menus/SeriesIndexViewMenu'; -import SeriesIndexFooter from './SeriesIndexFooter'; +import SeriesIndexFooterConnector from './SeriesIndexFooterConnector'; import styles from './SeriesIndex.css'; function getViewComponent(view) { @@ -330,9 +330,7 @@ class SeriesIndex extends Component { {...otherProps} /> - + } diff --git a/frontend/src/Series/Index/SeriesIndexConnector.js b/frontend/src/Series/Index/SeriesIndexConnector.js index 89d99b245..d65f6a79c 100644 --- a/frontend/src/Series/Index/SeriesIndexConnector.js +++ b/frontend/src/Series/Index/SeriesIndexConnector.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; +import createSeriesClientSideCollectionItemsSelector from 'Store/Selectors/createSeriesClientSideCollectionItemsSelector'; import dimensions from 'Styles/Variables/dimensions'; import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; @@ -39,7 +39,7 @@ function getScrollTop(view, scrollTop, isSmallScreen) { function createMapStateToProps() { return createSelector( - createClientSideCollectionSelector('series', 'seriesIndex'), + createSeriesClientSideCollectionItemsSelector('seriesIndex'), createCommandExecutingSelector(commandNames.REFRESH_SERIES), createCommandExecutingSelector(commandNames.RSS_SYNC), createDimensionsSelector(), diff --git a/frontend/src/Series/Index/SeriesIndexFooterConnector.js b/frontend/src/Series/Index/SeriesIndexFooterConnector.js new file mode 100644 index 000000000..18b48210a --- /dev/null +++ b/frontend/src/Series/Index/SeriesIndexFooterConnector.js @@ -0,0 +1,16 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import SeriesIndexFooter from './SeriesIndexFooter'; + +function createMapStateToProps() { + return createSelector( + (state) => state.series.items, + (series) => { + return { + series + }; + } + ); +} + +export default connect(createMapStateToProps)(SeriesIndexFooter); diff --git a/frontend/src/Series/Index/SeriesIndexItemConnector.js b/frontend/src/Series/Index/SeriesIndexItemConnector.js index fa0b4ac47..8df30e205 100644 --- a/frontend/src/Series/Index/SeriesIndexItemConnector.js +++ b/frontend/src/Series/Index/SeriesIndexItemConnector.js @@ -5,8 +5,8 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import createSeriesSelector from 'Store/Selectors/createSeriesSelector'; import createExecutingCommandsSelector from 'Store/Selectors/createCommandsSelector'; -import createQualityProfileSelector from 'Store/Selectors/createQualityProfileSelector'; -import createLanguageProfileSelector from 'Store/Selectors/createLanguageProfileSelector'; +import createSeriesQualityProfileSelector from 'Store/Selectors/createSeriesQualityProfileSelector'; +import createSeriesLanguageProfileSelector from 'Store/Selectors/createSeriesLanguageProfileSelector'; import { executeCommand } from 'Store/Actions/commandActions'; import * as commandNames from 'Commands/commandNames'; @@ -31,8 +31,8 @@ function selectShowSearchAction() { function createMapStateToProps() { return createSelector( createSeriesSelector(), - createQualityProfileSelector(), - createLanguageProfileSelector(), + createSeriesQualityProfileSelector(), + createSeriesLanguageProfileSelector(), selectShowSearchAction(), createExecutingCommandsSelector(), ( @@ -82,7 +82,7 @@ function createMapStateToProps() { } const mapDispatchToProps = { - executeCommand + dispatchExecuteCommand: executeCommand }; class SeriesIndexItemConnector extends Component { @@ -91,14 +91,14 @@ class SeriesIndexItemConnector extends Component { // Listeners onRefreshSeriesPress = () => { - this.props.executeCommand({ + this.props.dispatchExecuteCommand({ name: commandNames.REFRESH_SERIES, seriesId: this.props.id }); } onSearchPress = () => { - this.props.executeCommand({ + this.props.dispatchExecuteCommand({ name: commandNames.SERIES_SEARCH, seriesId: this.props.id }); @@ -132,7 +132,7 @@ class SeriesIndexItemConnector extends Component { SeriesIndexItemConnector.propTypes = { id: PropTypes.number, component: PropTypes.func.isRequired, - executeCommand: PropTypes.func.isRequired + dispatchExecuteCommand: PropTypes.func.isRequired }; export default connect(createMapStateToProps, mapDispatchToProps)(SeriesIndexItemConnector); diff --git a/frontend/src/Store/Selectors/createDeepEqualSelector.js b/frontend/src/Store/Selectors/createDeepEqualSelector.js new file mode 100644 index 000000000..c01d23875 --- /dev/null +++ b/frontend/src/Store/Selectors/createDeepEqualSelector.js @@ -0,0 +1,9 @@ +import { createSelectorCreator, defaultMemoize } from 'reselect'; +import _ from 'lodash'; + +const createDeepEqualSelector = createSelectorCreator( + defaultMemoize, + _.isEqual +); + +export default createDeepEqualSelector; diff --git a/frontend/src/Store/Selectors/createLanguageProfileSelector.js b/frontend/src/Store/Selectors/createLanguageProfileSelector.js index 2ad04d506..c32f85ada 100644 --- a/frontend/src/Store/Selectors/createLanguageProfileSelector.js +++ b/frontend/src/Store/Selectors/createLanguageProfileSelector.js @@ -1,4 +1,3 @@ -import _ from 'lodash'; import { createSelector } from 'reselect'; function createLanguageProfileSelector() { @@ -6,7 +5,9 @@ function createLanguageProfileSelector() { (state, { languageProfileId }) => languageProfileId, (state) => state.settings.languageProfiles.items, (languageProfileId, languageProfiles) => { - return _.find(languageProfiles, { id: languageProfileId }); + return languageProfiles.find((profile) => { + return profile.id === languageProfileId; + }); } ); } diff --git a/frontend/src/Store/Selectors/createQualityProfileSelector.js b/frontend/src/Store/Selectors/createQualityProfileSelector.js index 9308d63ac..451aacfd4 100644 --- a/frontend/src/Store/Selectors/createQualityProfileSelector.js +++ b/frontend/src/Store/Selectors/createQualityProfileSelector.js @@ -1,4 +1,3 @@ -import _ from 'lodash'; import { createSelector } from 'reselect'; function createQualityProfileSelector() { @@ -6,7 +5,9 @@ function createQualityProfileSelector() { (state, { qualityProfileId }) => qualityProfileId, (state) => state.settings.qualityProfiles.items, (qualityProfileId, qualityProfiles) => { - return _.find(qualityProfiles, { id: qualityProfileId }); + return qualityProfiles.find((profile) => { + return profile.id === qualityProfileId; + }); } ); } diff --git a/frontend/src/Store/Selectors/createSeriesClientSideCollectionItemsSelector.js b/frontend/src/Store/Selectors/createSeriesClientSideCollectionItemsSelector.js new file mode 100644 index 000000000..aea511e5d --- /dev/null +++ b/frontend/src/Store/Selectors/createSeriesClientSideCollectionItemsSelector.js @@ -0,0 +1,36 @@ +import { createSelector } from 'reselect'; +import createDeepEqualSelector from './createDeepEqualSelector'; +import createClientSideCollectionSelector from './createClientSideCollectionSelector'; + +function createUnoptimizedSelector(uiSection) { + return createSelector( + createClientSideCollectionSelector('series', uiSection), + (series) => { + const items = series.items.map((s) => { + const { + id, + sortTitle + } = s; + + return { + id, + sortTitle + }; + }); + + return { + ...series, + items + }; + } + ); +} + +function createSeriesClientSideCollectionItemsSelector(uiSection) { + return createDeepEqualSelector( + createUnoptimizedSelector(uiSection), + (series) => series + ); +} + +export default createSeriesClientSideCollectionItemsSelector; diff --git a/frontend/src/Store/Selectors/createSeriesLanguageProfileSelector.js b/frontend/src/Store/Selectors/createSeriesLanguageProfileSelector.js new file mode 100644 index 000000000..0774b5178 --- /dev/null +++ b/frontend/src/Store/Selectors/createSeriesLanguageProfileSelector.js @@ -0,0 +1,16 @@ +import { createSelector } from 'reselect'; +import createSeriesSelector from './createSeriesSelector'; + +function createSeriesLanguageProfileSelector() { + return createSelector( + (state) => state.settings.languageProfiles.items, + createSeriesSelector(), + (languageProfiles, series) => { + return languageProfiles.find((profile) => { + return profile.id === series.languageProfileId; + }); + } + ); +} + +export default createSeriesLanguageProfileSelector; diff --git a/frontend/src/Store/Selectors/createSeriesQualityProfileSelector.js b/frontend/src/Store/Selectors/createSeriesQualityProfileSelector.js new file mode 100644 index 000000000..4a04e63a3 --- /dev/null +++ b/frontend/src/Store/Selectors/createSeriesQualityProfileSelector.js @@ -0,0 +1,16 @@ +import { createSelector } from 'reselect'; +import createSeriesSelector from './createSeriesSelector'; + +function createSeriesQualityProfileSelector() { + return createSelector( + (state) => state.settings.qualityProfiles.items, + createSeriesSelector(), + (qualityProfiles, series) => { + return qualityProfiles.find((profile) => { + return profile.id === series.qualityProfileId; + }); + } + ); +} + +export default createSeriesQualityProfileSelector;