mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-20 13:33:34 -07:00
New: Import List Exclusions (#608)
* New: Import List Exclusions * Fixed: ImportExclusion ForeignId Checks, Unique. RefreshArtist Duplicate * Fixed: Copy/Paste typos
This commit is contained in:
parent
b9cc94aa46
commit
42c16c227e
35 changed files with 1160 additions and 20 deletions
|
@ -22,7 +22,8 @@ class DeleteArtistModalContent extends Component {
|
|||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
deleteFiles: false
|
||||
deleteFiles: false,
|
||||
addImportListExclusion: false
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -33,11 +34,17 @@ class DeleteArtistModalContent extends Component {
|
|||
this.setState({ deleteFiles: value });
|
||||
}
|
||||
|
||||
onAddImportListExclusionChange = ({ value }) => {
|
||||
this.setState({ addImportListExclusion: value });
|
||||
}
|
||||
|
||||
onDeleteArtistConfirmed = () => {
|
||||
const deleteFiles = this.state.deleteFiles;
|
||||
const addImportListExclusion = this.state.addImportListExclusion;
|
||||
|
||||
this.setState({ deleteFiles: false });
|
||||
this.props.onDeletePress(deleteFiles);
|
||||
this.setState({ addImportListExclusion: false });
|
||||
this.props.onDeletePress(deleteFiles, addImportListExclusion);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -57,6 +64,8 @@ class DeleteArtistModalContent extends Component {
|
|||
} = statistics;
|
||||
|
||||
const deleteFiles = this.state.deleteFiles;
|
||||
const addImportListExclusion = this.state.addImportListExclusion;
|
||||
|
||||
let deleteFilesLabel = `Delete ${trackFileCount} Track Files`;
|
||||
let deleteFilesHelpText = 'Delete the track files and artist folder';
|
||||
|
||||
|
@ -96,6 +105,19 @@ class DeleteArtistModalContent extends Component {
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Add List Exclusion</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="addImportListExclusion"
|
||||
value={addImportListExclusion}
|
||||
helpText="Prevent artist from being added to Lidarr by Import lists"
|
||||
kind={kinds.DANGER}
|
||||
onChange={this.onAddImportListExclusionChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
deleteFiles &&
|
||||
<div className={styles.deleteFilesMessage}>
|
||||
|
|
|
@ -24,10 +24,11 @@ class DeleteArtistModalContentConnector extends Component {
|
|||
//
|
||||
// Listeners
|
||||
|
||||
onDeletePress = (deleteFiles) => {
|
||||
onDeletePress = (deleteFiles, addImportListExclusion) => {
|
||||
this.props.deleteArtist({
|
||||
id: this.props.artistId,
|
||||
deleteFiles
|
||||
deleteFiles,
|
||||
addImportListExclusion
|
||||
});
|
||||
|
||||
this.props.onModalClose(true);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import EditImportListExclusionModalContentConnector from './EditImportListExclusionModalContentConnector';
|
||||
|
||||
function EditImportListExclusionModal({ isOpen, onModalClose, ...otherProps }) {
|
||||
return (
|
||||
<Modal
|
||||
size={sizes.MEDIUM}
|
||||
isOpen={isOpen}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<EditImportListExclusionModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
EditImportListExclusionModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EditImportListExclusionModal;
|
|
@ -0,0 +1,43 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||
import EditImportListExclusionModal from './EditImportListExclusionModal';
|
||||
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
clearPendingChanges
|
||||
};
|
||||
|
||||
class EditImportListExclusionModalConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onModalClose = () => {
|
||||
this.props.clearPendingChanges({ section: 'settings.importListExclusions' });
|
||||
this.props.onModalClose();
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditImportListExclusionModal
|
||||
{...this.props}
|
||||
onModalClose={this.onModalClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditImportListExclusionModalConnector.propTypes = {
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
clearPendingChanges: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(EditImportListExclusionModalConnector);
|
|
@ -0,0 +1,11 @@
|
|||
.body {
|
||||
composes: modalBody from 'Components/Modal/ModalBody.css';
|
||||
|
||||
flex: 1 1 430px;
|
||||
}
|
||||
|
||||
.deleteButton {
|
||||
composes: button from 'Components/Link/Button.css';
|
||||
|
||||
margin-right: auto;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import { stringSettingShape } from 'Helpers/Props/Shapes/settingShape';
|
||||
import Button from 'Components/Link/Button';
|
||||
import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import styles from './EditImportListExclusionModalContent.css';
|
||||
|
||||
function EditImportListExclusionModalContent(props) {
|
||||
const {
|
||||
id,
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
item,
|
||||
onInputChange,
|
||||
onSavePress,
|
||||
onModalClose,
|
||||
onDeleteImportListExclusionPress,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const {
|
||||
artistName,
|
||||
foreignId
|
||||
} = item;
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{id ? 'Edit Import List Exclusion' : 'Add Import List Exclusion'}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody className={styles.body}>
|
||||
{
|
||||
isFetching &&
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>Unable to add a new import list exclusion, please try again.</div>
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && !error &&
|
||||
<Form
|
||||
{...otherProps}
|
||||
>
|
||||
<FormGroup>
|
||||
<FormLabel>Artist Name</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="artistName"
|
||||
helpText="The name of the artist to exclude (can be anything meaningful)"
|
||||
{...artistName}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Musicbrainz Id</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="foreignId"
|
||||
helpText="The Musicbrainz Id of the artist to exclude"
|
||||
{...foreignId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
{
|
||||
id &&
|
||||
<Button
|
||||
className={styles.deleteButton}
|
||||
kind={kinds.DANGER}
|
||||
onPress={onDeleteImportListExclusionPress}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
}
|
||||
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<SpinnerErrorButton
|
||||
isSpinning={isSaving}
|
||||
error={saveError}
|
||||
onPress={onSavePress}
|
||||
>
|
||||
Save
|
||||
</SpinnerErrorButton>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
|
||||
const ImportListExclusionShape = {
|
||||
artistName: PropTypes.shape(stringSettingShape).isRequired,
|
||||
foreignId: PropTypes.shape(stringSettingShape).isRequired
|
||||
};
|
||||
|
||||
EditImportListExclusionModalContent.propTypes = {
|
||||
id: PropTypes.number,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
item: PropTypes.shape(ImportListExclusionShape).isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onSavePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
onDeleteImportListExclusionPress: PropTypes.func
|
||||
};
|
||||
|
||||
export default EditImportListExclusionModalContent;
|
|
@ -0,0 +1,118 @@
|
|||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import selectSettings from 'Store/Selectors/selectSettings';
|
||||
import { setImportListExclusionValue, saveImportListExclusion } from 'Store/Actions/settingsActions';
|
||||
import EditImportListExclusionModalContent from './EditImportListExclusionModalContent';
|
||||
|
||||
const newImportListExclusion = {
|
||||
artistName: '',
|
||||
foreignId: ''
|
||||
};
|
||||
|
||||
function createImportListExclusionSelector() {
|
||||
return createSelector(
|
||||
(state, { id }) => id,
|
||||
(state) => state.settings.importListExclusions,
|
||||
(id, importListExclusions) => {
|
||||
const {
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
pendingChanges,
|
||||
items
|
||||
} = importListExclusions;
|
||||
|
||||
const mapping = id ? _.find(items, { id }) : newImportListExclusion;
|
||||
const settings = selectSettings(mapping, pendingChanges, saveError);
|
||||
|
||||
return {
|
||||
id,
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
item: settings.settings,
|
||||
...settings
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createImportListExclusionSelector(),
|
||||
(importListExclusion) => {
|
||||
return {
|
||||
...importListExclusion
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setImportListExclusionValue,
|
||||
saveImportListExclusion
|
||||
};
|
||||
|
||||
class EditImportListExclusionModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.id) {
|
||||
Object.keys(newImportListExclusion).forEach((name) => {
|
||||
this.props.setImportListExclusionValue({
|
||||
name,
|
||||
value: newImportListExclusion[name]
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
|
||||
this.props.onModalClose();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.props.setImportListExclusionValue({ name, value });
|
||||
}
|
||||
|
||||
onSavePress = () => {
|
||||
this.props.saveImportListExclusion({ id: this.props.id });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditImportListExclusionModalContent
|
||||
{...this.props}
|
||||
onSavePress={this.onSavePress}
|
||||
onInputChange={this.onInputChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditImportListExclusionModalContentConnector.propTypes = {
|
||||
id: PropTypes.number,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
item: PropTypes.object.isRequired,
|
||||
setImportListExclusionValue: PropTypes.func.isRequired,
|
||||
saveImportListExclusion: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(EditImportListExclusionModalContentConnector);
|
|
@ -0,0 +1,23 @@
|
|||
.importListExclusion {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
margin-bottom: 10px;
|
||||
height: 30px;
|
||||
border-bottom: 1px solid $borderColor;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.artistName {
|
||||
flex: 0 0 300px;
|
||||
}
|
||||
|
||||
.foreignId {
|
||||
flex: 0 0 400px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 1 0 auto;
|
||||
padding-right: 10px;
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector';
|
||||
import styles from './ImportListExclusion.css';
|
||||
|
||||
class ImportListExclusion extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isEditImportListExclusionModalOpen: false,
|
||||
isDeleteImportListExclusionModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onEditImportListExclusionPress = () => {
|
||||
this.setState({ isEditImportListExclusionModalOpen: true });
|
||||
}
|
||||
|
||||
onEditImportListExclusionModalClose = () => {
|
||||
this.setState({ isEditImportListExclusionModalOpen: false });
|
||||
}
|
||||
|
||||
onDeleteImportListExclusionPress = () => {
|
||||
this.setState({
|
||||
isEditImportListExclusionModalOpen: false,
|
||||
isDeleteImportListExclusionModalOpen: true
|
||||
});
|
||||
}
|
||||
|
||||
onDeleteImportListExclusionModalClose = () => {
|
||||
this.setState({ isDeleteImportListExclusionModalOpen: false });
|
||||
}
|
||||
|
||||
onConfirmDeleteImportListExclusion = () => {
|
||||
this.props.onConfirmDeleteImportListExclusion(this.props.id);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
id,
|
||||
artistName,
|
||||
foreignId
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.importListExclusion,
|
||||
)}
|
||||
>
|
||||
<div className={styles.artistName}>{artistName}</div>
|
||||
<div className={styles.foreignId}>{foreignId}</div>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<Link
|
||||
onPress={this.onEditImportListExclusionPress}
|
||||
>
|
||||
<Icon name={icons.EDIT} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<EditImportListExclusionModalConnector
|
||||
id={id}
|
||||
isOpen={this.state.isEditImportListExclusionModalOpen}
|
||||
onModalClose={this.onEditImportListExclusionModalClose}
|
||||
onDeleteImportListExclusionPress={this.onDeleteImportListExclusionPress}
|
||||
/>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isDeleteImportListExclusionModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title="Delete Import List Exclusion"
|
||||
message="Are you sure you want to delete this import list exclusion?"
|
||||
confirmLabel="Delete"
|
||||
onConfirm={this.onConfirmDeleteImportListExclusion}
|
||||
onCancel={this.onDeleteImportListExclusionModalClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportListExclusion.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
artistName: PropTypes.string.isRequired,
|
||||
foreignId: PropTypes.string.isRequired,
|
||||
onConfirmDeleteImportListExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
ImportListExclusion.defaultProps = {
|
||||
// The drag preview will not connect the drag handle.
|
||||
connectDragSource: (node) => node
|
||||
};
|
||||
|
||||
export default ImportListExclusion;
|
|
@ -0,0 +1,23 @@
|
|||
.importListExclusionsHeader {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.host {
|
||||
flex: 0 0 300px;
|
||||
}
|
||||
|
||||
.path {
|
||||
flex: 0 0 400px;
|
||||
}
|
||||
|
||||
.addImportListExclusion {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.addButton {
|
||||
text-align: center;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import ImportListExclusion from './ImportListExclusion';
|
||||
import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector';
|
||||
import styles from './ImportListExclusions.css';
|
||||
|
||||
class ImportListExclusions extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isAddImportListExclusionModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onAddImportListExclusionPress = () => {
|
||||
this.setState({ isAddImportListExclusionModalOpen: true });
|
||||
}
|
||||
|
||||
onModalClose = () => {
|
||||
this.setState({ isAddImportListExclusionModalOpen: false });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
items,
|
||||
onConfirmDeleteImportListExclusion,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldSet legend="Import List Exclusions">
|
||||
<PageSectionContent
|
||||
errorMessage="Unable to load Import List Exclusions"
|
||||
{...otherProps}
|
||||
>
|
||||
<div className={styles.importListExclusionsHeader}>
|
||||
<div className={styles.host}>Name</div>
|
||||
<div className={styles.path}>Foreign Id</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{
|
||||
items.map((item, index) => {
|
||||
return (
|
||||
<ImportListExclusion
|
||||
key={item.id}
|
||||
{...item}
|
||||
{...otherProps}
|
||||
index={index}
|
||||
onConfirmDeleteImportListExclusion={onConfirmDeleteImportListExclusion}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={styles.addImportListExclusion}>
|
||||
<Link
|
||||
className={styles.addButton}
|
||||
onPress={this.onAddImportListExclusionPress}
|
||||
>
|
||||
<Icon name={icons.ADD} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<EditImportListExclusionModalConnector
|
||||
isOpen={this.state.isAddImportListExclusionModalOpen}
|
||||
onModalClose={this.onModalClose}
|
||||
/>
|
||||
|
||||
</PageSectionContent>
|
||||
</FieldSet>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportListExclusions.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onConfirmDeleteImportListExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportListExclusions;
|
|
@ -0,0 +1,59 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { fetchImportListExclusions, deleteImportListExclusion } from 'Store/Actions/settingsActions';
|
||||
import ImportListExclusions from './ImportListExclusions';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.settings.importListExclusions,
|
||||
(importListExclusions) => {
|
||||
return {
|
||||
...importListExclusions
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
fetchImportListExclusions,
|
||||
deleteImportListExclusion
|
||||
};
|
||||
|
||||
class ImportListExclusionsConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchImportListExclusions();
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onConfirmDeleteImportListExclusion = (id) => {
|
||||
this.props.deleteImportListExclusion({ id });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ImportListExclusions
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
onConfirmDeleteImportListExclusion={this.onConfirmDeleteImportListExclusion}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportListExclusionsConnector.propTypes = {
|
||||
fetchImportListExclusions: PropTypes.func.isRequired,
|
||||
deleteImportListExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportListExclusionsConnector);
|
|
@ -7,6 +7,7 @@ import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
|||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
|
||||
import ImportListsConnector from './ImportLists/ImportListsConnector';
|
||||
import ImportListsExclusionsConnector from './ImportListExclusions/ImportListExclusionsConnector';
|
||||
|
||||
class ImportListSettings extends Component {
|
||||
|
||||
|
@ -74,6 +75,7 @@ class ImportListSettings extends Component {
|
|||
|
||||
<PageContentBodyConnector>
|
||||
<ImportListsConnector />
|
||||
<ImportListsExclusionsConnector />
|
||||
</PageContentBodyConnector>
|
||||
</PageContent>
|
||||
);
|
||||
|
|
69
frontend/src/Store/Actions/Settings/importListExclusions.js
Normal file
69
frontend/src/Store/Actions/Settings/importListExclusions.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
import { createAction } from 'redux-actions';
|
||||
import { createThunk } from 'Store/thunks';
|
||||
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
||||
const section = 'settings.importListExclusions';
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
export const FETCH_IMPORT_LIST_EXCLUSIONS = 'settings/importListExclusions/fetchImportListExclusions';
|
||||
export const SAVE_IMPORT_LIST_EXCLUSION = 'settings/importListExclusions/saveImportListExclusion';
|
||||
export const DELETE_IMPORT_LIST_EXCLUSION = 'settings/importListExclusions/deleteImportListExclusion';
|
||||
export const SET_IMPORT_LIST_EXCLUSION_VALUE = 'settings/importListExclusions/setImportListExclusionValue';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
||||
export const fetchImportListExclusions = createThunk(FETCH_IMPORT_LIST_EXCLUSIONS);
|
||||
export const saveImportListExclusion = createThunk(SAVE_IMPORT_LIST_EXCLUSION);
|
||||
export const deleteImportListExclusion = createThunk(DELETE_IMPORT_LIST_EXCLUSION);
|
||||
|
||||
export const setImportListExclusionValue = createAction(SET_IMPORT_LIST_EXCLUSION_VALUE, (payload) => {
|
||||
return {
|
||||
section,
|
||||
...payload
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// Details
|
||||
|
||||
export default {
|
||||
|
||||
//
|
||||
// State
|
||||
|
||||
defaultState: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: [],
|
||||
isSaving: false,
|
||||
saveError: null,
|
||||
pendingChanges: {}
|
||||
},
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
actionHandlers: {
|
||||
[FETCH_IMPORT_LIST_EXCLUSIONS]: createFetchHandler(section, '/importlistexclusion'),
|
||||
[SAVE_IMPORT_LIST_EXCLUSION]: createSaveProviderHandler(section, '/importlistexclusion'),
|
||||
[DELETE_IMPORT_LIST_EXCLUSION]: createRemoveItemHandler(section, '/importlistexclusion')
|
||||
},
|
||||
|
||||
//
|
||||
// Reducers
|
||||
|
||||
reducers: {
|
||||
[SET_IMPORT_LIST_EXCLUSION_VALUE]: createSetSettingValueReducer(section)
|
||||
}
|
||||
|
||||
};
|
|
@ -186,7 +186,8 @@ export const deleteArtist = createThunk(DELETE_ARTIST, (payload) => {
|
|||
return {
|
||||
...payload,
|
||||
queryParams: {
|
||||
deleteFiles: payload.deleteFiles
|
||||
deleteFiles: payload.deleteFiles,
|
||||
addImportListExclusion: payload.addImportListExclusion
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@ import indexerOptions from './Settings/indexerOptions';
|
|||
import indexers from './Settings/indexers';
|
||||
import languageProfiles from './Settings/languageProfiles';
|
||||
import importLists from './Settings/importLists';
|
||||
import importListExclusions from './Settings/importListExclusions';
|
||||
import metadataProfiles from './Settings/metadataProfiles';
|
||||
import mediaManagement from './Settings/mediaManagement';
|
||||
import metadata from './Settings/metadata';
|
||||
|
@ -27,6 +28,7 @@ export * from './Settings/downloadClients';
|
|||
export * from './Settings/downloadClientOptions';
|
||||
export * from './Settings/general';
|
||||
export * from './Settings/importLists';
|
||||
export * from './Settings/importListExclusions';
|
||||
export * from './Settings/indexerOptions';
|
||||
export * from './Settings/indexers';
|
||||
export * from './Settings/languageProfiles';
|
||||
|
@ -62,6 +64,7 @@ export const defaultState = {
|
|||
indexers: indexers.defaultState,
|
||||
languageProfiles: languageProfiles.defaultState,
|
||||
importLists: importLists.defaultState,
|
||||
importListExclusions: importListExclusions.defaultState,
|
||||
metadataProfiles: metadataProfiles.defaultState,
|
||||
mediaManagement: mediaManagement.defaultState,
|
||||
metadata: metadata.defaultState,
|
||||
|
@ -102,6 +105,7 @@ export const actionHandlers = handleThunks({
|
|||
...indexers.actionHandlers,
|
||||
...languageProfiles.actionHandlers,
|
||||
...importLists.actionHandlers,
|
||||
...importListExclusions.actionHandlers,
|
||||
...metadataProfiles.actionHandlers,
|
||||
...mediaManagement.actionHandlers,
|
||||
...metadata.actionHandlers,
|
||||
|
@ -133,6 +137,7 @@ export const reducers = createHandleActions({
|
|||
...indexers.reducers,
|
||||
...languageProfiles.reducers,
|
||||
...importLists.reducers,
|
||||
...importListExclusions.reducers,
|
||||
...metadataProfiles.reducers,
|
||||
...mediaManagement.reducers,
|
||||
...metadata.reducers,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue