New: Browse Lists from Discover Movies Page

pull/2/head
Qstick 4 years ago committed by GitHub
parent 54bcf9eed3
commit 361ffe353d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import { fetchNetImportExclusions } from 'Store/Actions/Settings/netImportExclusions';
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
import parseUrl from 'Utilities/String/parseUrl';
import AddNewMovie from './AddNewMovie';
@ -29,7 +29,7 @@ const mapDispatchToProps = {
lookupMovie,
clearAddMovie,
fetchRootFolders,
fetchNetImportExclusions
fetchImportExclusions
};
class AddNewMovieConnector extends Component {
@ -45,7 +45,7 @@ class AddNewMovieConnector extends Component {
componentDidMount() {
this.props.fetchRootFolders();
this.props.fetchNetImportExclusions();
this.props.fetchImportExclusions();
}
componentWillUnmount() {
@ -102,7 +102,7 @@ AddNewMovieConnector.propTypes = {
lookupMovie: PropTypes.func.isRequired,
clearAddMovie: PropTypes.func.isRequired,
fetchRootFolders: PropTypes.func.isRequired,
fetchNetImportExclusions: PropTypes.func.isRequired
fetchImportExclusions: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector);

@ -118,7 +118,7 @@ class AddNewMovieSearchResult extends Component {
className={styles.exclusionIcon}
name={icons.DANGER}
size={36}
title={translate('MovieIsOnNetImportExclusionList')}
title={translate('MovieIsOnImportExclusionList')}
/>
}
</div>

@ -15,10 +15,10 @@ import MovieIndexConnector from 'Movie/Index/MovieIndexConnector';
import CustomFormatSettingsConnector from 'Settings/CustomFormats/CustomFormatSettingsConnector';
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
import ImportListSettingsConnector from 'Settings/ImportLists/ImportListSettingsConnector';
import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector';
import MediaManagementConnector from 'Settings/MediaManagement/MediaManagementConnector';
import MetadataSettings from 'Settings/Metadata/MetadataSettings';
import NetImportSettingsConnector from 'Settings/NetImport/NetImportSettingsConnector';
import NotificationSettings from 'Settings/Notifications/NotificationSettings';
import Profiles from 'Settings/Profiles/Profiles';
import Quality from 'Settings/Quality/Quality';
@ -156,8 +156,8 @@ function AppRoutes(props) {
/>
<Route
path="/settings/netimports"
component={NetImportSettingsConnector}
path="/settings/importlists"
component={ImportListSettingsConnector}
/>
<Route

@ -16,3 +16,4 @@ export const RENAME_MOVIE = 'RenameMovie';
export const RESET_API_KEY = 'ResetApiKey';
export const RSS_SYNC = 'RssSync';
export const MOVIE_SEARCH = 'MoviesSearch';
export const IMPORT_LIST_SYNC = 'ImportListSync';

@ -6,6 +6,7 @@ import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Prop
import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
import ImportListFilterBuilderRowValueConnector from './ImportListFilterBuilderRowValueConnector';
import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector';
import MovieStatusFilterBuilderRowValue from './MovieStatusFilterBuilderRowValue';
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
@ -74,6 +75,9 @@ function getRowValueConnector(selectedFilterBuilderProp) {
case filterBuilderValueTypes.TAG:
return TagFilterBuilderRowValueConnector;
case filterBuilderValueTypes.IMPORTLIST:
return ImportListFilterBuilderRowValueConnector;
default:
return FilterBuilderRowValueConnector;
}

@ -0,0 +1,27 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createImportListSelector from 'Store/Selectors/createImportListSelector';
import FilterBuilderRowValue from './FilterBuilderRowValue';
function createMapStateToProps() {
return createSelector(
createImportListSelector(),
(importLists) => {
return {
tagList: importLists.map((importList) => {
const {
id,
name
} = importList;
return {
id,
name
};
})
};
}
);
}
export default connect(createMapStateToProps)(FilterBuilderRowValue);

@ -0,0 +1,3 @@
.lists {
flex: 1 0 auto;
}

@ -0,0 +1,43 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import { kinds, sizes } from 'Helpers/Props';
import Label from './Label';
import styles from './ImportListList.css';
function ImportListList({ lists, importListList }) {
return (
<div className={styles.lists}>
{
lists.map((t) => {
const list = _.find(importListList, { id: t });
if (!list) {
return null;
}
return (
<Label
key={list.id}
kind={kinds.INFO}
size={sizes.MEDIUM}
>
{list.name}
</Label>
);
})
}
</div>
);
}
ImportListList.propTypes = {
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
importListList: PropTypes.arrayOf(PropTypes.object).isRequired
};
ImportListList.defaultProps = {
lists: []
};
export default ImportListList;

@ -0,0 +1,17 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createImportListSelector from 'Store/Selectors/createImportListSelector';
import ImportListList from './ImportListList';
function createMapStateToProps() {
return createSelector(
createImportListSelector(),
(importListList) => {
return {
importListList
};
}
);
}
export default connect(createMapStateToProps)(ImportListList);

@ -6,7 +6,7 @@ import { createSelector } from 'reselect';
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
import { fetchMovies } from 'Store/Actions/movieActions';
import { fetchLanguages, fetchNetImports, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
import { fetchImportLists, fetchLanguages, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
import { fetchStatus } from 'Store/Actions/systemActions';
import { fetchTags } from 'Store/Actions/tagActions';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
@ -48,7 +48,7 @@ const selectIsPopulated = createSelector(
(state) => state.settings.ui.isPopulated,
(state) => state.settings.qualityProfiles.isPopulated,
(state) => state.settings.languages.isPopulated,
(state) => state.settings.netImports.isPopulated,
(state) => state.settings.importLists.isPopulated,
(state) => state.system.status.isPopulated,
(
customFiltersIsPopulated,
@ -56,7 +56,7 @@ const selectIsPopulated = createSelector(
uiSettingsIsPopulated,
qualityProfilesIsPopulated,
languagesIsPopulated,
netImportsIsPopulated,
importListsIsPopulated,
systemStatusIsPopulated
) => {
return (
@ -65,7 +65,7 @@ const selectIsPopulated = createSelector(
uiSettingsIsPopulated &&
qualityProfilesIsPopulated &&
languagesIsPopulated &&
netImportsIsPopulated &&
importListsIsPopulated &&
systemStatusIsPopulated
);
}
@ -77,7 +77,7 @@ const selectErrors = createSelector(
(state) => state.settings.ui.error,
(state) => state.settings.qualityProfiles.error,
(state) => state.settings.languages.error,
(state) => state.settings.netImports.error,
(state) => state.settings.importLists.error,
(state) => state.system.status.error,
(
customFiltersError,
@ -85,7 +85,7 @@ const selectErrors = createSelector(
uiSettingsError,
qualityProfilesError,
languagesError,
netImportsError,
importListsError,
systemStatusError
) => {
const hasError = !!(
@ -94,7 +94,7 @@ const selectErrors = createSelector(
uiSettingsError ||
qualityProfilesError ||
languagesError ||
netImportsError ||
importListsError ||
systemStatusError
);
@ -105,7 +105,7 @@ const selectErrors = createSelector(
uiSettingsError,
qualityProfilesError,
languagesError,
netImportsError,
importListsError,
systemStatusError
};
}
@ -153,8 +153,8 @@ function createMapDispatchToProps(dispatch, props) {
dispatchFetchLanguages() {
dispatch(fetchLanguages());
},
dispatchFetchNetImports() {
dispatch(fetchNetImports());
dispatchFetchImportLists() {
dispatch(fetchImportLists());
},
dispatchFetchUISettings() {
dispatch(fetchUISettings());
@ -191,7 +191,7 @@ class PageConnector extends Component {
this.props.dispatchFetchTags();
this.props.dispatchFetchQualityProfiles();
this.props.dispatchFetchLanguages();
this.props.dispatchFetchNetImports();
this.props.dispatchFetchImportLists();
this.props.dispatchFetchUISettings();
this.props.dispatchFetchStatus();
}
@ -215,7 +215,7 @@ class PageConnector extends Component {
dispatchFetchTags,
dispatchFetchQualityProfiles,
dispatchFetchLanguages,
dispatchFetchNetImports,
dispatchFetchImportLists,
dispatchFetchUISettings,
dispatchFetchStatus,
...otherProps
@ -254,7 +254,7 @@ PageConnector.propTypes = {
dispatchFetchTags: PropTypes.func.isRequired,
dispatchFetchQualityProfiles: PropTypes.func.isRequired,
dispatchFetchLanguages: PropTypes.func.isRequired,
dispatchFetchNetImports: PropTypes.func.isRequired,
dispatchFetchImportLists: PropTypes.func.isRequired,
dispatchFetchUISettings: PropTypes.func.isRequired,
dispatchFetchStatus: PropTypes.func.isRequired,
onSidebarVisibleChange: PropTypes.func.isRequired

@ -98,7 +98,7 @@ const links = [
},
{
title: translate('Lists'),
to: '/settings/netimports'
to: '/settings/importlists'
},
{
title: translate('Connect'),

@ -18,26 +18,27 @@ import getSelectedIds from 'Utilities/Table/getSelectedIds';
import selectAll from 'Utilities/Table/selectAll';
import toggleSelected from 'Utilities/Table/toggleSelected';
import DiscoverMovieFooterConnector from './DiscoverMovieFooterConnector';
import AddListMovieFilterMenu from './Menus/AddListMovieFilterMenu';
import AddListMovieSortMenu from './Menus/AddListMovieSortMenu';
import AddListMovieViewMenu from './Menus/AddListMovieViewMenu';
import DiscoverMovieFilterMenu from './Menus/DiscoverMovieFilterMenu';
import DiscoverMovieSortMenu from './Menus/DiscoverMovieSortMenu';
import DiscoverMovieViewMenu from './Menus/DiscoverMovieViewMenu';
import NoDiscoverMovie from './NoDiscoverMovie';
import AddListMovieOverviewsConnector from './Overview/AddListMovieOverviewsConnector';
import AddListMovieOverviewOptionsModal from './Overview/Options/AddListMovieOverviewOptionsModal';
import AddListMoviePostersConnector from './Posters/AddListMoviePostersConnector';
import AddListMoviePosterOptionsModal from './Posters/Options/AddListMoviePosterOptionsModal';
import AddListMovieTableConnector from './Table/AddListMovieTableConnector';
import DiscoverMovieOverviewsConnector from './Overview/DiscoverMovieOverviewsConnector';
import DiscoverMovieOverviewOptionsModal from './Overview/Options/DiscoverMovieOverviewOptionsModal';
import DiscoverMoviePostersConnector from './Posters/DiscoverMoviePostersConnector';
import DiscoverMoviePosterOptionsModal from './Posters/Options/DiscoverMoviePosterOptionsModal';
import DiscoverMovieTableConnector from './Table/DiscoverMovieTableConnector';
import DiscoverMovieTableOptionsConnector from './Table/DiscoverMovieTableOptionsConnector';
function getViewComponent(view) {
if (view === 'posters') {
return AddListMoviePostersConnector;
return DiscoverMoviePostersConnector;
}
if (view === 'overview') {
return AddListMovieOverviewsConnector;
return DiscoverMovieOverviewsConnector;
}
return AddListMovieTableConnector;
return DiscoverMovieTableConnector;
}
class DiscoverMovie extends Component {
@ -212,6 +213,10 @@ class DiscoverMovie extends Component {
this.onSelectAllChange({ value: !this.state.allSelected });
}
onImportListSyncPress = () => {
this.props.onImportListSyncPress();
}
onSelectedChange = ({ id, value, shiftKey = false }) => {
this.setState((state) => {
return toggleSelected(state, this.props.items, id, value, shiftKey, 'tmdbId');
@ -248,6 +253,7 @@ class DiscoverMovie extends Component {
onViewSelect,
onScroll,
onAddMoviesPress,
isSyncingLists,
...otherProps
} = this.props;
@ -272,6 +278,13 @@ class DiscoverMovie extends Component {
<PageContent>
<PageToolbar>
<PageToolbarSection>
<PageToolbarButton
label='Refresh Lists'
iconName={icons.REFRESH}
isSpinning={isSyncingLists}
isDisabled={hasNoMovie}
onPress={this.onImportListSyncPress}
/>
<PageToolbarButton
label={allSelected ? 'Unselect All' : 'Select All'}
iconName={icons.CHECK_SQUARE}
@ -289,6 +302,7 @@ class DiscoverMovie extends Component {
<TableOptionsModalWrapper
{...otherProps}
columns={columns}
optionsComponent={DiscoverMovieTableOptionsConnector}
>
<PageToolbarButton
label={translate('Options')}
@ -325,20 +339,20 @@ class DiscoverMovie extends Component {
<PageToolbarSeparator />
}
<AddListMovieViewMenu
<DiscoverMovieViewMenu
view={view}
isDisabled={hasNoMovie}
onViewSelect={onViewSelect}
/>
<AddListMovieSortMenu
<DiscoverMovieSortMenu
sortKey={sortKey}
sortDirection={sortDirection}
isDisabled={hasNoMovie}
onSortSelect={onSortSelect}
/>
<AddListMovieFilterMenu
<DiscoverMovieFilterMenu
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
@ -409,12 +423,12 @@ class DiscoverMovie extends Component {
/>
}
<AddListMoviePosterOptionsModal
<DiscoverMoviePosterOptionsModal
isOpen={isPosterOptionsModalOpen}
onModalClose={this.onPosterOptionsModalClose}
/>
<AddListMovieOverviewOptionsModal
<DiscoverMovieOverviewOptionsModal
isOpen={isOverviewOptionsModalOpen}
onModalClose={this.onOverviewOptionsModalClose}
/>
@ -436,13 +450,15 @@ DiscoverMovie.propTypes = {
sortKey: PropTypes.string,
sortDirection: PropTypes.oneOf(sortDirections.all),
view: PropTypes.string.isRequired,
isSyncingLists: PropTypes.bool.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
onSortSelect: PropTypes.func.isRequired,
onFilterSelect: PropTypes.func.isRequired,
onViewSelect: PropTypes.func.isRequired,
onScroll: PropTypes.func.isRequired,
onAddMoviesPress: PropTypes.func.isRequired,
onExcludeMoviesPress: PropTypes.func.isRequired
onExcludeMoviesPress: PropTypes.func.isRequired,
onImportListSyncPress: PropTypes.func.isRequired
};
export default DiscoverMovie;

@ -2,11 +2,14 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import withScrollPosition from 'Components/withScrollPosition';
import { addMovies, addNetImportExclusions, clearAddMovie, fetchDiscoverMovies, setListMovieFilter, setListMovieSort, setListMovieTableOption, setListMovieView } from 'Store/Actions/discoverMovieActions';
import { executeCommand } from 'Store/Actions/commandActions';
import { addImportExclusions, addMovies, clearAddMovie, fetchDiscoverMovies, setListMovieFilter, setListMovieSort, setListMovieTableOption, setListMovieView } from 'Store/Actions/discoverMovieActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import { fetchNetImportExclusions } from 'Store/Actions/Settings/netImportExclusions';
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
import scrollPositions from 'Store/scrollPositions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createDiscoverMovieClientSideCollectionItemsSelector from 'Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector';
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
@ -15,13 +18,16 @@ import DiscoverMovie from './DiscoverMovie';
function createMapStateToProps() {
return createSelector(
createDiscoverMovieClientSideCollectionItemsSelector('discoverMovie'),
createCommandExecutingSelector(commandNames.IMPORT_LIST_SYNC),
createDimensionsSelector(),
(
movies,
isSyncingLists,
dimensionsState
) => {
return {
...movies,
isSyncingLists,
isSmallScreen: dimensionsState.isSmallScreen
};
}
@ -34,8 +40,8 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(fetchRootFolders());
},
dispatchFetchNetImportExclusions() {
dispatch(fetchNetImportExclusions());
dispatchFetchImportExclusions() {
dispatch(fetchImportExclusions());
},
dispatchClearListMovie() {
@ -66,8 +72,14 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(addMovies({ ids, addOptions }));
},
dispatchAddNetImportExclusions(exclusions) {
dispatch(addNetImportExclusions(exclusions));
dispatchAddImportExclusions(exclusions) {
dispatch(addImportExclusions(exclusions));
},
onImportListSyncPress() {
dispatch(executeCommand({
name: commandNames.IMPORT_LIST_SYNC
}));
}
};
}
@ -80,7 +92,7 @@ class DiscoverMovieConnector extends Component {
componentDidMount() {
registerPagePopulator(this.repopulate);
this.props.dispatchFetchRootFolders();
this.props.dispatchFetchNetImportExclusions();
this.props.dispatchFetchImportExclusions();
this.props.dispatchFetchListMovies();
}
@ -105,7 +117,7 @@ class DiscoverMovieConnector extends Component {
}
onExcludeMoviesPress =({ ids }) => {
this.props.dispatchAddNetImportExclusions({ ids });
this.props.dispatchAddImportExclusions({ ids });
}
//
@ -119,6 +131,7 @@ class DiscoverMovieConnector extends Component {
onScroll={this.onScroll}
onAddMoviesPress={this.onAddMoviesPress}
onExcludeMoviesPress={this.onExcludeMoviesPress}
onSyncListsPress={this.onSyncListsPress}
/>
);
}
@ -127,13 +140,13 @@ class DiscoverMovieConnector extends Component {
DiscoverMovieConnector.propTypes = {
isSmallScreen: PropTypes.bool.isRequired,
view: PropTypes.string.isRequired,
dispatchFetchNetImportExclusions: PropTypes.func.isRequired,
dispatchFetchImportExclusions: PropTypes.func.isRequired,
dispatchFetchRootFolders: PropTypes.func.isRequired,
dispatchFetchListMovies: PropTypes.func.isRequired,
dispatchClearListMovie: PropTypes.func.isRequired,
dispatchSetListMovieView: PropTypes.func.isRequired,
dispatchAddMovies: PropTypes.func.isRequired,
dispatchAddNetImportExclusions: PropTypes.func.isRequired
dispatchAddImportExclusions: PropTypes.func.isRequired
};
export default withScrollPosition(

@ -29,7 +29,7 @@
.excludeSelectedButton {
composes: button from '~Components/Link/SpinnerButton.css';
margin-left: 50px;
margin-left: 25px;
height: 35px;
}

@ -8,9 +8,9 @@ import DiscoverMovieFooter from './DiscoverMovieFooter';
function createMapStateToProps() {
return createSelector(
(state) => state.discoverMovie,
(state) => state.settings.netImportExclusions,
(state) => state.settings.importExclusions,
(state, { selectedIds }) => selectedIds,
(discoverMovie, netImportExclusions, selectedIds) => {
(discoverMovie, importExclusions, selectedIds) => {
const {
monitor: defaultMonitor,
qualityProfileId: defaultQualityProfileId,
@ -25,7 +25,7 @@ function createMapStateToProps() {
const {
isSaving
} = netImportExclusions;
} = importExclusions;
return {
selectedCount: selectedIds.length,

@ -27,7 +27,7 @@ function createMapStateToProps() {
);
}
class AddListMovieItemConnector extends Component {
class DiscoverMovieItemConnector extends Component {
//
// Render
@ -52,9 +52,9 @@ class AddListMovieItemConnector extends Component {
}
}
AddListMovieItemConnector.propTypes = {
DiscoverMovieItemConnector.propTypes = {
tmdbId: PropTypes.number,
component: PropTypes.elementType.isRequired
};
export default connect(createMapStateToProps)(AddListMovieItemConnector);
export default connect(createMapStateToProps)(DiscoverMovieItemConnector);

@ -1,11 +1,11 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { addNetImportExclusions } from 'Store/Actions/discoverMovieActions';
import { addImportExclusions } from 'Store/Actions/discoverMovieActions';
import ExcludeMovieModalContent from './ExcludeMovieModalContent';
const mapDispatchToProps = {
addNetImportExclusions
addImportExclusions
};
class ExcludeMovieModalContentConnector extends Component {
@ -14,7 +14,7 @@ class ExcludeMovieModalContentConnector extends Component {
// Listeners
onExcludePress = () => {
this.props.addNetImportExclusions({ ids: [this.props.tmdbId] });
this.props.addImportExclusions({ ids: [this.props.tmdbId] });
this.props.onModalClose(true);
}
@ -37,7 +37,7 @@ ExcludeMovieModalContentConnector.propTypes = {
title: PropTypes.string.isRequired,
year: PropTypes.number.isRequired,
onModalClose: PropTypes.func.isRequired,
addNetImportExclusions: PropTypes.func.isRequired
addImportExclusions: PropTypes.func.isRequired
};
export default connect(undefined, mapDispatchToProps)(ExcludeMovieModalContentConnector);

@ -1,10 +1,10 @@
import PropTypes from 'prop-types';
import React from 'react';
import FilterMenu from 'Components/Menu/FilterMenu';
import AddListMovieFilterModalConnector from 'DiscoverMovie/AddListMovieFilterModalConnector';
import DiscoverMovieFilterModalConnector from 'DiscoverMovie/DiscoverMovieFilterModalConnector';
import { align } from 'Helpers/Props';
function AddListMovieFilterMenu(props) {
function DiscoverMovieFilterMenu(props) {
const {
selectedFilterKey,
filters,
@ -20,13 +20,13 @@ function AddListMovieFilterMenu(props) {
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
filterModalConnectorComponent={AddListMovieFilterModalConnector}
filterModalConnectorComponent={DiscoverMovieFilterModalConnector}
onFilterSelect={onFilterSelect}
/>
);
}
AddListMovieFilterMenu.propTypes = {
DiscoverMovieFilterMenu.propTypes = {
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
@ -34,8 +34,8 @@ AddListMovieFilterMenu.propTypes = {
onFilterSelect: PropTypes.func.isRequired
};
AddListMovieFilterMenu.defaultProps = {
DiscoverMovieFilterMenu.defaultProps = {
showCustomFilters: false
};
export default AddListMovieFilterMenu;
export default DiscoverMovieFilterMenu;

@ -5,7 +5,7 @@ import SortMenu from 'Components/Menu/SortMenu';
import SortMenuItem from 'Components/Menu/SortMenuItem';
import { align, sortDirections } from 'Helpers/Props';
function AddListMovieSortMenu(props) {
function DiscoverMovieSortMenu(props) {
const {
sortKey,
sortDirection,
@ -64,6 +64,24 @@ function AddListMovieSortMenu(props) {
Physical Release
</SortMenuItem>
<SortMenuItem
name="digitalRelease"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
Digital Release
</SortMenuItem>
<SortMenuItem
name="runtime"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
Runtime
</SortMenuItem>
<SortMenuItem
name="ratings"
sortKey={sortKey}
@ -86,11 +104,11 @@ function AddListMovieSortMenu(props) {
);
}
AddListMovieSortMenu.propTypes = {
DiscoverMovieSortMenu.propTypes = {
sortKey: PropTypes.string,
sortDirection: PropTypes.oneOf(sortDirections.all),
isDisabled: PropTypes.bool.isRequired,
onSortSelect: PropTypes.func.isRequired
};
export default AddListMovieSortMenu;
export default DiscoverMovieSortMenu;

@ -5,7 +5,7 @@ import ViewMenu from 'Components/Menu/ViewMenu';
import ViewMenuItem from 'Components/Menu/ViewMenuItem';
import { align } from 'Helpers/Props';
function AddListMovieViewMenu(props) {
function DiscoverMovieViewMenu(props) {
const {
view,
isDisabled,
@ -46,10 +46,10 @@ function AddListMovieViewMenu(props) {
);
}
AddListMovieViewMenu.propTypes = {
DiscoverMovieViewMenu.propTypes = {
view: PropTypes.string.isRequired,
isDisabled: PropTypes.bool.isRequired,
onViewSelect: PropTypes.func.isRequired
};
export default AddListMovieViewMenu;
export default DiscoverMovieViewMenu;

@ -44,7 +44,7 @@ function NoDiscoverMovie(props) {
<div className={styles.buttonContainer}>
<Button
to="/settings/netimports"
to="/settings/importlists"
kind={kinds.PRIMARY}
>
{translate('AddList')}

@ -32,6 +32,12 @@ $hoverScale: 1.05;
}
}
.alreadyExistsIcon {
margin-left: 10px;
color: #37bc9b;
pointer-events: all;
}
.exclusionIcon {
margin-left: 10px;
color: $dangerColor;
@ -50,10 +56,15 @@ $hoverScale: 1.05;
display: flex;
justify-content: space-between;
flex: 0 0 auto;
margin-bottom: 10px;
margin-bottom: 5px;
line-height: 32px;
}
.lists {
display: flex;
margin-bottom: 5px;
}
.title {
@add-mixin truncate;
composes: link;
@ -61,6 +72,7 @@ $hoverScale: 1.05;
flex: 1 0 1px;
font-weight: 300;
font-size: 30px;
line-height: 1;
}
.actions {

@ -3,27 +3,30 @@ import React, { Component } from 'react';
import TextTruncate from 'react-text-truncate';
import CheckInput from 'Components/Form/CheckInput';
import Icon from 'Components/Icon';
import ImportListListConnector from 'Components/ImportListListConnector';
import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import Popover from 'Components/Tooltip/Popover';
import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
import { icons } from 'Helpers/Props';
import { icons, kinds } from 'Helpers/Props';
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
import MoviePoster from 'Movie/MoviePoster';
import dimensions from 'Styles/Variables/dimensions';
import fonts from 'Styles/Variables/fonts';
import translate from 'Utilities/String/translate';
import styles from './AddListMovieOverview.css';
import DiscoverMovieOverviewInfo from './DiscoverMovieOverviewInfo';
import styles from './DiscoverMovieOverview.css';
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen);
const defaultFontSize = parseInt(fonts.defaultFontSize);
const lineHeight = parseFloat(fonts.lineHeight);
// Hardcoded height beased on line-height of 32 + bottom margin of 10.
// Hardcoded height beased on line-height of 32 + bottom margin of 10. 19 + 5 for List Row
// Less side-effecty than using react-measure.
const titleRowHeight = 42;
const titleRowHeight = 66;
function getContentHeight(rowHeight, isSmallScreen) {
const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding;
@ -31,7 +34,7 @@ function getContentHeight(rowHeight, isSmallScreen) {
return rowHeight - padding;
}
class AddListMovieOverview extends Component {
class DiscoverMovieOverview extends Component {
//
// Lifecycle
@ -82,18 +85,21 @@ class AddListMovieOverview extends Component {
imdbId,
youTubeTrailerId,
title,
titleSlug,
folder,
year,
overview,
images,
lists,
posterWidth,
posterHeight,
rowHeight,
isSmallScreen,
isExisting,
isExcluded,
isSelected
isRecommendation,
isSelected,
overviewOptions,
...otherProps
} = this.props;
const {
@ -106,7 +112,7 @@ class AddListMovieOverview extends Component {
height: `${posterHeight}px`
};
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onPress };
const contentHeight = getContentHeight(rowHeight, isSmallScreen);
const overviewHeight = contentHeight - titleRowHeight;
@ -142,15 +148,24 @@ class AddListMovieOverview extends Component {
className={styles.title}
{...linkProps}
>
{title} { year > 0 ? `(${year})` : ''}
{title}
{
isExisting ?
<Icon
className={styles.alreadyExistsIcon}
name={icons.CHECK_CIRCLE}
size={30}
title={'Already in your Library'}
/> : null
}
{
isExcluded &&
<Icon
className={styles.exclusionIcon}
name={icons.DANGER}
size={36}
title='Movie is on Net Import Exclusion List'
size={30}
title='Movie is on Import Exclusion List'
/>
}
</Link>
@ -184,12 +199,38 @@ class AddListMovieOverview extends Component {
</div>
</div>
<div className={styles.lists}>
{
isRecommendation ?
<Label
kind={kinds.INFO}
>
<Icon
name={icons.RECOMMENDED}
size={10}
/>
</Label> :
null
}
<ImportListListConnector
lists={lists}
/>
</div>
<div className={styles.details}>
<TextTruncate
line={Math.floor(overviewHeight / (defaultFontSize * lineHeight))}
text={overview}
/>
<DiscoverMovieOverviewInfo
height={overviewHeight}
year={year}
{...overviewOptions}
{...otherProps}
/>
</div>
</div>
</div>
@ -217,7 +258,7 @@ class AddListMovieOverview extends Component {
}
}
AddListMovieOverview.propTypes = {
DiscoverMovieOverview.propTypes = {
tmdbId: PropTypes.number.isRequired,
imdbId: PropTypes.string,
youTubeTrailerId: PropTypes.string,
@ -226,7 +267,6 @@ AddListMovieOverview.propTypes = {
year: PropTypes.number.isRequired,
overview: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
titleSlug: PropTypes.string.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired,
@ -239,8 +279,14 @@ AddListMovieOverview.propTypes = {
isSmallScreen: PropTypes.bool.isRequired,
isExisting: PropTypes.bool.isRequired,
isExcluded: PropTypes.bool.isRequired,
isRecommendation: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
onSelectedChange: PropTypes.func.isRequired
};
export default AddListMovieOverview;
DiscoverMovieOverview.defaultProps = {
lists: []
};
export default DiscoverMovieOverview;

@ -1,7 +1,7 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import AddListMovieOverview from './AddListMovieOverview';
import DiscoverMovieOverview from './DiscoverMovieOverview';
function createMapStateToProps() {
return createSelector(
@ -14,4 +14,4 @@ function createMapStateToProps() {
);
}
export default connect(createMapStateToProps)(AddListMovieOverview);
export default connect(createMapStateToProps)(DiscoverMovieOverview);

@ -0,0 +1,12 @@
.infos {
display: flex;
flex: 0 0 250px;
flex-direction: column;
margin-left: 10px;
}
@media only screen and (max-width: $breakpointSmall) {
.infos {
margin-left: 0;
}
}

@ -0,0 +1,147 @@
import PropTypes from 'prop-types';
import React from 'react';
import { icons } from 'Helpers/Props';
import dimensions from 'Styles/Variables/dimensions';
import DiscoverMovieOverviewInfoRow from './DiscoverMovieOverviewInfoRow';
import styles from './DiscoverMovieOverviewInfo.css';
const infoRowHeight = parseInt(dimensions.movieIndexOverviewInfoRowHeight);
const rows = [
{
name: 'year',
showProp: 'showYear',
valueProp: 'year'
},
{
name: 'genres',
showProp: 'showGenres',
valueProp: 'genres'
},
{
name: 'ratings',
showProp: 'showRatings',
valueProp: 'ratings'
},
{
name: 'certification',
showProp: 'showCertification',
valueProp: 'certification'
},
{
name: 'studio',
showProp: 'showStudio',
valueProp: 'studio'
}
];
function isVisible(row, props) {
const {
name,
showProp,
valueProp
} = row;
if (props[valueProp] == null) {
return false;
}
return props[showProp] || props.sortKey === name;
}
function getInfoRowProps(row, props) {
const { name } = row;
if (name === 'year') {
return {
title: 'Year',
iconName: icons.CALENDAR,
label: props.year
};
}
if (name === 'genres') {
return {
title: 'Genres',
iconName: icons.GENRE,
label: props.genres.slice(0, 2).join(', ')
};
}
if (name === 'ratings') {
return {
title: 'Ratings',
iconName: icons.HEART,
label: `${props.ratings.value * 10}%`
};
}
if (name === 'certification') {
return {
title: 'Certification',
iconName: icons.FILM,
label: props.certification
};
}
if (name === 'studio') {
return {
title: 'Studio',
iconName: icons.STUDIO,
label: props.studio
};
}
}
function DiscoverMovieOverviewInfo(props) {
const {
height
} = props;
let shownRows = 1;
const maxRows = Math.floor(height / (infoRowHeight + 4));
return (
<div className={styles.infos}>
{
rows.map((row) => {
if (!isVisible(row, props)) {
return null;
}
if (shownRows >= maxRows) {
return null;
}
shownRows++;
const infoRowProps = getInfoRowProps(row, props);
return (
<DiscoverMovieOverviewInfoRow
key={row.name}
{...infoRowProps}
/>
);
})
}
</div>
);
}
DiscoverMovieOverviewInfo.propTypes = {
height: PropTypes.number.isRequired,
showStudio: PropTypes.bool.isRequired,
showYear: PropTypes.bool.isRequired,
showRatings: PropTypes.bool.isRequired,
showCertification: PropTypes.bool.isRequired,
showGenres: PropTypes.bool.isRequired,
studio: PropTypes.string,
year: PropTypes.number,
certification: PropTypes.string,
ratings: PropTypes.object,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
sortKey: PropTypes.string.isRequired
};
export default DiscoverMovieOverviewInfo;

@ -0,0 +1,10 @@
.infoRow {
flex: 0 0 $movieIndexOverviewInfoRowHeight;
margin: 2px 0;
}
.icon {
margin-right: 5px;
width: 25px !important;
text-align: center;
}

@ -0,0 +1,35 @@
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import styles from './DiscoverMovieOverviewInfoRow.css';
function DiscoverMovieOverviewInfoRow(props) {
const {
title,
iconName,
label
} = props;
return (
<div
className={styles.infoRow}
title={title}
>
<Icon
className={styles.icon}
name={iconName}
size={14}
/>
{label}
</div>
);
}
DiscoverMovieOverviewInfoRow.propTypes = {
title: PropTypes.string,
iconName: PropTypes.object.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
};
export default DiscoverMovieOverviewInfoRow;

@ -2,12 +2,12 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Grid, WindowScroller } from 'react-virtualized';
import Measure from 'Components/Measure';
import AddListMovieItemConnector from 'DiscoverMovie/AddListMovieItemConnector';
import DiscoverMovieItemConnector from 'DiscoverMovie/DiscoverMovieItemConnector';
import dimensions from 'Styles/Variables/dimensions';
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
import AddListMovieOverviewConnector from './AddListMovieOverviewConnector';
import styles from './AddListMovieOverviews.css';
import DiscoverMovieOverviewConnector from './DiscoverMovieOverviewConnector';
import styles from './DiscoverMovieOverviews.css';
// Poster container dimensions
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
@ -41,7 +41,7 @@ function calculatePosterHeight(posterWidth) {
return Math.ceil((250 / 170) * posterWidth);
}
class AddListMovieOverviews extends Component {
class DiscoverMovieOverviews extends Component {
//
// Lifecycle
@ -156,9 +156,9 @@ class AddListMovieOverviews extends Component {
key={key}
style={style}
>
<AddListMovieItemConnector
<DiscoverMovieItemConnector
key={movie.tmdbId}
component={AddListMovieOverviewConnector}
component={DiscoverMovieOverviewConnector}
sortKey={sortKey}
posterWidth={posterWidth}
posterHeight={posterHeight}
@ -243,7 +243,7 @@ class AddListMovieOverviews extends Component {
}
}
AddListMovieOverviews.propTypes = {
DiscoverMovieOverviews.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
sortKey: PropTypes.string,
overviewOptions: PropTypes.object.isRequired,
@ -258,4 +258,4 @@ AddListMovieOverviews.propTypes = {
onSelectedChange: PropTypes.func.isRequired
};
export default AddListMovieOverviews;
export default DiscoverMovieOverviews;

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import AddListMovieOverviews from './AddListMovieOverviews';
import DiscoverMovieOverviews from './DiscoverMovieOverviews';
function createMapStateToProps() {
return createSelector(
@ -22,4 +22,4 @@ function createMapStateToProps() {
);
}
export default connect(createMapStateToProps)(AddListMovieOverviews);
export default connect(createMapStateToProps)(DiscoverMovieOverviews);

@ -1,133 +0,0 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Form from 'Components/Form/Form';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import Button from 'Components/Link/Button';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
const posterSizeOptions = [
{ key: 'small', value: 'Small' },
{ key: 'medium', value: 'Medium' },
{ key: 'large', value: 'Large' }
];
class AddListMovieOverviewOptionsModalContent extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
size: props.size,
showStudio: props.showStudio
};
}
componentDidUpdate(prevProps) {
const {
size,
showStudio
} = this.props;
const state = {};
if (size !== prevProps.size) {
state.size = size;
}
if (showStudio !== prevProps.showStudio) {
state.showStudio = showStudio;
}
if (!_.isEmpty(state)) {
this.setState(state);
}
}
//
// Listeners
onChangeOverviewOption = ({ name, value }) => {
this.setState({
[name]: value
}, () => {
this.props.onChangeOverviewOption({ [name]: value });
});
}
//
// Render
render() {
const {
onModalClose
} = this.props;
const {
size,
showStudio
} = this.state;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Overview Options
</ModalHeader>
<ModalBody>
<Form>
<FormGroup>
<FormLabel>{translate('PosterSize')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="size"
value={size}
values={posterSizeOptions}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowStudio')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showStudio"
value={showStudio}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button
onPress={onModalClose}
>
{translate('Close')}
</Button>
</ModalFooter>
</ModalContent>
);
}
}
AddListMovieOverviewOptionsModalContent.propTypes = {
size: PropTypes.string.isRequired,
showStudio: PropTypes.bool.isRequired,
onChangeOverviewOption: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddListMovieOverviewOptionsModalContent;

@ -1,15 +1,15 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import AddListMovieOverviewOptionsModalContentConnector from './AddListMovieOverviewOptionsModalContentConnector';
import DiscoverMovieOverviewOptionsModalContentConnector from './DiscoverMovieOverviewOptionsModalContentConnector';
function AddListMovieOverviewOptionsModal({ isOpen, onModalClose, ...otherProps }) {
function DiscoverMovieOverviewOptionsModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
isOpen={isOpen}
onModalClose={onModalClose}
>
<AddListMovieOverviewOptionsModalContentConnector
<DiscoverMovieOverviewOptionsModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
@ -17,9 +17,9 @@ function AddListMovieOverviewOptionsModal({ isOpen, onModalClose, ...otherProps
);
}
AddListMovieOverviewOptionsModal.propTypes = {
DiscoverMovieOverviewOptionsModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddListMovieOverviewOptionsModal;
export default DiscoverMovieOverviewOptionsModal;

@ -0,0 +1,239 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Form from 'Components/Form/Form';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import Button from 'Components/Link/Button';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
const posterSizeOptions = [
{ key: 'small', value: 'Small' },
{ key: 'medium', value: 'Medium' },
{ key: 'large', value: 'Large' }
];
class DiscoverMovieOverviewOptionsModalContent extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
size: props.size,
showStudio: props.showStudio,
showCertification: props.showCertification,
showRatings: props.showRatings,
showYear: props.showYear,
showGenres: props.showGenres,
includeRecommendations: props.includeRecommendations
};
}
componentDidUpdate(prevProps) {
const {
size,
showStudio,
showYear,
showRatings,
showCertification,
showGenres,
includeRecommendations
} = this.props;
const state = {};
if (size !== prevProps.size) {
state.size = size;
}
if (showStudio !== prevProps.showStudio) {
state.showStudio = showStudio;
}
if (showYear !== prevProps.showYear) {
state.showYear = showYear;
}
if (showRatings !== prevProps.showRatings) {
state.showRatings = showRatings;
}
if (showCertification !== prevProps.showCertification) {
state.showCertification = showCertification;
}
if (showGenres !== prevProps.showGenres) {
state.showGenres = showGenres;
}
if (includeRecommendations !== prevProps.includeRecommendations) {
state.includeRecommendations = includeRecommendations;
}
if (!_.isEmpty(state)) {
this.setState(state);
}
}
//
// Listeners
onChangeOverviewOption = ({ name, value }) => {
this.setState({
[name]: value
}, () => {
this.props.onChangeOverviewOption({ [name]: value });
});
}
onChangeOption = ({ name, value }) => {
this.setState({
[name]: value
}, () => {
this.props.onChangeOption({
[name]: value
});
});
}
//
// Render
render() {
const {
onModalClose
} = this.props;
const {
size,
showStudio,
showCertification,
showRatings,
showYear,
showGenres,
includeRecommendations
} = this.state;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Overview Options
</ModalHeader>
<ModalBody>
<Form>
<FormGroup>
<FormLabel>Include Radarr Recommendations</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="includeRecommendations"
value={includeRecommendations}
helpText="Include Radarr recommended movies in discovery view"
onChange={this.onChangeOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('PosterSize')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="size"
value={size}
values={posterSizeOptions}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>Show Genres</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showGenres"
value={showGenres}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowStudio')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showStudio"
value={showStudio}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>Show Year</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showYear"
value={showYear}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>Show Ratings</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showRatings"
value={showRatings}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>Show Certification</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showCertification"
value={showCertification}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button
onPress={onModalClose}
>
{translate('Close')}
</Button>
</ModalFooter>
</ModalContent>
);
}
}
DiscoverMovieOverviewOptionsModalContent.propTypes = {
size: PropTypes.string.isRequired,
showStudio: PropTypes.bool.isRequired,
showYear: PropTypes.bool.isRequired,
showRatings: PropTypes.bool.isRequired,
showCertification: PropTypes.bool.isRequired,
showGenres: PropTypes.bool.isRequired,
includeRecommendations: PropTypes.bool.isRequired,
onChangeOverviewOption: PropTypes.func.isRequired,
onChangeOption: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default DiscoverMovieOverviewOptionsModalContent;

@ -1,13 +1,16 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setListMovieOverviewOption } from 'Store/Actions/discoverMovieActions';
import AddListMovieOverviewOptionsModalContent from './AddListMovieOverviewOptionsModalContent';
import { setListMovieOption, setListMovieOverviewOption } from 'Store/Actions/discoverMovieActions';
import DiscoverMovieOverviewOptionsModalContent from './DiscoverMovieOverviewOptionsModalContent';
function createMapStateToProps() {
return createSelector(
(state) => state.discoverMovie,
(discoverMovie) => {
return discoverMovie.overviewOptions;
return {
...discoverMovie.options,
...discoverMovie.overviewOptions
};
}
);
}
@ -16,8 +19,11 @@ function createMapDispatchToProps(dispatch, props) {
return {
onChangeOverviewOption(payload) {
dispatch(setListMovieOverviewOption(payload));
},
onChangeOption(payload) {
dispatch(setListMovieOption(payload));
}
};
}
export default connect(createMapStateToProps, createMapDispatchToProps)(AddListMovieOverviewOptionsModalContent);
export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieOverviewOptionsModalContent);

@ -1,30 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import styles from './AddListMoviePosterInfo.css';
function AddListMoviePosterInfo(props) {
const {
studio,
sortKey
} = props;
if (sortKey === 'studio' && studio) {
return (
<div className={styles.info}>
{studio}
</div>
);
}
return null;
}
AddListMoviePosterInfo.propTypes = {
studio: PropTypes.string,
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired
};
export default AddListMoviePosterInfo;

@ -12,9 +12,10 @@ import { icons } from 'Helpers/Props';
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
import MoviePoster from 'Movie/MoviePoster';
import translate from 'Utilities/String/translate';
import styles from './AddListMoviePoster.css';
import DiscoverMoviePosterInfo from './DiscoverMoviePosterInfo';
import styles from './DiscoverMoviePoster.css';
class AddListMoviePoster extends Component {
class DiscoverMoviePoster extends Component {
//
// Lifecycle
@ -81,14 +82,17 @@ class AddListMoviePoster extends Component {
year,
overview,
folder,
titleSlug,
images,
posterWidth,
posterHeight,
showTitle,
isExisting,
isExcluded,
isSelected
isSelected,
showRelativeDates,
shortDateFormat,
timeFormat,
...otherProps
} = this.props;
const {
@ -97,7 +101,7 @@ class AddListMoviePoster extends Component {
isExcludeMovieModalOpen
} = this.state;
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onPress };
const elementStyle = {
width: `${posterWidth}px`,
@ -186,6 +190,13 @@ class AddListMoviePoster extends Component {
</div>
}
<DiscoverMoviePosterInfo
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
timeFormat={timeFormat}
{...otherProps}
/>
<AddNewDiscoverMovieModal
isOpen={isNewAddMovieModalOpen && !isExisting}
tmdbId={tmdbId}
@ -209,7 +220,7 @@ class AddListMoviePoster extends Component {
}
}
AddListMoviePoster.propTypes = {
DiscoverMoviePoster.propTypes = {
tmdbId: PropTypes.number.isRequired,
imdbId: PropTypes.string,
youTubeTrailerId: PropTypes.string,
@ -218,7 +229,6 @@ AddListMoviePoster.propTypes = {
overview: PropTypes.string.isRequired,
folder: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
titleSlug: PropTypes.string.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired,
@ -232,4 +242,4 @@ AddListMoviePoster.propTypes = {
onSelectedChange: PropTypes.func.isRequired
};
export default AddListMoviePoster;
export default DiscoverMoviePoster;

@ -1,7 +1,7 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import AddListMoviePoster from './AddListMoviePoster';
import DiscoverMoviePoster from './DiscoverMoviePoster';
function createMapStateToProps() {
return createSelector(
@ -14,4 +14,4 @@ function createMapStateToProps() {
);
}
export default connect(createMapStateToProps)(AddListMoviePoster);
export default connect(createMapStateToProps)(DiscoverMoviePoster);

@ -0,0 +1,139 @@
import PropTypes from 'prop-types';
import React from 'react';
import HeartRating from 'Components/HeartRating';
import { getMovieStatusDetails } from 'Movie/MovieStatus';
import formatRuntime from 'Utilities/Date/formatRuntime';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
import styles from './DiscoverMoviePosterInfo.css';
function DiscoverMoviePosterInfo(props) {
const {
status,
studio,
inCinemas,
digitalRelease,
physicalRelease,
certification,
runtime,
ratings,
sortKey,
showRelativeDates,
shortDateFormat,
timeFormat
} = props;
if (sortKey === 'status' && status) {
return (
<div className={styles.info}>
{getMovieStatusDetails(status).title}
</div>
);
}
if (sortKey === 'studio' && studio) {
return (
<div className={styles.info}>
{studio}
</div>
);
}
if (sortKey === 'inCinemas' && inCinemas) {
const inCinemasDate = getRelativeDate(
inCinemas,
shortDateFormat,
showRelativeDates,
{
timeFormat,
timeForToday: false
}
);
return (
<div className={styles.info}>
{`In Cinemas ${inCinemasDate}`}
</div>
);
}
if (sortKey === 'digitalRelease' && digitalRelease) {
const digitalReleaseDate = getRelativeDate(
digitalRelease,
shortDateFormat,
showRelativeDates,
{
timeFormat,
timeForToday: false
}
);
return (
<div className={styles.info}>
{`Digital ${digitalReleaseDate}`}
</div>
);
}
if (sortKey === 'physicalRelease' && physicalRelease) {
const physicalReleaseDate = getRelativeDate(
physicalRelease,
shortDateFormat,
showRelativeDates,
{
timeFormat,
timeForToday: false
}
);
return (
<div className={styles.info}>
{`Released ${physicalReleaseDate}`}
</div>
);
}
if (sortKey === 'certification' && certification) {
return (
<div className={styles.info}>
{certification}
</div>
);
}
if (sortKey === 'runtime' && runtime) {
return (
<div className={styles.info}>
{formatRuntime(runtime)}
</div>
);
}
if (sortKey === 'ratings' && ratings) {
return (
<div className={styles.info}>
<HeartRating
rating={ratings.value}
/>
</div>
);
}
return null;
}
DiscoverMoviePosterInfo.propTypes = {
status: PropTypes.string,
studio: PropTypes.string,
inCinemas: PropTypes.string,
certification: PropTypes.string,
digitalRelease: PropTypes.string,
physicalRelease: PropTypes.string,
runtime: PropTypes.number,
ratings: PropTypes.object,
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired
};
export default DiscoverMoviePosterInfo;

@ -2,12 +2,12 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Grid, WindowScroller } from 'react-virtualized';
import Measure from 'Components/Measure';
import AddListMovieItemConnector from 'DiscoverMovie/AddListMovieItemConnector';
import DiscoverMovieItemConnector from 'DiscoverMovie/DiscoverMovieItemConnector';
import dimensions from 'Styles/Variables/dimensions';
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
import AddListMoviePosterConnector from './AddListMoviePosterConnector';
import styles from './AddListMoviePosters.css';
import DiscoverMoviePosterConnector from './DiscoverMoviePosterConnector';
import styles from './DiscoverMoviePosters.css';
// Poster container dimensions
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
@ -65,7 +65,7 @@ function calculatePosterHeight(posterWidth) {
return Math.ceil((250 / 170) * posterWidth);
}
class AddListMoviePosters extends Component {
class DiscoverMoviePosters extends Component {
//
// Lifecycle
@ -201,9 +201,9 @@ class AddListMoviePosters extends Component {
padding: this._padding
}}
>
<AddListMovieItemConnector
<DiscoverMovieItemConnector
key={movie.tmdbId}
component={AddListMoviePosterConnector}
component={DiscoverMoviePosterConnector}
sortKey={sortKey}
posterWidth={posterWidth}
posterHeight={posterHeight}
@ -289,7 +289,7 @@ class AddListMoviePosters extends Component {
}
}
AddListMoviePosters.propTypes = {
DiscoverMoviePosters.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
sortKey: PropTypes.string,
posterOptions: PropTypes.object.isRequired,
@ -303,4 +303,4 @@ AddListMoviePosters.propTypes = {
onSelectedChange: PropTypes.func.isRequired
};
export default AddListMoviePosters;
export default DiscoverMoviePosters;

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import AddListMoviePosters from './AddListMoviePosters';
import DiscoverMoviePosters from './DiscoverMoviePosters';
function createMapStateToProps() {
return createSelector(
@ -21,4 +21,4 @@ function createMapStateToProps() {
);
}
export default connect(createMapStateToProps)(AddListMoviePosters);
export default connect(createMapStateToProps)(DiscoverMoviePosters);

@ -1,15 +1,15 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import AddListMoviePosterOptionsModalContentConnector from './AddListMoviePosterOptionsModalContentConnector';
import DiscoverMoviePosterOptionsModalContentConnector from './DiscoverMoviePosterOptionsModalContentConnector';
function AddListMoviePosterOptionsModal({ isOpen, onModalClose, ...otherProps }) {
function DiscoverMoviePosterOptionsModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
isOpen={isOpen}
onModalClose={onModalClose}
>
<AddListMoviePosterOptionsModalContentConnector
<DiscoverMoviePosterOptionsModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
@ -17,9 +17,9 @@ function AddListMoviePosterOptionsModal({ isOpen, onModalClose, ...otherProps })
);
}
AddListMoviePosterOptionsModal.propTypes = {
DiscoverMoviePosterOptionsModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddListMoviePosterOptionsModal;
export default DiscoverMoviePosterOptionsModal;

@ -19,7 +19,7 @@ const posterSizeOptions = [
{ key: 'large', value: 'Large' }
];
class AddListMoviePosterOptionsModalContent extends Component {
class DiscoverMoviePosterOptionsModalContent extends Component {
//
// Lifecycle
@ -29,14 +29,16 @@ class AddListMoviePosterOptionsModalContent extends Component {
this.state = {
size: props.size,
showTitle: props.showTitle
showTitle: props.showTitle,
includeRecommendations: props.includeRecommendations
};
}
componentDidUpdate(prevProps) {
const {
size,
showTitle
showTitle,
includeRecommendations
} = this.props;
const state = {};
@ -49,6 +51,10 @@ class AddListMoviePosterOptionsModalContent extends Component {
state.showTitle = showTitle;
}
if (includeRecommendations !== prevProps.includeRecommendations) {
state.includeRecommendations = includeRecommendations;
}
if (!_.isEmpty(state)) {
this.setState(state);
}
@ -65,6 +71,16 @@ class AddListMoviePosterOptionsModalContent extends Component {
});
}
onChangeOption = ({ name, value }) => {
this.setState({
[name]: value
}, () => {
this.props.onChangeOption({
[name]: value
});
});
}
//
// Render
@ -75,7 +91,8 @@ class AddListMoviePosterOptionsModalContent extends Component {
const {
size,
showTitle
showTitle,
includeRecommendations
} = this.state;
return (
@ -86,6 +103,18 @@ class AddListMoviePosterOptionsModalContent extends Component {
<ModalBody>
<Form>
<FormGroup>
<FormLabel>Include Radarr Recommendations</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="includeRecommendations"
value={includeRecommendations}
helpText="Include Radarr recommended movies in discovery view"
onChange={this.onChangeOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('PosterSize')}</FormLabel>
@ -124,11 +153,13 @@ class AddListMoviePosterOptionsModalContent extends Component {
}
}
AddListMoviePosterOptionsModalContent.propTypes = {
DiscoverMoviePosterOptionsModalContent.propTypes = {
size: PropTypes.string.isRequired,
showTitle: PropTypes.bool.isRequired,
includeRecommendations: PropTypes.bool.isRequired,
onChangePosterOption: PropTypes.func.isRequired,
onChangeOption: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddListMoviePosterOptionsModalContent;
export default DiscoverMoviePosterOptionsModalContent;

@ -1,13 +1,16 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setListMoviePosterOption } from 'Store/Actions/discoverMovieActions';
import AddListMoviePosterOptionsModalContent from './AddListMoviePosterOptionsModalContent';
import { setListMovieOption, setListMoviePosterOption } from 'Store/Actions/discoverMovieActions';
import DiscoverMoviePosterOptionsModalContent from './DiscoverMoviePosterOptionsModalContent';
function createMapStateToProps() {
return createSelector(
(state) => state.discoverMovie,
(discoverMovie) => {
return discoverMovie.posterOptions;
return {
...discoverMovie.options,
...discoverMovie.posterOptions
};
}
);
}
@ -16,8 +19,11 @@ function createMapDispatchToProps(dispatch, props) {
return {
onChangePosterOption(payload) {
dispatch(setListMoviePosterOption(payload));
},
onChangeOption(payload) {
dispatch(setListMovieOption(payload));
}
};
}
export default connect(createMapStateToProps, createMapDispatchToProps)(AddListMoviePosterOptionsModalContent);
export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMoviePosterOptionsModalContent);

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
class AddListMovieActionsCell extends Component {
class DiscoverMovieActionsCell extends Component {
//
// Render
@ -47,8 +47,8 @@ class AddListMovieActionsCell extends Component {
}
}
AddListMovieActionsCell.propTypes = {
DiscoverMovieActionsCell.propTypes = {
id: PropTypes.number.isRequired
};
export default AddListMovieActionsCell;
export default DiscoverMovieActionsCell;

@ -1,9 +1,10 @@
.status {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 60px;
flex: 0 0 30px;
}
.collection,
.sortTitle {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
@ -18,23 +19,36 @@
.inCinemas,
.physicalRelease,
.digitalRelease,
.genres {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 180px;
}
.movieStatus,
.ratings,
.runtime {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 90px;
}
.lists {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 1 0 110px;
}
.certification {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 100px;
flex: 0 0 115px;
}
.ratings {
.isRecommendation {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 80px;
flex: 0 0 50px;
}
.actions {

@ -1,14 +1,16 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import IconButton from 'Components/Link/IconButton';
import TableOptionsModal from 'Components/Table/TableOptions/TableOptionsModal';
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
import { icons } from 'Helpers/Props';
import styles from './AddListMovieHeader.css';
import DiscoverMovieTableOptionsConnector from './DiscoverMovieTableOptionsConnector';
import styles from './DiscoverMovieHeader.css';
class AddListMovieHeader extends Component {
class DiscoverMovieHeader extends Component {
//
// Lifecycle
@ -84,6 +86,23 @@ class AddListMovieHeader extends Component {
);
}
if (name === 'isRecommendation') {
return (
<VirtualTableHeaderCell
key={name}
className={styles[name]}
name={name}
isSortable={true}
{...otherProps}
>
<Icon
name={icons.RECOMMENDED}
size={12}
/>
</VirtualTableHeaderCell>
);
}
return (
<VirtualTableHeaderCell
key={name}
@ -102,6 +121,7 @@ class AddListMovieHeader extends Component {
isOpen={this.state.isTableOptionsModalOpen}
columns={columns}
onTableOptionChange={onTableOptionChange}
optionsComponent={DiscoverMovieTableOptionsConnector}
onModalClose={this.onTableOptionsModalClose}
/>
</VirtualTableHeader>
@ -109,7 +129,7 @@ class AddListMovieHeader extends Component {
}
}
AddListMovieHeader.propTypes = {
DiscoverMovieHeader.propTypes = {
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
onTableOptionChange: PropTypes.func.isRequired,
allSelected: PropTypes.bool.isRequired,
@ -117,4 +137,4 @@ AddListMovieHeader.propTypes = {
onSelectAllChange: PropTypes.func.isRequired
};
export default AddListMovieHeader;
export default DiscoverMovieHeader;

@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { setListMovieTableOption } from 'Store/Actions/discoverMovieActions';
import AddListMovieHeader from './AddListMovieHeader';
import DiscoverMovieHeader from './DiscoverMovieHeader';
function createMapDispatchToProps(dispatch, props) {
return {
@ -10,4 +10,4 @@ function createMapDispatchToProps(dispatch, props) {
};
}
export default connect(undefined, createMapDispatchToProps)(AddListMovieHeader);
export default connect(undefined, createMapDispatchToProps)(DiscoverMovieHeader);

@ -8,7 +8,19 @@
.status {
composes: cell;
flex: 0 0 60px;
flex: 0 0 30px;
}
.alreadyExistsIcon {
width: 20px !important;
color: #37bc9b;
pointer-events: all;
}
.exclusionIcon {
width: 20px !important;
color: $dangerColor;
pointer-events: all;
}
.collection,
@ -26,29 +38,36 @@
.inCinemas,
.physicalRelease,
.digitalRelease,
.genres {
composes: cell;
flex: 0 0 180px;
}
.movieStatus,
.certification {
composes: cell;
flex: 0 0 100px;
flex: 0 0 115px;
}
.ratings,
.runtime {
composes: cell;
flex: 0 0 90px;
}
.ratings {
.lists {
composes: cell;
flex: 0 0 80px;
flex: 1 0 110px;
}
.tags {
.isRecommendation {
composes: cell;
flex: 1 0 60px;
flex: 0 0 50px;
}
.actions {

@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import HeartRating from 'Components/HeartRating';
import Icon from 'Components/Icon';
import ImportListListConnector from 'Components/ImportListListConnector';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
@ -12,11 +13,12 @@ import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
import { icons } from 'Helpers/Props';
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
import formatRuntime from 'Utilities/Date/formatRuntime';
import translate from 'Utilities/String/translate';
import ListMovieStatusCell from './ListMovieStatusCell';
import styles from './AddListMovieRow.css';
import styles from './DiscoverMovieRow.css';
class AddListMovieRow extends Component {
class DiscoverMovieRow extends Component {
//
// Lifecycle
@ -59,10 +61,11 @@ class AddListMovieRow extends Component {
imdbId,
youTubeTrailerId,
title,
titleSlug,
studio,
inCinemas,
physicalRelease,
digitalRelease,
runtime,
year,
overview,
folder,
@ -70,10 +73,13 @@ class AddListMovieRow extends Component {
genres,
ratings,
certification,
collection,
columns,
isExisting,
isExcluded,
isRecommendation,
isSelected,
lists,
onSelectedChange
} = this.props;
@ -82,7 +88,7 @@ class AddListMovieRow extends Component {
isExcludeMovieModalOpen
} = this.state;
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onAddMoviePress };
const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onAddMoviePress };
return (
<>
@ -113,6 +119,7 @@ class AddListMovieRow extends Component {
className={styles[name]}
status={status}
isExclusion={isExcluded}
isExisting={isExisting}
component={VirtualTableRowCell}
/>
);
@ -129,6 +136,35 @@ class AddListMovieRow extends Component {
>
{title}
</Link>
{
isExisting ?
<Icon
className={styles.alreadyExistsIcon}
name={icons.CHECK_CIRCLE}
title={'Already in your Library'}
/> : null
}
{
isExcluded ?
<Icon
className={styles.exclusionIcon}
name={icons.DANGER}
title={'Movie Excluded From Automatic Add'}
/> : null
}
</VirtualTableRowCell>
);
}
if (name === 'collection') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{collection ? collection.name : null }
</VirtualTableRowCell>
);
}
@ -166,6 +202,28 @@ class AddListMovieRow extends Component {
);
}
if (name === 'digitalRelease') {
return (
<RelativeDateCellConnector
key={name}
className={styles[name]}
date={digitalRelease}
component={VirtualTableRowCell}
/>
);
}
if (name === 'runtime') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{formatRuntime(runtime)}
</VirtualTableRowCell>
);
}
if (name === 'genres') {
const joinedGenres = genres.join(', ');
@ -205,6 +263,38 @@ class AddListMovieRow extends Component {
);
}
if (name === 'lists') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
<ImportListListConnector
lists={lists}
/>
</VirtualTableRowCell>
);
}
if (name === 'isRecommendation') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{
isRecommendation ?
<Icon
name={icons.RECOMMENDED}
size={12}
title='Recommended'
/> :
null
}
</VirtualTableRowCell>
);
}
if (name === 'actions') {
return (
<VirtualTableRowCell
@ -267,7 +357,7 @@ class AddListMovieRow extends Component {
}
}
AddListMovieRow.propTypes = {
DiscoverMovieRow.propTypes = {
tmdbId: PropTypes.number.isRequired,
imdbId: PropTypes.string,
youTubeTrailerId: PropTypes.string,
@ -277,23 +367,27 @@ AddListMovieRow.propTypes = {
overview: PropTypes.string.isRequired,
folder: PropTypes.string.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
titleSlug: PropTypes.string.isRequired,
studio: PropTypes.string,
inCinemas: PropTypes.string,
physicalRelease: PropTypes.string,
digitalRelease: PropTypes.string,
runtime: PropTypes.number,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
ratings: PropTypes.object.isRequired,
certification: PropTypes.string,
collection: PropTypes.object,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
isExisting: PropTypes.bool.isRequired,
isExcluded: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
isRecommendation: PropTypes.bool.isRequired,
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
onSelectedChange: PropTypes.func.isRequired
};
AddListMovieRow.defaultProps = {
DiscoverMovieRow.defaultProps = {
genres: [],
tags: []
lists: []
};
export default AddListMovieRow;
export default DiscoverMovieRow;

@ -1,7 +1,7 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import AddListMovieRow from './AddListMovieRow';
import DiscoverMovieRow from './DiscoverMovieRow';
function createMapStateToProps() {
return createSelector(
@ -14,4 +14,4 @@ function createMapStateToProps() {
);
}
export default connect(createMapStateToProps)(AddListMovieRow);
export default connect(createMapStateToProps)(DiscoverMovieRow);

@ -2,14 +2,14 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import VirtualTable from 'Components/Table/VirtualTable';
import VirtualTableRow from 'Components/Table/VirtualTableRow';
import AddListMovieItemConnector from 'DiscoverMovie/AddListMovieItemConnector';
import DiscoverMovieItemConnector from 'DiscoverMovie/DiscoverMovieItemConnector';
import { sortDirections } from 'Helpers/Props';
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
import AddListMovieHeaderConnector from './AddListMovieHeaderConnector';
import AddListMovieRowConnector from './AddListMovieRowConnector';
import styles from './AddListMovieTable.css';
import DiscoverMovieHeaderConnector from './DiscoverMovieHeaderConnector';
import DiscoverMovieRowConnector from './DiscoverMovieRowConnector';
import styles from './DiscoverMovieTable.css';
class AddListMovieTable extends Component {
class DiscoverMovieTable extends Component {
//
// Lifecycle
@ -58,9 +58,9 @@ class AddListMovieTable extends Component {
key={key}
style={style}
>
<AddListMovieItemConnector
<DiscoverMovieItemConnector
key={movie.tmdbId}
component={AddListMovieRowConnector}
component={DiscoverMovieRowConnector}
columns={columns}
movieId={movie.tmdbId}
isSelected={selectedState[movie.tmdbId]}
@ -99,7 +99,7 @@ class AddListMovieTable extends Component {
overscanRowCount={2}
rowRenderer={this.rowRenderer}
header={
<AddListMovieHeaderConnector
<DiscoverMovieHeaderConnector
columns={columns}
sortKey={sortKey}
sortDirection={sortDirection}
@ -116,7 +116,7 @@ class AddListMovieTable extends Component {
}
}
AddListMovieTable.propTypes = {
DiscoverMovieTable.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
sortKey: PropTypes.string,
@ -132,4 +132,4 @@ AddListMovieTable.propTypes = {
onSelectAllChange: PropTypes.func.isRequired
};
export default AddListMovieTable;
export default DiscoverMovieTable;

@ -1,7 +1,7 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setListMovieSort } from 'Store/Actions/discoverMovieActions';
import AddListMovieTable from './AddListMovieTable';
import DiscoverMovieTable from './DiscoverMovieTable';
function createMapStateToProps() {
return createSelector(
@ -24,4 +24,4 @@ function createMapDispatchToProps(dispatch, props) {
};
}
export default connect(createMapStateToProps, createMapDispatchToProps)(AddListMovieTable);
export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieTable);

@ -0,0 +1,73 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import { inputTypes } from 'Helpers/Props';
class DiscoverMovieTableOptions extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
includeRecommendations: props.includeRecommendations
};
}
componentDidUpdate(prevProps) {
const { includeRecommendations } = this.props;
if (includeRecommendations !== prevProps.includeRecommendations) {
this.setState({
includeRecommendations
});
}
}
//
// Listeners
onChangeOption = ({ name, value }) => {
this.setState({
[name]: value
}, () => {
this.props.onChangeOption({
[name]: value
});
});
}
//
// Render
render() {
const {
includeRecommendations
} = this.state;
return (
<FormGroup>
<FormLabel>Include Radarr Recommendations</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="includeRecommendations"
value={includeRecommendations}
helpText="Include Radarr recommended movies in discovery view"
onChange={this.onChangeOption}
/>
</FormGroup>
);
}
}
DiscoverMovieTableOptions.propTypes = {
includeRecommendations: PropTypes.bool.isRequired,
onChangeOption: PropTypes.func.isRequired
};
export default DiscoverMovieTableOptions;

@ -0,0 +1,24 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setListMovieOption } from 'Store/Actions/discoverMovieActions';
import DiscoverMovieTableOptions from './DiscoverMovieTableOptions';
function createMapStateToProps() {
return createSelector(
(state) => state.discoverMovie,
(discoverMovie) => {
return discoverMovie.options;
}
);
}
function createMapDispatchToProps(dispatch, props) {
return {
onChangeOption(payload) {
dispatch(setListMovieOption(payload));
}
};
}
export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieTableOptions);

@ -1,13 +1,3 @@
.status {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 60px;
}
.statusIcon {
width: 20px !important;
}
.exclusionIcon {
color: $dangerColor;
}

@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import VirtualTableRowCell from 'Components/Table/Cells/TableRowCell';
import { icons } from 'Helpers/Props';
import { getMovieStatusDetails } from 'Movie/MovieStatus';
import styles from './ListMovieStatusCell.css';
@ -10,7 +9,6 @@ function ListMovieStatusCell(props) {
const {
className,
status,
isExclusion,
component: Component,
...otherProps
} = props;
@ -28,15 +26,6 @@ function ListMovieStatusCell(props) {
title={`${statusDetails.title}: ${statusDetails.message}`}
/>
{
isExclusion ?
<Icon
className={styles.exclusionIcon}
name={icons.DANGER}
title={'Movie Excluded From Automatic Add'}
/> : null
}
</Component>
);
}
@ -44,7 +33,6 @@ function ListMovieStatusCell(props) {
ListMovieStatusCell.propTypes = {
className: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
isExclusion: PropTypes.bool.isRequired,
component: PropTypes.elementType
};

@ -8,3 +8,4 @@ export const QUALITY = 'quality';
export const QUALITY_PROFILE = 'qualityProfile';
export const MOVIE_STATUS = 'movieStatus';
export const TAG = 'tag';
export const IMPORTLIST = 'importList';

@ -29,6 +29,7 @@ import {
faBookReader as fasBookReader,
faBroadcastTower as fasBroadcastTower,
faBug as fasBug,
faBuilding as fasBuilding,
faBullhorn as fasBullhorn,
faCalendarAlt as fasCalendarAlt,
faCaretDown as fasCaretDown,
@ -92,7 +93,9 @@ import {
faTable as fasTable,
faTags as fasTags,
faTh as fasTh,
faTheaterMasks as fasTheaterMasks,
faThList as fasThList,
faThumbsUp as fasThumbsUp,
faTicketAlt as fasTicketAlt,
faTimes as fasTimes,
faTimesCircle as fasTimesCircle,
@ -145,10 +148,12 @@ export const EXPAND_INDETERMINATE = fasChevronCircleRight;
export const EXTERNAL_LINK = fasExternalLinkAlt;
export const FATAL = fasTimesCircle;
export const FILE = farFile;
export const FILM = fasFilm;
export const FILTER = fasFilter;
export const FLAG = fasFlag;
export const FOLDER = farFolder;
export const FOLDER_OPEN = fasFolderOpen;
export const GENRE = fasTheaterMasks;
export const GROUP = farObjectGroup;
export const HEALTH = fasMedkit;
export const HEART = fasHeart;
@ -180,6 +185,7 @@ export const PROFILE = fasUser;
export const POSTER = fasTh;
export const QUEUED = fasCloud;
export const QUICK = fasRocket;
export const RECOMMENDED = fasThumbsUp;
export const REFRESH = fasSync;
export const REMOVE = fasTimes;
export const RESTART = fasRedoAlt;
@ -199,7 +205,7 @@ export const SORT = fasSort;
export const SORT_ASCENDING = fasSortUp;
export const SORT_DESCENDING = fasSortDown;
export const SPINNER = fasSpinner;
export const STUDIO = fasFilm;
export const STUDIO = fasBuilding;
export const SUBTRACT = fasMinus;
export const SYSTEM = fasLaptop;
export const TABLE = fasTable;

@ -24,7 +24,7 @@ class DeleteMovieModalContent extends Component {
this.state = {
deleteFiles: false,
addNetImportExclusion: false
addImportExclusion: false
};
}
@ -35,16 +35,16 @@ class DeleteMovieModalContent extends Component {
this.setState({ deleteFiles: value });
}
onAddNetImportExclusionChange = ({ value }) => {
this.setState({ addNetImportExclusion: value });
onAddImportExclusionChange = ({ value }) => {
this.setState({ addImportExclusion: value });
}
onDeleteMovieConfirmed = () => {
const deleteFiles = this.state.deleteFiles;
const addNetImportExclusion = this.state.addNetImportExclusion;
const addImportExclusion = this.state.addImportExclusion;
this.setState({ deleteFiles: false, addNetImportExclusion: false });
this.props.onDeletePress(deleteFiles, addNetImportExclusion);
this.setState({ deleteFiles: false, addImportExclusion: false });
this.props.onDeletePress(deleteFiles, addImportExclusion);
}
//
@ -64,7 +64,7 @@ class DeleteMovieModalContent extends Component {
} = statistics;
const deleteFiles = this.state.deleteFiles;
const addNetImportExclusion = this.state.addNetImportExclusion;
const addImportExclusion = this.state.addImportExclusion;
let deleteFilesLabel = `Delete ${movieFileCount} Movie Files`;
let deleteFilesHelpText = 'Delete the movie files and movie folder';
@ -122,11 +122,11 @@ class DeleteMovieModalContent extends Component {
<FormInputGroup
type={inputTypes.CHECK}
name="addNetImportExclusion"
value={addNetImportExclusion}
name="addImportExclusion"
value={addImportExclusion}
helpText="Prevent movie from being added to Radarr by lists"
kind={kinds.DANGER}
onChange={this.onAddNetImportExclusionChange}
onChange={this.onAddImportExclusionChange}
/>
</FormGroup>

@ -24,11 +24,11 @@ class DeleteMovieModalContentConnector extends Component {
//
// Listeners
onDeletePress = (deleteFiles, addNetImportExclusion) => {
onDeletePress = (deleteFiles, addImportExclusion) => {
this.props.deleteMovie({
id: this.props.movieId,
deleteFiles,
addNetImportExclusion
addImportExclusion
});
this.props.onModalClose(true);

@ -4,7 +4,7 @@ import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import { icons } from 'Helpers/Props';
import MovieHeadshot from 'Movie/MovieHeadshot';
import EditNetImportModalConnector from 'Settings/NetImport/NetImport/EditNetImportModalConnector';
import EditImportListModalConnector from 'Settings/ImportLists/ImportLists/EditImportListModalConnector';
import translate from 'Utilities/String/translate';
import styles from '../MovieCreditPoster.css';
@ -18,24 +18,24 @@ class MovieCastPoster extends Component {
this.state = {
hasPosterError: false,
isEditNetImportModalOpen: false
isEditImportListModalOpen: false
};
}
//
// Listeners
onEditNetImportPress = () => {
this.setState({ isEditNetImportModalOpen: true });
onEditImportListPress = () => {
this.setState({ isEditImportListModalOpen: true });
}
onAddNetImportPress = () => {
this.props.onNetImportSelect();
this.setState({ isEditNetImportModalOpen: true });
onAddImportListPress = () => {
this.props.onImportListSelect();
this.setState({ isEditImportListModalOpen: true });
}
onEditNetImportModalClose = () => {
this.setState({ isEditNetImportModalOpen: false });
onEditImportListModalClose = () => {
this.setState({ isEditImportListModalOpen: false });
}
onPosterLoad = () => {
@ -60,7 +60,7 @@ class MovieCastPoster extends Component {
images,
posterWidth,
posterHeight,
netImportId
importListId
} = this.props;
const {
@ -84,18 +84,18 @@ class MovieCastPoster extends Component {
<div className={styles.posterContainer}>
<Label className={styles.controls}>
{
netImportId > 0 ?
importListId > 0 ?
<IconButton
className={styles.action}
name={icons.EDIT}
title={translate('EditPerson')}
onPress={this.onEditNetImportPress}
onPress={this.onEditImportListPress}
/> :
<IconButton
className={styles.action}
name={icons.ADD}
title={translate('FollowPerson')}
onPress={this.onAddNetImportPress}
onPress={this.onAddImportListPress}
/>
}
</Label>
@ -130,11 +130,11 @@ class MovieCastPoster extends Component {
{character}
</div>
<EditNetImportModalConnector
id={netImportId}
isOpen={this.state.isEditNetImportModalOpen}
onModalClose={this.onEditNetImportModalClose}
onDeleteNetImportPress={this.onDeleteNetImportPress}
<EditImportListModalConnector
id={importListId}
isOpen={this.state.isEditImportListModalOpen}
onModalClose={this.onEditImportListModalClose}
onDeleteImportListPress={this.onDeleteImportListPress}
/>
</div>
);
@ -148,12 +148,12 @@ MovieCastPoster.propTypes = {
images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired,
netImportId: PropTypes.number.isRequired,
onNetImportSelect: PropTypes.func.isRequired
importListId: PropTypes.number.isRequired,
onImportListSelect: PropTypes.func.isRequired
};
MovieCastPoster.defaultProps = {
netImportId: 0
importListId: 0
};
export default MovieCastPoster;

@ -4,7 +4,7 @@ import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import { icons } from 'Helpers/Props';
import MovieHeadshot from 'Movie/MovieHeadshot';
import EditNetImportModalConnector from 'Settings/NetImport/NetImport/EditNetImportModalConnector';
import EditImportListModalConnector from 'Settings/ImportLists/ImportLists/EditImportListModalConnector';
import translate from 'Utilities/String/translate';
import styles from '../MovieCreditPoster.css';
@ -18,24 +18,24 @@ class MovieCrewPoster extends Component {
this.state = {
hasPosterError: false,
isEditNetImportModalOpen: false
isEditImportListModalOpen: false
};
}
//
// Listeners
onEditNetImportPress = () => {
this.setState({ isEditNetImportModalOpen: true });
onEditImportListPress = () => {
this.setState({ isEditImportListModalOpen: true });
}
onAddNetImportPress = () => {
this.props.onNetImportSelect();
this.setState({ isEditNetImportModalOpen: true });
onAddImportListPress = () => {
this.props.onImportListSelect();
this.setState({ isEditImportListModalOpen: true });
}
onEditNetImportModalClose = () => {
this.setState({ isEditNetImportModalOpen: false });
onEditImportListModalClose = () => {
this.setState({ isEditImportListModalOpen: false });
}
onPosterLoad = () => {
@ -60,7 +60,7 @@ class MovieCrewPoster extends Component {
images,
posterWidth,
posterHeight,
netImportId
importListId
} = this.props;
const {
@ -84,18 +84,18 @@ class MovieCrewPoster extends Component {
<div className={styles.posterContainer}>
<Label className={styles.controls}>
{
netImportId > 0 ?
importListId > 0 ?
<IconButton
className={styles.action}
name={icons.EDIT}
title={translate('EditPerson')}
onPress={this.onEditNetImportPress}
onPress={this.onEditImportListPress}
/> :
<IconButton
className={styles.action}
name={icons.ADD}
title={translate('FollowPerson')}
onPress={this.onAddNetImportPress}
onPress={this.onAddImportListPress}
/>
}
</Label>
@ -130,11 +130,11 @@ class MovieCrewPoster extends Component {
{job}
</div>
<EditNetImportModalConnector
id={netImportId}
isOpen={this.state.isEditNetImportModalOpen}
onModalClose={this.onEditNetImportModalClose}
onDeleteNetImportPress={this.onDeleteNetImportPress}
<EditImportListModalConnector
id={importListId}
isOpen={this.state.isEditImportListModalOpen}
onModalClose={this.onEditImportListModalClose}
onDeleteImportListPress={this.onDeleteImportListPress}
/>
</div>
);
@ -148,12 +148,12 @@ MovieCrewPoster.propTypes = {
images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired,
netImportId: PropTypes.number.isRequired,
onNetImportSelect: PropTypes.func.isRequired
importListId: PropTypes.number.isRequired,
onImportListSelect: PropTypes.func.isRequired
};
MovieCrewPoster.defaultProps = {
netImportId: 0
importListId: 0
};
export default MovieCrewPoster;

@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { selectNetImportSchema, setNetImportFieldValue, setNetImportValue } from 'Store/Actions/settingsActions';
import { selectImportListSchema, setImportListFieldValue, setImportListValue } from 'Store/Actions/settingsActions';
import createMovieCreditListSelector from 'Store/Selectors/createMovieCreditListSelector';
function createMapStateToProps() {
@ -9,9 +9,9 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
selectNetImportSchema,
setNetImportFieldValue,
setNetImportValue
selectImportListSchema,
setImportListFieldValue,
setImportListValue
};
class MovieCreditPosterConnector extends Component {
@ -19,10 +19,10 @@ class MovieCreditPosterConnector extends Component {
//
// Listeners
onNetImportSelect = () => {
this.props.selectNetImportSchema({ implementation: 'TMDbPersonImport', presetName: undefined });
this.props.setNetImportFieldValue({ name: 'personId', value: this.props.tmdbId.toString() });
this.props.setNetImportValue({ name: 'name', value: `${this.props.personName} - ${this.props.tmdbId}` });
onImportListSelect = () => {
this.props.selectImportListSchema({ implementation: 'TMDbPersonImport', presetName: undefined });
this.props.setImportListFieldValue({ name: 'personId', value: this.props.tmdbId.toString() });
this.props.setImportListValue({ name: 'name', value: `${this.props.personName} - ${this.props.tmdbId}` });
}
//
@ -40,7 +40,7 @@ class MovieCreditPosterConnector extends Component {
{...this.props}
tmdbId={tmdbId}
personName={personName}
onNetImportSelect={this.onNetImportSelect}
onImportListSelect={this.onImportListSelect}
/>
);
}
@ -50,9 +50,9 @@ MovieCreditPosterConnector.propTypes = {
tmdbId: PropTypes.number.isRequired,
personName: PropTypes.string.isRequired,
component: PropTypes.elementType.isRequired,
selectNetImportSchema: PropTypes.func.isRequired,
setNetImportFieldValue: PropTypes.func.isRequired,
setNetImportValue: PropTypes.func.isRequired
selectImportListSchema: PropTypes.func.isRequired,
setImportListFieldValue: PropTypes.func.isRequired,
setImportListValue: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(MovieCreditPosterConnector);

@ -12,7 +12,7 @@ import { clearMovieCredits, fetchMovieCredits } from 'Store/Actions/movieCredits
import { clearMovieFiles, fetchMovieFiles } from 'Store/Actions/movieFileActions';
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
import { cancelFetchReleases, clearReleases } from 'Store/Actions/releaseActions';
import { fetchNetImportSchema } from 'Store/Actions/settingsActions';
import { fetchImportListSchema } from 'Store/Actions/settingsActions';
import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector';
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
@ -198,8 +198,8 @@ function createMapDispatchToProps(dispatch, props) {
dispatchClearQueueDetails() {
dispatch(clearQueueDetails());
},
dispatchFetchNetImportSchema() {
dispatch(fetchNetImportSchema());
dispatchFetchImportListSchema() {
dispatch(fetchImportListSchema());
},
dispatchToggleMovieMonitored(payload) {
dispatch(toggleMovieMonitored(payload));
@ -265,7 +265,7 @@ class MovieDetailsConnector extends Component {
this.props.dispatchFetchExtraFiles({ movieId });
this.props.dispatchFetchMovieCredits({ movieId });
this.props.dispatchFetchQueueDetails({ movieId });
this.props.dispatchFetchNetImportSchema();
this.props.dispatchFetchImportListSchema();
}
unpopulate = () => {
@ -336,7 +336,7 @@ MovieDetailsConnector.propTypes = {
dispatchToggleMovieMonitored: PropTypes.func.isRequired,
dispatchFetchQueueDetails: PropTypes.func.isRequired,
dispatchClearQueueDetails: PropTypes.func.isRequired,
dispatchFetchNetImportSchema: PropTypes.func.isRequired,
dispatchFetchImportListSchema: PropTypes.func.isRequired,
dispatchExecuteCommand: PropTypes.func.isRequired,
onGoToMovie: PropTypes.func.isRequired
};

@ -22,7 +22,7 @@ class DeleteMovieModalContent extends Component {
this.state = {
deleteFiles: false,
addNetImportExclusion: false
addImportExclusion: false
};
}
@ -33,16 +33,16 @@ class DeleteMovieModalContent extends Component {
this.setState({ deleteFiles: value });
}
onAddNetImportExclusionChange = ({ value }) => {
this.setState({ addNetImportExclusion: value });
onAddImportExclusionChange = ({ value }) => {
this.setState({ addImportExclusion: value });
}
onDeleteMovieConfirmed = () => {
const deleteFiles = this.state.deleteFiles;
const addNetImportExclusion = this.state.addNetImportExclusion;
const addImportExclusion = this.state.addImportExclusion;
this.setState({ deleteFiles: false, addNetImportExclusion: false });
this.props.onDeleteSelectedPress(deleteFiles, addNetImportExclusion);
this.setState({ deleteFiles: false, addImportExclusion: false });
this.props.onDeleteSelectedPress(deleteFiles, addImportExclusion);
}
//
@ -55,7 +55,7 @@ class DeleteMovieModalContent extends Component {
} = this.props;
const deleteFiles = this.state.deleteFiles;
const addNetImportExclusion = this.state.addNetImportExclusion;
const addImportExclusion = this.state.addImportExclusion;
return (
<ModalContent onModalClose={onModalClose}>
@ -83,11 +83,11 @@ class DeleteMovieModalContent extends Component {
<FormInputGroup
type={inputTypes.CHECK}
name="addNetImportExclusion"
value={addNetImportExclusion}
helpText={translate('AddNetImportExclusionHelpText')}
name="addImportExclusion"
value={addImportExclusion}
helpText={translate('AddImportExclusionHelpText')}
kind={kinds.DANGER}
onChange={this.onAddNetImportExclusionChange}
onChange={this.onAddImportExclusionChange}
/>
</FormGroup>
</div>

@ -31,11 +31,11 @@ function createMapStateToProps() {
function createMapDispatchToProps(dispatch, props) {
return {
onDeleteSelectedPress(deleteFiles, addNetImportExclusion) {
onDeleteSelectedPress(deleteFiles, addImportExclusion) {
dispatch(bulkDeleteMovie({
movieIds: props.movieIds,
deleteFiles,
addNetImportExclusion
addImportExclusion
}));
props.onModalClose();

@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import MonitorToggleButton from 'Components/MonitorToggleButton';
import EditNetImportModalConnector from 'Settings/NetImport/NetImport/EditNetImportModalConnector';
import EditImportListModalConnector from 'Settings/ImportLists/ImportLists/EditImportListModalConnector';
import styles from './MovieCollection.css';
class MovieCollection extends Component {
@ -14,21 +14,21 @@ class MovieCollection extends Component {
this.state = {
hasPosterError: false,
isEditNetImportModalOpen: false
isEditImportListModalOpen: false
};
}
onAddNetImportPress = (monitored) => {
onAddImportListPress = (monitored) => {
if (this.props.collectionList) {
this.props.onMonitorTogglePress(monitored);
} else {
this.props.onMonitorTogglePress(monitored);
this.setState({ isEditNetImportModalOpen: true });
this.setState({ isEditImportListModalOpen: true });
}
}
onEditNetImportModalClose = () => {
this.setState({ isEditNetImportModalOpen: false });
onEditImportListModalClose = () => {
this.setState({ isEditImportListModalOpen: false });
}
render() {
@ -39,7 +39,7 @@ class MovieCollection extends Component {
} = this.props;
const monitored = collectionList !== undefined && collectionList.enabled && collectionList.enableAuto;
const netImportId = collectionList ? collectionList.id : 0;
const importListId = collectionList ? collectionList.id : 0;
return (
<div>
@ -48,14 +48,14 @@ class MovieCollection extends Component {
monitored={monitored}
isSaving={isSaving}
size={15}
onPress={this.onAddNetImportPress}
onPress={this.onAddImportListPress}
/>
{name}
<EditNetImportModalConnector
id={netImportId}
isOpen={this.state.isEditNetImportModalOpen}
onModalClose={this.onEditNetImportModalClose}
onDeleteNetImportPress={this.onDeleteNetImportPress}
<EditImportListModalConnector
id={importListId}
isOpen={this.state.isEditImportListModalOpen}
onModalClose={this.onEditImportListModalClose}
onDeleteImportListPress={this.onDeleteImportListPress}
/>
</div>
);

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { saveNetImport, selectNetImportSchema, setNetImportFieldValue, setNetImportValue } from 'Store/Actions/settingsActions';
import { saveImportList, selectImportListSchema, setImportListFieldValue, setImportListValue } from 'Store/Actions/settingsActions';
import createMovieCollectionListSelector from 'Store/Selectors/createMovieCollectionListSelector';
import createMovieSelector from 'Store/Selectors/createMovieSelector';
import MovieCollection from './MovieCollection';
@ -11,8 +11,8 @@ function createMapStateToProps() {
return createSelector(
createMovieSelector(),
createMovieCollectionListSelector(),
(state) => state.settings.netImports,
(movie, collectionList, netImports) => {
(state) => state.settings.importLists,
(movie, collectionList, importLists) => {
const {
monitored,
qualityProfileId,
@ -24,17 +24,17 @@ function createMapStateToProps() {
monitored,
qualityProfileId,
minimumAvailability,
isSaving: netImports.isSaving
isSaving: importLists.isSaving
};
}
);
}
const mapDispatchToProps = {
selectNetImportSchema,
setNetImportFieldValue,
setNetImportValue,
saveNetImport
selectImportListSchema,
setImportListFieldValue,
setImportListValue,
saveImportList
};
class MovieCollectionConnector extends Component {
@ -44,18 +44,18 @@ class MovieCollectionConnector extends Component {
onMonitorTogglePress = (monitored) => {
if (this.props.collectionList) {
this.props.setNetImportValue({ name: 'enabled', value: monitored });
this.props.setNetImportValue({ name: 'enableAuto', value: monitored });
this.props.saveNetImport({ id: this.props.collectionList.id });
this.props.setImportListValue({ name: 'enabled', value: monitored });
this.props.setImportListValue({ name: 'enableAuto', value: monitored });
this.props.saveImportList({ id: this.props.collectionList.id });
} else {
this.props.selectNetImportSchema({ implementation: 'TMDbCollectionImport', presetName: undefined });
this.props.setNetImportFieldValue({ name: 'collectionId', value: this.props.tmdbId.toString() });
this.props.setNetImportValue({ name: 'enabled', value: true });
this.props.setNetImportValue({ name: 'enableAuto', value: true });
this.props.setNetImportValue({ name: 'name', value: `${this.props.name} - ${this.props.tmdbId}` });
this.props.setNetImportValue({ name: 'qualityProfileId', value: this.props.qualityProfileId });
this.props.setNetImportValue({ name: 'monitored', value: this.props.monitored });
this.props.setNetImportValue({ name: 'minimumAvailability', value: this.props.minimumAvailability });
this.props.selectImportListSchema({ implementation: 'TMDbCollectionImport', presetName: undefined });
this.props.setImportListFieldValue({ name: 'collectionId', value: this.props.tmdbId.toString() });
this.props.setImportListValue({ name: 'enabled', value: true });
this.props.setImportListValue({ name: 'enableAuto', value: true });
this.props.setImportListValue({ name: 'name', value: `${this.props.name} - ${this.props.tmdbId}` });
this.props.setImportListValue({ name: 'qualityProfileId', value: this.props.qualityProfileId });
this.props.setImportListValue({ name: 'monitored', value: this.props.monitored });
this.props.setImportListValue({ name: 'minimumAvailability', value: this.props.minimumAvailability });
}
}
@ -81,10 +81,10 @@ MovieCollectionConnector.propTypes = {
qualityProfileId: PropTypes.number.isRequired,
minimumAvailability: PropTypes.string.isRequired,
isSaving: PropTypes.bool.isRequired,
selectNetImportSchema: PropTypes.func.isRequired,
setNetImportFieldValue: PropTypes.func.isRequired,
setNetImportValue: PropTypes.func.isRequired,
saveNetImport: PropTypes.func.isRequired
selectImportListSchema: PropTypes.func.isRequired,
setImportListFieldValue: PropTypes.func.isRequired,
setImportListValue: PropTypes.func.isRequired,
saveImportList: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(MovieCollectionConnector);

@ -2,16 +2,16 @@ import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import { sizes } from 'Helpers/Props';
import EditNetImportExclusionModalContentConnector from './EditNetImportExclusionModalContentConnector';
import EditImportExclusionModalContentConnector from './EditImportExclusionModalContentConnector';
function EditNetImportExclusionModal({ isOpen, onModalClose, ...otherProps }) {
function EditImportExclusionModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
size={sizes.MEDIUM}
isOpen={isOpen}
onModalClose={onModalClose}
>
<EditNetImportExclusionModalContentConnector
<EditImportExclusionModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
@ -19,9 +19,9 @@ function EditNetImportExclusionModal({ isOpen, onModalClose, ...otherProps }) {
);
}
EditNetImportExclusionModal.propTypes = {
EditImportExclusionModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default EditNetImportExclusionModal;
export default EditImportExclusionModal;

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { clearPendingChanges } from 'Store/Actions/baseActions';
import EditNetImportExclusionModal from './EditNetImportExclusionModal';
import EditImportExclusionModal from './EditImportExclusionModal';
function mapStateToProps() {
return {};
@ -12,13 +12,13 @@ const mapDispatchToProps = {
clearPendingChanges
};
class EditNetImportExclusionModalConnector extends Component {
class EditImportExclusionModalConnector extends Component {
//
// Listeners
onModalClose = () => {
this.props.clearPendingChanges({ section: 'settings.netImportExclusions' });
this.props.clearPendingChanges({ section: 'settings.importExclusions' });
this.props.onModalClose();
}
@ -27,7 +27,7 @@ class EditNetImportExclusionModalConnector extends Component {
render() {
return (
<EditNetImportExclusionModal
<EditImportExclusionModal
{...this.props}
onModalClose={this.onModalClose}
/>
@ -35,9 +35,9 @@ class EditNetImportExclusionModalConnector extends Component {
}
}
EditNetImportExclusionModalConnector.propTypes = {
EditImportExclusionModalConnector.propTypes = {
onModalClose: PropTypes.func.isRequired,
clearPendingChanges: PropTypes.func.isRequired
};
export default connect(mapStateToProps, mapDispatchToProps)(EditNetImportExclusionModalConnector);
export default connect(mapStateToProps, mapDispatchToProps)(EditImportExclusionModalConnector);

@ -13,9 +13,9 @@ import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './EditNetImportExclusionModalContent.css';
import styles from './EditImportExclusionModalContent.css';
function EditNetImportExclusionModalContent(props) {
function EditImportExclusionModalContent(props) {
const {
id,
isFetching,
@ -26,7 +26,7 @@ function EditNetImportExclusionModalContent(props) {
onInputChange,
onSavePress,
onModalClose,
onDeleteNetImportExclusionPress,
onDeleteImportExclusionPress,
...otherProps
} = props;
@ -104,7 +104,7 @@ function EditNetImportExclusionModalContent(props) {
<Button
className={styles.deleteButton}
kind={kinds.DANGER}
onPress={onDeleteNetImportExclusionPress}
onPress={onDeleteImportExclusionPress}
>
{translate('Delete')}
</Button>
@ -128,7 +128,7 @@ function EditNetImportExclusionModalContent(props) {
);
}
EditNetImportExclusionModalContent.propTypes = {
EditImportExclusionModalContent.propTypes = {
id: PropTypes.number,
isFetching: PropTypes.bool.isRequired,
error: PropTypes.object,
@ -138,7 +138,7 @@ EditNetImportExclusionModalContent.propTypes = {
onInputChange: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired,
onDeleteNetImportExclusionPress: PropTypes.func
onDeleteImportExclusionPress: PropTypes.func
};
export default EditNetImportExclusionModalContent;
export default EditImportExclusionModalContent;

@ -3,21 +3,21 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { saveNetImportExclusion, setNetImportExclusionValue } from 'Store/Actions/settingsActions';
import { saveImportExclusion, setImportExclusionValue } from 'Store/Actions/settingsActions';
import selectSettings from 'Store/Selectors/selectSettings';
import EditNetImportExclusionModalContent from './EditNetImportExclusionModalContent';
import EditImportExclusionModalContent from './EditImportExclusionModalContent';
const newNetImportExclusion = {
const newImportExclusion = {
movieTitle: '',
tmdbId: 0,
movieYear: 0
};
function createNetImportExclusionSelector() {
function createImportExclusionSelector() {
return createSelector(
(state, { id }) => id,
(state) => state.settings.netImportExclusions,
(id, netImportExclusions) => {
(state) => state.settings.importExclusions,
(id, importExclusions) => {
const {
isFetching,
error,
@ -25,9 +25,9 @@ function createNetImportExclusionSelector() {
saveError,
pendingChanges,
items
} = netImportExclusions;
} = importExclusions;
const mapping = id ? _.find(items, { id }) : newNetImportExclusion;
const mapping = id ? _.find(items, { id }) : newImportExclusion;
const settings = selectSettings(mapping, pendingChanges, saveError);
return {
@ -45,31 +45,31 @@ function createNetImportExclusionSelector() {
function createMapStateToProps() {
return createSelector(
createNetImportExclusionSelector(),
(netImportExclusion) => {
createImportExclusionSelector(),
(importExclusion) => {
return {
...netImportExclusion
...importExclusion
};
}
);
}
const mapDispatchToProps = {
setNetImportExclusionValue,
saveNetImportExclusion
setImportExclusionValue,
saveImportExclusion
};
class EditNetImportExclusionModalContentConnector extends Component {
class EditImportExclusionModalContentConnector extends Component {
//
// Lifecycle
componentDidMount() {
if (!this.props.id) {
Object.keys(newNetImportExclusion).forEach((name) => {
this.props.setNetImportExclusionValue({
Object.keys(newImportExclusion).forEach((name) => {
this.props.setImportExclusionValue({
name,
value: newNetImportExclusion[name]
value: newImportExclusion[name]
});
});
}
@ -85,11 +85,11 @@ class EditNetImportExclusionModalContentConnector extends Component {
// Listeners
onInputChange = ({ name, value }) => {
this.props.setNetImportExclusionValue({ name, value });
this.props.setImportExclusionValue({ name, value });
}
onSavePress = () => {
this.props.saveNetImportExclusion({ id: this.props.id });
this.props.saveImportExclusion({ id: this.props.id });
}
//
@ -97,7 +97,7 @@ class EditNetImportExclusionModalContentConnector extends Component {
render() {
return (
<EditNetImportExclusionModalContent
<EditImportExclusionModalContent
{...this.props}
onSavePress={this.onSavePress}
onInputChange={this.onInputChange}
@ -106,14 +106,14 @@ class EditNetImportExclusionModalContentConnector extends Component {
}
}
EditNetImportExclusionModalContentConnector.propTypes = {
EditImportExclusionModalContentConnector.propTypes = {
id: PropTypes.number,
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
item: PropTypes.object.isRequired,
setNetImportExclusionValue: PropTypes.func.isRequired,
saveNetImportExclusion: PropTypes.func.isRequired,
setImportExclusionValue: PropTypes.func.isRequired,
saveImportExclusion: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(EditNetImportExclusionModalContentConnector);
export default connect(createMapStateToProps, mapDispatchToProps)(EditImportExclusionModalContentConnector);

@ -1,4 +1,4 @@
.netImportExclusion {
.importExclusion {
display: flex;
align-items: stretch;
margin-bottom: 10px;

@ -6,10 +6,10 @@ import Link from 'Components/Link/Link';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import { icons, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import EditNetImportExclusionModalConnector from './EditNetImportExclusionModalConnector';
import styles from './NetImportExclusion.css';
import EditImportExclusionModalConnector from './EditImportExclusionModalConnector';
import styles from './ImportExclusion.css';
class NetImportExclusion extends Component {
class ImportExclusion extends Component {
//
// Lifecycle
@ -18,35 +18,35 @@ class NetImportExclusion extends Component {
super(props, context);
this.state = {
isEditNetImportExclusionModalOpen: false,
isDeleteNetImportExclusionModalOpen: false
isEditImportExclusionModalOpen: false,
isDeleteImportExclusionModalOpen: false
};
}
//
// Listeners
onEditNetImportExclusionPress = () => {
this.setState({ isEditNetImportExclusionModalOpen: true });
onEditImportExclusionPress = () => {
this.setState({ isEditImportExclusionModalOpen: true });
}
onEditNetImportExclusionModalClose = () => {
this.setState({ isEditNetImportExclusionModalOpen: false });
onEditImportExclusionModalClose = () => {
this.setState({ isEditImportExclusionModalOpen: false });
}
onDeleteNetImportExclusionPress = () => {
onDeleteImportExclusionPress = () => {
this.setState({
isEditNetImportExclusionModalOpen: false,
isDeleteNetImportExclusionModalOpen: true
isEditImportExclusionModalOpen: false,
isDeleteImportExclusionModalOpen: true
});
}
onDeleteNetImportExclusionModalClose = () => {
this.setState({ isDeleteNetImportExclusionModalOpen: false });
onDeleteImportExclusionModalClose = () => {
this.setState({ isDeleteImportExclusionModalOpen: false });
}
onConfirmDeleteNetImportExclusion = () => {
this.props.onConfirmDeleteNetImportExclusion(this.props.id);
onConfirmDeleteImportExclusion = () => {
this.props.onConfirmDeleteImportExclusion(this.props.id);
}
//
@ -63,7 +63,7 @@ class NetImportExclusion extends Component {
return (
<div
className={classNames(
styles.netImportExclusion
styles.importExclusion
)}
>
<div className={styles.tmdbId}>{tmdbId}</div>
@ -72,44 +72,44 @@ class NetImportExclusion extends Component {
<div className={styles.actions}>
<Link
onPress={this.onEditNetImportExclusionPress}
onPress={this.onEditImportExclusionPress}
>
<Icon name={icons.EDIT} />
</Link>
</div>
<EditNetImportExclusionModalConnector
<EditImportExclusionModalConnector
id={id}
isOpen={this.state.isEditNetImportExclusionModalOpen}
onModalClose={this.onEditNetImportExclusionModalClose}
onDeleteNetImportExclusionPress={this.onDeleteNetImportExclusionPress}
isOpen={this.state.isEditImportExclusionModalOpen}
onModalClose={this.onEditImportExclusionModalClose}
onDeleteImportExclusionPress={this.onDeleteImportExclusionPress}
/>
<ConfirmModal
isOpen={this.state.isDeleteNetImportExclusionModalOpen}
isOpen={this.state.isDeleteImportExclusionModalOpen}
kind={kinds.DANGER}
title={translate('DeleteImportListExclusion')}
message={translate('AreYouSureYouWantToDeleteThisImportListExclusion')}
confirmLabel={translate('Delete')}
onConfirm={this.onConfirmDeleteNetImportExclusion}
onCancel={this.onDeleteNetImportExclusionModalClose}
onConfirm={this.onConfirmDeleteImportExclusion}
onCancel={this.onDeleteImportExclusionModalClose}
/>
</div>
);
}
}
NetImportExclusion.propTypes = {
ImportExclusion.propTypes = {
id: PropTypes.number.isRequired,
movieTitle: PropTypes.string.isRequired,
tmdbId: PropTypes.number.isRequired,
movieYear: PropTypes.number.isRequired,
onConfirmDeleteNetImportExclusion: PropTypes.func.isRequired
onConfirmDeleteImportExclusion: PropTypes.func.isRequired
};
NetImportExclusion.defaultProps = {
ImportExclusion.defaultProps = {
// The drag preview will not connect the drag handle.
connectDragSource: (node) => node
};
export default NetImportExclusion;
export default ImportExclusion;

@ -1,4 +1,4 @@
.netImportExclusionsHeader {
.importExclusionsHeader {
display: flex;
margin-bottom: 10px;
font-weight: bold;
@ -13,7 +13,7 @@
flex: 0 0 200px;
}
.addNetImportExclusion {
.addImportExclusion {
display: flex;
justify-content: flex-end;
padding-right: 10px;

@ -6,11 +6,11 @@ import Link from 'Components/Link/Link';
import PageSectionContent from 'Components/Page/PageSectionContent';
import { icons } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import EditNetImportExclusionModalConnector from './EditNetImportExclusionModalConnector';
import NetImportExclusion from './NetImportExclusion';
import styles from './NetImportExclusions.css';
import EditImportExclusionModalConnector from './EditImportExclusionModalConnector';
import ImportExclusion from './ImportExclusion';
import styles from './ImportExclusions.css';
class NetImportExclusions extends Component {
class ImportExclusions extends Component {
//
// Lifecycle
@ -19,19 +19,19 @@ class NetImportExclusions extends Component {
super(props, context);
this.state = {
isAddNetImportExclusionModalOpen: false
isAddImportExclusionModalOpen: false
};
}
//
// Listeners
onAddNetImportExclusionPress = () => {
this.setState({ isAddNetImportExclusionModalOpen: true });
onAddImportExclusionPress = () => {
this.setState({ isAddImportExclusionModalOpen: true });
}
onModalClose = () => {
this.setState({ isAddNetImportExclusionModalOpen: false });
this.setState({ isAddImportExclusionModalOpen: false });
}
//
@ -40,7 +40,7 @@ class NetImportExclusions extends Component {
render() {
const {
items,
onConfirmDeleteNetImportExclusion,
onConfirmDeleteImportExclusion,
...otherProps
} = this.props;
@ -50,7 +50,7 @@ class NetImportExclusions extends Component {
errorMessage={translate('UnableToLoadListExclusions')}
{...otherProps}
>
<div className={styles.netImportExclusionsHeader}>
<div className={styles.importExclusionsHeader}>
<div className={styles.tmdbId}>TMDB Id</div>
<div className={styles.title}>Title</div>
<div className={styles.movieYear}>Year</div>
@ -60,29 +60,29 @@ class NetImportExclusions extends Component {
{
items.map((item, index) => {
return (
<NetImportExclusion
<ImportExclusion
key={item.id}
{...item}
{...otherProps}
index={index}
onConfirmDeleteNetImportExclusion={onConfirmDeleteNetImportExclusion}
onConfirmDeleteImportExclusion={onConfirmDeleteImportExclusion}
/>
);
})
}
</div>
<div className={styles.addNetImportExclusion}>
<div className={styles.addImportExclusion}>
<Link
className={styles.addButton}
onPress={this.onAddNetImportExclusionPress}
onPress={this.onAddImportExclusionPress}
>
<Icon name={icons.ADD} />
</Link>
</div>
<EditNetImportExclusionModalConnector
isOpen={this.state.isAddNetImportExclusionModalOpen}
<EditImportExclusionModalConnector
isOpen={this.state.isAddImportExclusionModalOpen}
onModalClose={this.onModalClose}
/>
@ -92,11 +92,11 @@ class NetImportExclusions extends Component {
}
}
NetImportExclusions.propTypes = {
ImportExclusions.propTypes = {
isFetching: PropTypes.bool.isRequired,
error: PropTypes.object,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
onConfirmDeleteNetImportExclusion: PropTypes.func.isRequired
onConfirmDeleteImportExclusion: PropTypes.func.isRequired
};
export default NetImportExclusions;
export default ImportExclusions;

@ -0,0 +1,59 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { deleteImportExclusion, fetchImportExclusions } from 'Store/Actions/settingsActions';
import ImportExclusions from './ImportExclusions';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.importExclusions,
(importExclusions) => {
return {
...importExclusions
};
}
);
}
const mapDispatchToProps = {
fetchImportExclusions,
deleteImportExclusion
};
class ImportExclusionsConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.props.fetchImportExclusions();
}
//
// Listeners
onConfirmDeleteImportExclusion = (id) => {
this.props.deleteImportExclusion({ id });
}
//
// Render
render() {
return (
<ImportExclusions
{...this.state}
{...this.props}
onConfirmDeleteImportExclusion={this.onConfirmDeleteImportExclusion}
/>
);
}
}
ImportExclusionsConnector.propTypes = {
fetchImportExclusions: PropTypes.func.isRequired,
deleteImportExclusion: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(ImportExclusionsConnector);

@ -7,11 +7,11 @@ import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import { icons } from 'Helpers/Props';
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
import translate from 'Utilities/String/translate';
import NetImportsConnector from './NetImport/NetImportsConnector';
import NetImportExclusionsConnector from './NetImportExclusions/NetImportExclusionsConnector';
import NetImportOptionsConnector from './Options/NetImportOptionsConnector';
import ImportExclusionsConnector from './ImportExclusions/ImportExclusionsConnector';
import ImportListsConnector from './ImportLists/ImportListsConnector';
import ImportListOptionsConnector from './Options/ImportListOptionsConnector';
class NetImportSettings extends Component {
class ImportListSettings extends Component {
//
// Lifecycle
@ -50,7 +50,7 @@ class NetImportSettings extends Component {
render() {
const {
isTestingAll,
dispatchTestAllNetImport
dispatchTestAllImportList
} = this.props;
const {
@ -71,7 +71,7 @@ class NetImportSettings extends Component {
label={translate('TestAllLists')}
iconName={icons.TEST}
isSpinning={isTestingAll}
onPress={dispatchTestAllNetImport}
onPress={dispatchTestAllImportList}
/>
</Fragment>
}
@ -79,14 +79,14 @@ class NetImportSettings extends Component {
/>
<PageContentBody>
<NetImportsConnector />
<ImportListsConnector />
<NetImportOptionsConnector
<ImportListOptionsConnector
onChildMounted={this.onChildMounted}
onChildStateChange={this.onChildStateChange}
/>
<NetImportExclusionsConnector />
<ImportExclusionsConnector />
</PageContentBody>
</PageContent>
@ -94,9 +94,9 @@ class NetImportSettings extends Component {
}
}
NetImportSettings.propTypes = {
ImportListSettings.propTypes = {
isTestingAll: PropTypes.bool.isRequired,
dispatchTestAllNetImport: PropTypes.func.isRequired
dispatchTestAllImportList: PropTypes.func.isRequired
};
export default NetImportSettings;
export default ImportListSettings;

@ -1,11 +1,11 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { testAllNetImport } from 'Store/Actions/settingsActions';
import NetImportSettings from './NetImportSettings';
import { testAllImportList } from 'Store/Actions/settingsActions';
import ImportListSettings from './ImportListSettings';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.netImports.isTestingAll,
(state) => state.settings.importLists.isTestingAll,
(isTestingAll) => {
return {
isTestingAll
@ -15,7 +15,7 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
dispatchTestAllNetImport: testAllNetImport
dispatchTestAllImportList: testAllImportList
};
export default connect(createMapStateToProps, mapDispatchToProps)(NetImportSettings);
export default connect(createMapStateToProps, mapDispatchToProps)(ImportListSettings);

@ -1,4 +1,4 @@
.netImport {
.importList {
composes: card from '~Components/Card.css';
position: relative;

@ -6,20 +6,20 @@ import Menu from 'Components/Menu/Menu';
import MenuContent from 'Components/Menu/MenuContent';
import { sizes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import AddNetImportPresetMenuItem from './AddNetImportPresetMenuItem';
import styles from './AddNetImportItem.css';
import AddImportListPresetMenuItem from './AddImportListPresetMenuItem';
import styles from './AddImportListItem.css';
class AddNetImportItem extends Component {
class AddImportListItem extends Component {
//
// Listeners
onNetImportSelect = () => {
onImportListSelect = () => {
const {
implementation
} = this.props;
this.props.onNetImportSelect({ implementation });
this.props.onImportListSelect({ implementation });
}
//
@ -31,18 +31,18 @@ class AddNetImportItem extends Component {
implementationName,
infoLink,
presets,
onNetImportSelect
onImportListSelect
} = this.props;
const hasPresets = !!presets && !!presets.length;
return (
<div
className={styles.netImport}
className={styles.importList}
>
<Link
className={styles.underlay}
onPress={this.onNetImportSelect}
onPress={this.onImportListSelect}
/>
<div className={styles.overlay}>
@ -56,7 +56,7 @@ class AddNetImportItem extends Component {
<span>
<Button
size={sizes.SMALL}
onPress={this.onNetImportSelect}
onPress={this.onImportListSelect}
>
Custom
</Button>
@ -73,11 +73,11 @@ class AddNetImportItem extends Component {
{
presets.map((preset) => {
return (
<AddNetImportPresetMenuItem
<AddImportListPresetMenuItem
key={preset.name}
name={preset.name}
implementation={implementation}
onPress={onNetImportSelect}
onPress={onImportListSelect}
/>
);
})
@ -100,12 +100,12 @@ class AddNetImportItem extends Component {
}
}
AddNetImportItem.propTypes = {
AddImportListItem.propTypes = {
implementation: PropTypes.string.isRequired,
implementationName: PropTypes.string.isRequired,
infoLink: PropTypes.string.isRequired,
presets: PropTypes.arrayOf(PropTypes.object),
onNetImportSelect: PropTypes.func.isRequired
onImportListSelect: PropTypes.func.isRequired
};
export default AddNetImportItem;
export default AddImportListItem;

@ -1,15 +1,15 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import AddNetImportModalContentConnector from './AddNetImportModalContentConnector';
import AddImportListModalContentConnector from './AddImportListModalContentConnector';
function AddNetImportModal({ isOpen, onModalClose, ...otherProps }) {
function AddImportListModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
isOpen={isOpen}
onModalClose={onModalClose}
>
<AddNetImportModalContentConnector
<AddImportListModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
@ -17,9 +17,9 @@ function AddNetImportModal({ isOpen, onModalClose, ...otherProps }) {
);
}
AddNetImportModal.propTypes = {
AddImportListModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddNetImportModal;
export default AddImportListModal;

@ -11,10 +11,10 @@ import ModalHeader from 'Components/Modal/ModalHeader';
import { kinds } from 'Helpers/Props';
import titleCase from 'Utilities/String/titleCase';
import translate from 'Utilities/String/translate';
import AddNetImportItem from './AddNetImportItem';
import styles from './AddNetImportModalContent.css';
import AddImportListItem from './AddImportListItem';
import styles from './AddImportListModalContent.css';
class AddNetImportModalContent extends Component {
class AddImportListModalContent extends Component {
//
// Render
@ -25,7 +25,7 @@ class AddNetImportModalContent extends Component {
isSchemaPopulated,
schemaError,
listGroups,
onNetImportSelect,
onImportListSelect,
onModalClose
} = this.props;
@ -52,22 +52,22 @@ class AddNetImportModalContent extends Component {
<Alert kind={kinds.INFO}>
<div>Radarr supports any RSS movie lists as well as the one stated below.</div>
<div>For more information on the individual netImports, clink on the info buttons.</div>
<div>For more information on the individual importLists, clink on the info buttons.</div>
</Alert>
{
Object.keys(listGroups).map((key) => {
return (
<FieldSet legend={`${titleCase(key)} List`} key={key}>
<div className={styles.netImports}>
<div className={styles.importLists}>
{
listGroups[key].map((netImport) => {
listGroups[key].map((importList) => {
return (
<AddNetImportItem
key={netImport.implementation}
implementation={netImport.implementation}
{...netImport}
onNetImportSelect={onNetImportSelect}
<AddImportListItem
key={importList.implementation}
implementation={importList.implementation}
{...importList}
onImportListSelect={onImportListSelect}
/>
);
})
@ -92,13 +92,13 @@ class AddNetImportModalContent extends Component {
}
}
AddNetImportModalContent.propTypes = {
AddImportListModalContent.propTypes = {
isSchemaFetching: PropTypes.bool.isRequired,
isSchemaPopulated: PropTypes.bool.isRequired,
schemaError: PropTypes.object,
listGroups: PropTypes.object.isRequired,
onNetImportSelect: PropTypes.func.isRequired,
onImportListSelect: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddNetImportModalContent;
export default AddImportListModalContent;

@ -3,19 +3,19 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { fetchNetImportSchema, selectNetImportSchema } from 'Store/Actions/settingsActions';
import AddNetImportModalContent from './AddNetImportModalContent';
import { fetchImportListSchema, selectImportListSchema } from 'Store/Actions/settingsActions';
import AddImportListModalContent from './AddImportListModalContent';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.netImports,
(netImports) => {
(state) => state.settings.importLists,
(importLists) => {
const {
isSchemaFetching,
isSchemaPopulated,
schemaError,
schema
} = netImports;
} = importLists;
const listGroups = _.chain(schema)
.sortBy((o) => o.listOrder)
@ -33,25 +33,25 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
fetchNetImportSchema,
selectNetImportSchema
fetchImportListSchema,
selectImportListSchema
};
class AddNetImportModalContentConnector extends Component {
class AddImportListModalContentConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.props.fetchNetImportSchema();
this.props.fetchImportListSchema();
}
//
// Listeners
onNetImportSelect = ({ implementation, name }) => {
this.props.selectNetImportSchema({ implementation, presetName: name });
this.props.onModalClose({ netImportSelected: true });
onImportListSelect = ({ implementation, name }) => {
this.props.selectImportListSchema({ implementation, presetName: name });
this.props.onModalClose({ importListSelected: true });
}
//
@ -59,18 +59,18 @@ class AddNetImportModalContentConnector extends Component {
render() {
return (
<AddNetImportModalContent
<AddImportListModalContent
{...this.props}
onNetImportSelect={this.onNetImportSelect}
onImportListSelect={this.onImportListSelect}
/>
);
}
}
AddNetImportModalContentConnector.propTypes = {
fetchNetImportSchema: PropTypes.func.isRequired,
selectNetImportSchema: PropTypes.func.isRequired,
AddImportListModalContentConnector.propTypes = {
fetchImportListSchema: PropTypes.func.isRequired,
selectImportListSchema: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AddNetImportModalContentConnector);
export default connect(createMapStateToProps, mapDispatchToProps)(AddImportListModalContentConnector);

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import MenuItem from 'Components/Menu/MenuItem';
class AddNetImportPresetMenuItem extends Component {
class AddImportListPresetMenuItem extends Component {
//
// Listeners
@ -40,10 +40,10 @@ class AddNetImportPresetMenuItem extends Component {
}
}
AddNetImportPresetMenuItem.propTypes = {
AddImportListPresetMenuItem.propTypes = {
name: PropTypes.string.isRequired,
implementation: PropTypes.string.isRequired,
onPress: PropTypes.func.isRequired
};
export default AddNetImportPresetMenuItem;
export default AddImportListPresetMenuItem;

@ -2,16 +2,16 @@ import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import { sizes } from 'Helpers/Props';
import EditNetImportModalContentConnector from './EditNetImportModalContentConnector';
import EditImportListModalContentConnector from './EditImportListModalContentConnector';
function EditNetImportModal({ isOpen, onModalClose, ...otherProps }) {
function EditImportListModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
size={sizes.MEDIUM}
isOpen={isOpen}
onModalClose={onModalClose}
>
<EditNetImportModalContentConnector
<EditImportListModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
@ -19,9 +19,9 @@ function EditNetImportModal({ isOpen, onModalClose, ...otherProps }) {
);
}
EditNetImportModal.propTypes = {
EditImportListModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default EditNetImportModal;
export default EditImportListModal;

@ -0,0 +1,65 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { clearPendingChanges } from 'Store/Actions/baseActions';
import { cancelSaveImportList, cancelTestImportList } from 'Store/Actions/settingsActions';
import EditImportListModal from './EditImportListModal';
function createMapDispatchToProps(dispatch, props) {
const section = 'settings.importLists';
return {
dispatchClearPendingChanges() {
dispatch(clearPendingChanges({ section }));
},
dispatchCancelTestImportList() {
dispatch(cancelTestImportList({ section }));
},
dispatchCancelSaveImportList() {
dispatch(cancelSaveImportList({ section }));
}
};
}
class EditImportListModalConnector extends Component {
//
// Listeners
onModalClose = () => {
this.props.dispatchClearPendingChanges();
this.props.dispatchCancelTestImportList();
this.props.dispatchCancelSaveImportList();
this.props.onModalClose();
}
//
// Render
render() {
const {
dispatchClearPendingChanges,
dispatchCancelTestImportList,
dispatchCancelSaveImportList,
...otherProps
} = this.props;
return (
<EditImportListModal
{...otherProps}
onModalClose={this.onModalClose}
/>
);
}
}
EditImportListModalConnector.propTypes = {
onModalClose: PropTypes.func.isRequired,
dispatchClearPendingChanges: PropTypes.func.isRequired,
dispatchCancelTestImportList: PropTypes.func.isRequired,
dispatchCancelSaveImportList: PropTypes.func.isRequired
};
export default connect(null, createMapDispatchToProps)(EditImportListModalConnector);

@ -14,9 +14,9 @@ import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './EditNetImportModalContent.css';
import styles from './EditImportListModalContent.css';
function EditNetImportModalContent(props) {
function EditImportListModalContent(props) {
const {
advancedSettings,
isFetching,
@ -30,7 +30,7 @@ function EditNetImportModalContent(props) {
onModalClose,
onSavePress,
onTestPress,
onDeleteNetImportPress,
onDeleteImportListPress,
...otherProps
} = props;
@ -44,6 +44,7 @@ function EditNetImportModalContent(props) {
minimumAvailability,
qualityProfileId,
rootFolderPath,
searchOnAdd,
tags,
fields
} = item;
@ -117,6 +118,21 @@ function EditNetImportModalContent(props) {
/>
</FormGroup>
{
shouldMonitor &&
<FormGroup>
<FormLabel>Search on Add</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="searchOnAdd"
helpText="Search for movies on this list when added to Radarr"
{...searchOnAdd}
onChange={onInputChange}
/>
</FormGroup>
}
<FormGroup>
<FormLabel>{translate('MinimumAvailability')}</FormLabel>
<FormInputGroup
@ -167,7 +183,7 @@ function EditNetImportModalContent(props) {
<ProviderFieldFormGroup
key={field.name}
advancedSettings={advancedSettings}
provider="netImport"
provider="importList"
providerData={item}
{...field}
onChange={onFieldChange}
@ -185,7 +201,7 @@ function EditNetImportModalContent(props) {
<Button
className={styles.deleteButton}
kind={kinds.DANGER}
onPress={onDeleteNetImportPress}
onPress={onDeleteImportListPress}
>
{translate('Delete')}
</Button>
@ -217,7 +233,7 @@ function EditNetImportModalContent(props) {
);
}
EditNetImportModalContent.propTypes = {
EditImportListModalContent.propTypes = {
advancedSettings: PropTypes.bool.isRequired,
isFetching: PropTypes.bool.isRequired,
error: PropTypes.object,
@ -230,7 +246,7 @@ EditNetImportModalContent.propTypes = {
onModalClose: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
onTestPress: PropTypes.func.isRequired,
onDeleteNetImportPress: PropTypes.func
onDeleteImportListPress: PropTypes.func
};
export default EditNetImportModalContent;
export default EditImportListModalContent;

@ -2,31 +2,31 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { saveNetImport, setNetImportFieldValue, setNetImportValue, testNetImport } from 'Store/Actions/settingsActions';
import { saveImportList, setImportListFieldValue, setImportListValue, testImportList } from 'Store/Actions/settingsActions';
import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
import EditNetImportModalContent from './EditNetImportModalContent';
import EditImportListModalContent from './EditImportListModalContent';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.advancedSettings,
createProviderSettingsSelector('netImports'),
(advancedSettings, netImport) => {
createProviderSettingsSelector('importLists'),
(advancedSettings, importList) => {
return {
advancedSettings,
...netImport
...importList
};
}
);
}
const mapDispatchToProps = {
setNetImportValue,
setNetImportFieldValue,
saveNetImport,
testNetImport
setImportListValue,
setImportListFieldValue,
saveImportList,
testImportList
};
class EditNetImportModalContentConnector extends Component {
class EditImportListModalContentConnector extends Component {
//
// Lifecycle
@ -41,19 +41,19 @@ class EditNetImportModalContentConnector extends Component {
// Listeners
onInputChange = ({ name, value }) => {
this.props.setNetImportValue({ name, value });
this.props.setImportListValue({ name, value });
}
onFieldChange = ({ name, value }) => {
this.props.setNetImportFieldValue({ name, value });
this.props.setImportListFieldValue({ name, value });
}
onSavePress = () => {
this.props.saveNetImport({ id: this.props.id });
this.props.saveImportList({ id: this.props.id });
}
onTestPress = () => {
this.props.testNetImport({ id: this.props.id });
this.props.testImportList({ id: this.props.id });
}
//
@ -61,7 +61,7 @@ class EditNetImportModalContentConnector extends Component {
render() {
return (
<EditNetImportModalContent
<EditImportListModalContent
{...this.props}
onSavePress={this.onSavePress}
onTestPress={this.onTestPress}
@ -72,17 +72,17 @@ class EditNetImportModalContentConnector extends Component {
}
}
EditNetImportModalContentConnector.propTypes = {
EditImportListModalContentConnector.propTypes = {
id: PropTypes.number,
isFetching: PropTypes.bool.isRequired,
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
item: PropTypes.object.isRequired,
setNetImportValue: PropTypes.func.isRequired,
setNetImportFieldValue: PropTypes.func.isRequired,
saveNetImport: PropTypes.func.isRequired,
testNetImport: PropTypes.func.isRequired,
setImportListValue: PropTypes.func.isRequired,
setImportListFieldValue: PropTypes.func.isRequired,
saveImportList: PropTypes.func.isRequired,
testImportList: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(EditNetImportModalContentConnector);
export default connect(createMapStateToProps, mapDispatchToProps)(EditImportListModalContentConnector);

@ -1,4 +1,4 @@
.netImport {
.importList {
composes: card from '~Components/Card.css';
width: 290px;

@ -5,10 +5,10 @@ import Label from 'Components/Label';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import { kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import EditNetImportModalConnector from './EditNetImportModalConnector';
import styles from './NetImport.css';
import EditImportListModalConnector from './EditImportListModalConnector';
import styles from './ImportList.css';
class NetImport extends Component {
class ImportList extends Component {
//
// Lifecycle
@ -17,35 +17,35 @@ class NetImport extends Component {
super(props, context);
this.state = {
isEditNetImportModalOpen: false,
isDeleteNetImportModalOpen: false
isEditImportListModalOpen: false,
isDeleteImportListModalOpen: false
};
}
//
// Listeners
onEditNetImportPress = () => {
this.setState({ isEditNetImportModalOpen: true });
onEditImportListPress = () => {
this.setState({ isEditImportListModalOpen: true });
}
onEditNetImportModalClose = () => {
this.setState({ isEditNetImportModalOpen: false });
onEditImportListModalClose = () => {
this.setState({ isEditImportListModalOpen: false });
}
onDeleteNetImportPress = () => {
onDeleteImportListPress = () => {
this.setState({
isEditNetImportModalOpen: false,
isDeleteNetImportModalOpen: true
isEditImportListModalOpen: false,
isDeleteImportListModalOpen: true
});
}
onDeleteNetImportModalClose= () => {
this.setState({ isDeleteNetImportModalOpen: false });
onDeleteImportListModalClose= () => {
this.setState({ isDeleteImportListModalOpen: false });
}
onConfirmDeleteNetImport = () => {
this.props.onConfirmDeleteNetImport(this.props.id);
onConfirmDeleteImportList = () => {
this.props.onConfirmDeleteImportList(this.props.id);
}
//
@ -61,9 +61,9 @@ class NetImport extends Component {
return (
<Card
className={styles.netImport}
className={styles.importList}
overlayContent={true}
onPress={this.onEditNetImportPress}
onPress={this.onEditImportListPress}
>
<div className={styles.name}>
{name}
@ -96,33 +96,33 @@ class NetImport extends Component {
}
</div>
<EditNetImportModalConnector
<EditImportListModalConnector
id={id}
isOpen={this.state.isEditNetImportModalOpen}
onModalClose={this.onEditNetImportModalClose}
onDeleteNetImportPress={this.onDeleteNetImportPress}
isOpen={this.state.isEditImportListModalOpen}
onModalClose={this.onEditImportListModalClose}
onDeleteImportListPress={this.onDeleteImportListPress}
/>
<ConfirmModal
isOpen={this.state.isDeleteNetImportModalOpen}
isOpen={this.state.isDeleteImportListModalOpen}
kind={kinds.DANGER}
title={translate('DeleteList')}
message={`Are you sure you want to delete the list '${name}'?`}
confirmLabel={translate('Delete')}
onConfirm={this.onConfirmDeleteNetImport}
onCancel={this.onDeleteNetImportModalClose}
onConfirm={this.onConfirmDeleteImportList}
onCancel={this.onDeleteImportListModalClose}
/>
</Card>
);
}
}
NetImport.propTypes = {
ImportList.propTypes = {
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
enabled: PropTypes.bool.isRequired,
enableAuto: PropTypes.bool.isRequired,
onConfirmDeleteNetImport: PropTypes.func.isRequired
onConfirmDeleteImportList: PropTypes.func.isRequired
};
export default NetImport;
export default ImportList;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save