mirror of https://github.com/Radarr/Radarr
parent
f338941cfc
commit
e6f5d535e9
|
@ -4,6 +4,11 @@
|
||||||
width: 290px;
|
width: 290px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nameContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
@add-mixin truncate;
|
@add-mixin truncate;
|
||||||
|
|
||||||
|
@ -12,6 +17,12 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cloneButton {
|
||||||
|
composes: button from '~Components/Link/IconButton.css';
|
||||||
|
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
.enabled {
|
.enabled {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
import Card from 'Components/Card';
|
import Card from 'Components/Card';
|
||||||
import Label from 'Components/Label';
|
import Label from 'Components/Label';
|
||||||
|
import IconButton from 'Components/Link/IconButton';
|
||||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||||
import EditIndexerModalConnector from './EditIndexerModalConnector';
|
import EditIndexerModalConnector from './EditIndexerModalConnector';
|
||||||
import styles from './Indexer.css';
|
import styles from './Indexer.css';
|
||||||
|
@ -47,6 +48,15 @@ class Indexer extends Component {
|
||||||
this.props.onConfirmDeleteIndexer(this.props.id);
|
this.props.onConfirmDeleteIndexer(this.props.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCloneIndexerPress = () => {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
onCloneIndexerPress
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
onCloneIndexerPress(id);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
|
@ -67,8 +77,17 @@ class Indexer extends Component {
|
||||||
overlayContent={true}
|
overlayContent={true}
|
||||||
onPress={this.onEditIndexerPress}
|
onPress={this.onEditIndexerPress}
|
||||||
>
|
>
|
||||||
<div className={styles.name}>
|
<div className={styles.nameContainer}>
|
||||||
{name}
|
<div className={styles.name}>
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
className={styles.cloneButton}
|
||||||
|
title="Clone Profile"
|
||||||
|
name={icons.CLONE}
|
||||||
|
onPress={this.onCloneIndexerPress}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.enabled}>
|
<div className={styles.enabled}>
|
||||||
|
@ -134,6 +153,7 @@ Indexer.propTypes = {
|
||||||
enableInteractiveSearch: PropTypes.bool.isRequired,
|
enableInteractiveSearch: PropTypes.bool.isRequired,
|
||||||
supportsRss: PropTypes.bool.isRequired,
|
supportsRss: PropTypes.bool.isRequired,
|
||||||
supportsSearch: PropTypes.bool.isRequired,
|
supportsSearch: PropTypes.bool.isRequired,
|
||||||
|
onCloneIndexerPress: PropTypes.func.isRequired,
|
||||||
onConfirmDeleteIndexer: PropTypes.func.isRequired
|
onConfirmDeleteIndexer: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,11 @@ class Indexers extends Component {
|
||||||
this.setState({ isAddIndexerModalOpen: true });
|
this.setState({ isAddIndexerModalOpen: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCloneIndexerPress = (id) => {
|
||||||
|
this.props.dispatchCloneIndexer({ id });
|
||||||
|
this.setState({ isEditIndexerModalOpen: true });
|
||||||
|
}
|
||||||
|
|
||||||
onAddIndexerModalClose = ({ indexerSelected = false } = {}) => {
|
onAddIndexerModalClose = ({ indexerSelected = false } = {}) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isAddIndexerModalOpen: false,
|
isAddIndexerModalOpen: false,
|
||||||
|
@ -48,6 +53,7 @@ class Indexers extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
items,
|
items,
|
||||||
|
dispatchCloneIndexer,
|
||||||
onConfirmDeleteIndexer,
|
onConfirmDeleteIndexer,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -70,6 +76,7 @@ class Indexers extends Component {
|
||||||
<Indexer
|
<Indexer
|
||||||
key={item.id}
|
key={item.id}
|
||||||
{...item}
|
{...item}
|
||||||
|
onCloneIndexerPress={this.onCloneIndexerPress}
|
||||||
onConfirmDeleteIndexer={onConfirmDeleteIndexer}
|
onConfirmDeleteIndexer={onConfirmDeleteIndexer}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -108,6 +115,7 @@ Indexers.propTypes = {
|
||||||
isFetching: PropTypes.bool.isRequired,
|
isFetching: PropTypes.bool.isRequired,
|
||||||
error: PropTypes.object,
|
error: PropTypes.object,
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
dispatchCloneIndexer: PropTypes.func.isRequired,
|
||||||
onConfirmDeleteIndexer: PropTypes.func.isRequired
|
onConfirmDeleteIndexer: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import sortByName from 'Utilities/Array/sortByName';
|
import sortByName from 'Utilities/Array/sortByName';
|
||||||
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
||||||
import { fetchIndexers, deleteIndexer } from 'Store/Actions/settingsActions';
|
import { fetchIndexers, deleteIndexer, cloneIndexer } from 'Store/Actions/settingsActions';
|
||||||
import Indexers from './Indexers';
|
import Indexers from './Indexers';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -15,8 +15,9 @@ function createMapStateToProps() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
fetchIndexers,
|
dispatchFetchIndexers: fetchIndexers,
|
||||||
deleteIndexer
|
dispatchDeleteIndexer: deleteIndexer,
|
||||||
|
dispatchCloneIndexer: cloneIndexer
|
||||||
};
|
};
|
||||||
|
|
||||||
class IndexersConnector extends Component {
|
class IndexersConnector extends Component {
|
||||||
|
@ -25,14 +26,14 @@ class IndexersConnector extends Component {
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.fetchIndexers();
|
this.props.dispatchFetchIndexers();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onConfirmDeleteIndexer = (id) => {
|
onConfirmDeleteIndexer = (id) => {
|
||||||
this.props.deleteIndexer({ id });
|
this.props.dispatchDeleteIndexer({ id });
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -49,8 +50,9 @@ class IndexersConnector extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexersConnector.propTypes = {
|
IndexersConnector.propTypes = {
|
||||||
fetchIndexers: PropTypes.func.isRequired,
|
dispatchFetchIndexers: PropTypes.func.isRequired,
|
||||||
deleteIndexer: PropTypes.func.isRequired
|
dispatchDeleteIndexer: PropTypes.func.isRequired,
|
||||||
|
dispatchCloneIndexer: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(IndexersConnector);
|
export default connect(createMapStateToProps, mapDispatchToProps)(IndexersConnector);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import { createThunk } from 'Store/thunks';
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
|
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
|
||||||
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
||||||
|
@ -21,6 +23,7 @@ const section = 'settings.indexers';
|
||||||
export const FETCH_INDEXERS = 'settings/indexers/fetchIndexers';
|
export const FETCH_INDEXERS = 'settings/indexers/fetchIndexers';
|
||||||
export const FETCH_INDEXER_SCHEMA = 'settings/indexers/fetchIndexerSchema';
|
export const FETCH_INDEXER_SCHEMA = 'settings/indexers/fetchIndexerSchema';
|
||||||
export const SELECT_INDEXER_SCHEMA = 'settings/indexers/selectIndexerSchema';
|
export const SELECT_INDEXER_SCHEMA = 'settings/indexers/selectIndexerSchema';
|
||||||
|
export const CLONE_INDEXER = 'settings/indexers/cloneIndexer';
|
||||||
export const SET_INDEXER_VALUE = 'settings/indexers/setIndexerValue';
|
export const SET_INDEXER_VALUE = 'settings/indexers/setIndexerValue';
|
||||||
export const SET_INDEXER_FIELD_VALUE = 'settings/indexers/setIndexerFieldValue';
|
export const SET_INDEXER_FIELD_VALUE = 'settings/indexers/setIndexerFieldValue';
|
||||||
export const SAVE_INDEXER = 'settings/indexers/saveIndexer';
|
export const SAVE_INDEXER = 'settings/indexers/saveIndexer';
|
||||||
|
@ -36,6 +39,7 @@ export const TEST_ALL_INDEXERS = 'settings/indexers/testAllIndexers';
|
||||||
export const fetchIndexers = createThunk(FETCH_INDEXERS);
|
export const fetchIndexers = createThunk(FETCH_INDEXERS);
|
||||||
export const fetchIndexerSchema = createThunk(FETCH_INDEXER_SCHEMA);
|
export const fetchIndexerSchema = createThunk(FETCH_INDEXER_SCHEMA);
|
||||||
export const selectIndexerSchema = createAction(SELECT_INDEXER_SCHEMA);
|
export const selectIndexerSchema = createAction(SELECT_INDEXER_SCHEMA);
|
||||||
|
export const cloneIndexer = createAction(CLONE_INDEXER);
|
||||||
|
|
||||||
export const saveIndexer = createThunk(SAVE_INDEXER);
|
export const saveIndexer = createThunk(SAVE_INDEXER);
|
||||||
export const cancelSaveIndexer = createThunk(CANCEL_SAVE_INDEXER);
|
export const cancelSaveIndexer = createThunk(CANCEL_SAVE_INDEXER);
|
||||||
|
@ -112,6 +116,30 @@ export default {
|
||||||
|
|
||||||
return selectedSchema;
|
return selectedSchema;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[CLONE_INDEXER]: function(state, { payload }) {
|
||||||
|
const id = payload.id;
|
||||||
|
const newState = getSectionState(state, section);
|
||||||
|
const item = newState.items.find((i) => i.id === id);
|
||||||
|
|
||||||
|
// Use selectedSchema so `createProviderSettingsSelector` works properly
|
||||||
|
const selectedSchema = { ...item };
|
||||||
|
delete selectedSchema.id;
|
||||||
|
delete selectedSchema.name;
|
||||||
|
|
||||||
|
selectedSchema.fields = selectedSchema.fields.map((field) => {
|
||||||
|
return { ...field };
|
||||||
|
});
|
||||||
|
|
||||||
|
newState.selectedSchema = selectedSchema;
|
||||||
|
|
||||||
|
// Set the name in pendingChanges
|
||||||
|
newState.pendingChanges = {
|
||||||
|
name: `${item.name} - Copy`
|
||||||
|
};
|
||||||
|
|
||||||
|
return updateSectionState(state, section, newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue