mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
Fix Delete Indexer from Edit Modal
This commit is contained in:
@@ -2,13 +2,12 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import DeleteMovieModalContentConnector from './DeleteMovieModalContentConnector';
|
||||
import DeleteIndexerModalContentConnector from './DeleteIndexerModalContentConnector';
|
||||
|
||||
function DeleteMovieModal(props) {
|
||||
function DeleteIndexerModal(props) {
|
||||
const {
|
||||
isOpen,
|
||||
onModalClose,
|
||||
previousMovie,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
@@ -18,19 +17,17 @@ function DeleteMovieModal(props) {
|
||||
size={sizes.MEDIUM}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<DeleteMovieModalContentConnector
|
||||
<DeleteIndexerModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
previousMovie={previousMovie}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
DeleteMovieModal.propTypes = {
|
||||
DeleteIndexerModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
previousMovie: PropTypes.string
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default DeleteMovieModal;
|
||||
export default DeleteIndexerModal;
|
88
frontend/src/Indexer/Delete/DeleteIndexerModalContent.js
Normal file
88
frontend/src/Indexer/Delete/DeleteIndexerModalContent.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
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 { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
class DeleteIndexerModalContent extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
deleteFiles: false,
|
||||
addImportExclusion: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onDeleteFilesChange = ({ value }) => {
|
||||
this.setState({ deleteFiles: value });
|
||||
}
|
||||
|
||||
onAddImportExclusionChange = ({ value }) => {
|
||||
this.setState({ addImportExclusion: value });
|
||||
}
|
||||
|
||||
onDeleteMovieConfirmed = () => {
|
||||
const deleteFiles = this.state.deleteFiles;
|
||||
const addImportExclusion = this.state.addImportExclusion;
|
||||
|
||||
this.setState({ deleteFiles: false, addImportExclusion: false });
|
||||
this.props.onDeletePress(deleteFiles, addImportExclusion);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
name,
|
||||
onModalClose
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<ModalContent
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
Delete - {name}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
{`Are you sure you want to delete ${name} from Prowlarr`}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
kind={kinds.DANGER}
|
||||
onPress={this.onDeleteMovieConfirmed}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteIndexerModalContent.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
onDeletePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default DeleteIndexerModalContent;
|
@@ -0,0 +1,57 @@
|
||||
import { push } from 'connected-react-router';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { deleteIndexer } from 'Store/Actions/indexerActions';
|
||||
import createIndexerSelector from 'Store/Selectors/createIndexerSelector';
|
||||
import DeleteIndexerModalContent from './DeleteIndexerModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createIndexerSelector(),
|
||||
(indexer) => {
|
||||
return indexer;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
deleteIndexer,
|
||||
push
|
||||
};
|
||||
|
||||
class DeleteIndexerModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onDeletePress = () => {
|
||||
this.props.deleteIndexer({
|
||||
id: this.props.indexerId
|
||||
});
|
||||
|
||||
this.props.onModalClose(true);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DeleteIndexerModalContent
|
||||
{...this.props}
|
||||
onDeletePress={this.onDeletePress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteIndexerModalContentConnector.propTypes = {
|
||||
indexerId: PropTypes.number.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
deleteIndexer: PropTypes.func.isRequired,
|
||||
push: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(DeleteIndexerModalContentConnector);
|
@@ -1,12 +0,0 @@
|
||||
.pathContainer {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.pathIcon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.deleteFilesMessage {
|
||||
margin-top: 20px;
|
||||
color: $dangerColor;
|
||||
}
|
@@ -1,166 +0,0 @@
|
||||
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 Icon from 'Components/Icon';
|
||||
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 { icons, inputTypes, kinds } from 'Helpers/Props';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './DeleteMovieModalContent.css';
|
||||
|
||||
class DeleteMovieModalContent extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
deleteFiles: false,
|
||||
addImportExclusion: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onDeleteFilesChange = ({ value }) => {
|
||||
this.setState({ deleteFiles: value });
|
||||
}
|
||||
|
||||
onAddImportExclusionChange = ({ value }) => {
|
||||
this.setState({ addImportExclusion: value });
|
||||
}
|
||||
|
||||
onDeleteMovieConfirmed = () => {
|
||||
const deleteFiles = this.state.deleteFiles;
|
||||
const addImportExclusion = this.state.addImportExclusion;
|
||||
|
||||
this.setState({ deleteFiles: false, addImportExclusion: false });
|
||||
this.props.onDeletePress(deleteFiles, addImportExclusion);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
title,
|
||||
path,
|
||||
statistics,
|
||||
onModalClose
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
movieFileCount,
|
||||
sizeOnDisk
|
||||
} = statistics;
|
||||
|
||||
const deleteFiles = this.state.deleteFiles;
|
||||
const addImportExclusion = this.state.addImportExclusion;
|
||||
|
||||
let deleteFilesLabel = `Delete ${movieFileCount} Movie Files`;
|
||||
let deleteFilesHelpText = 'Delete the movie files and movie folder';
|
||||
|
||||
if (movieFileCount === 0) {
|
||||
deleteFilesLabel = 'Delete Movie Folder';
|
||||
deleteFilesHelpText = 'Delete the movie folder and it\'s contents';
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalContent
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
Delete - {title}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<div className={styles.pathContainer}>
|
||||
<Icon
|
||||
className={styles.pathIcon}
|
||||
name={icons.FOLDER}
|
||||
/>
|
||||
|
||||
{path}
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{deleteFilesLabel}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="deleteFiles"
|
||||
value={deleteFiles}
|
||||
helpText={deleteFilesHelpText}
|
||||
kind={kinds.DANGER}
|
||||
onChange={this.onDeleteFilesChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
deleteFiles &&
|
||||
<div className={styles.deleteFilesMessage}>
|
||||
<div>The movie folder <strong>{path}</strong> and all it's content will be deleted.</div>
|
||||
|
||||
{
|
||||
!!movieFileCount &&
|
||||
<div>{movieFileCount} movie files totaling {formatBytes(sizeOnDisk)}</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Add List Exclusion</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="addImportExclusion"
|
||||
value={addImportExclusion}
|
||||
helpText="Prevent movie from being added to Prowlarr by lists"
|
||||
kind={kinds.DANGER}
|
||||
onChange={this.onAddImportExclusionChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
kind={kinds.DANGER}
|
||||
onPress={this.onDeleteMovieConfirmed}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteMovieModalContent.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
statistics: PropTypes.object.isRequired,
|
||||
onDeletePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
DeleteMovieModalContent.defaultProps = {
|
||||
statistics: {
|
||||
movieFileCount: 0
|
||||
}
|
||||
};
|
||||
|
||||
export default DeleteMovieModalContent;
|
@@ -1,64 +0,0 @@
|
||||
import { push } from 'connected-react-router';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { deleteMovie } from 'Store/Actions/movieActions';
|
||||
import createIndexerSelector from 'Store/Selectors/createIndexerSelector';
|
||||
import DeleteMovieModalContent from './DeleteMovieModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createIndexerSelector(),
|
||||
(movie) => {
|
||||
return movie;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
deleteMovie,
|
||||
push
|
||||
};
|
||||
|
||||
class DeleteMovieModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onDeletePress = (deleteFiles, addImportExclusion) => {
|
||||
this.props.deleteMovie({
|
||||
id: this.props.movieId,
|
||||
deleteFiles,
|
||||
addImportExclusion
|
||||
});
|
||||
|
||||
this.props.onModalClose(true);
|
||||
|
||||
if (this.props.nextMovieRelativePath) {
|
||||
this.props.push(window.Prowlarr.urlBase + this.props.nextMovieRelativePath);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DeleteMovieModalContent
|
||||
{...this.props}
|
||||
onDeletePress={this.onDeletePress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteMovieModalContentConnector.propTypes = {
|
||||
movieId: PropTypes.number.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
deleteMovie: PropTypes.func.isRequired,
|
||||
push: PropTypes.func.isRequired,
|
||||
nextMovieRelativePath: PropTypes.string
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(DeleteMovieModalContentConnector);
|
@@ -165,7 +165,7 @@ class EditMovieModalContent extends Component {
|
||||
}
|
||||
|
||||
EditMovieModalContent.propTypes = {
|
||||
movieId: PropTypes.number.isRequired,
|
||||
indexerId: PropTypes.number.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
item: PropTypes.object.isRequired,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
|
@@ -83,7 +83,7 @@ class EditMovieModalContentConnector extends Component {
|
||||
|
||||
onSavePress = (moveFiles) => {
|
||||
this.props.dispatchSaveMovie({
|
||||
id: this.props.movieId,
|
||||
id: this.props.indexerId,
|
||||
moveFiles
|
||||
});
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class EditMovieModalContentConnector extends Component {
|
||||
}
|
||||
|
||||
EditMovieModalContentConnector.propTypes = {
|
||||
movieId: PropTypes.number,
|
||||
indexerId: PropTypes.number,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
dispatchSetMovieValue: PropTypes.func.isRequired,
|
||||
|
@@ -79,14 +79,14 @@ class MovieIndexActionsCell extends Component {
|
||||
|
||||
<EditMovieModalConnector
|
||||
isOpen={isEditMovieModalOpen}
|
||||
movieId={id}
|
||||
indexerId={id}
|
||||
onModalClose={this.onEditMovieModalClose}
|
||||
onDeleteMoviePress={this.onDeleteMoviePress}
|
||||
/>
|
||||
|
||||
<DeleteMovieModal
|
||||
isOpen={isDeleteMovieModalOpen}
|
||||
movieId={id}
|
||||
indexerId={id}
|
||||
onModalClose={this.onDeleteMovieModalClose}
|
||||
/>
|
||||
</VirtualTableRowCell>
|
||||
|
@@ -6,7 +6,7 @@ import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellCo
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
|
||||
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import DeleteMovieModal from 'Indexer/Delete/DeleteMovieModal';
|
||||
import DeleteIndexerModal from 'Indexer/Delete/DeleteIndexerModal';
|
||||
import EditIndexerModalConnector from 'Settings/Indexers/Indexers/EditIndexerModalConnector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import CapabilitiesLabel from './CapabilitiesLabel';
|
||||
@@ -217,11 +217,12 @@ class MovieIndexRow extends Component {
|
||||
id={id}
|
||||
isOpen={isEditIndexerModalOpen}
|
||||
onModalClose={this.onEditIndexerModalClose}
|
||||
onDeleteIndexerPress={this.onDeleteMoviePress}
|
||||
/>
|
||||
|
||||
<DeleteMovieModal
|
||||
<DeleteIndexerModal
|
||||
isOpen={isDeleteMovieModalOpen}
|
||||
movieId={id}
|
||||
indexerId={id}
|
||||
onModalClose={this.onDeleteMovieModalClose}
|
||||
/>
|
||||
</>
|
||||
|
@@ -64,7 +64,7 @@ class MovieIndexTable extends Component {
|
||||
key={movie.id}
|
||||
component={MovieIndexRow}
|
||||
columns={columns}
|
||||
movieId={movie.id}
|
||||
indexerId={movie.id}
|
||||
isSelected={selectedState[movie.id]}
|
||||
onSelectedChange={onSelectedChange}
|
||||
isMovieEditorActive={isMovieEditorActive}
|
||||
|
@@ -292,7 +292,7 @@ SearchIndex.propTypes = {
|
||||
onFilterSelect: PropTypes.func.isRequired,
|
||||
onSearchPress: PropTypes.func.isRequired,
|
||||
onScroll: PropTypes.func.isRequired,
|
||||
hasIndexers: PropTypes.func.isRequired
|
||||
hasIndexers: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default SearchIndex;
|
||||
|
@@ -2,12 +2,12 @@ import { createSelector } from 'reselect';
|
||||
|
||||
function createIndexerSelector() {
|
||||
return createSelector(
|
||||
(state, { movieId }) => movieId,
|
||||
(state, { indexerId }) => indexerId,
|
||||
(state) => state.indexers.itemMap,
|
||||
(state) => state.indexers.items,
|
||||
(movieId, itemMap, allMovies) => {
|
||||
if (allMovies && itemMap && movieId in itemMap) {
|
||||
return allMovies[itemMap[movieId]];
|
||||
(indexerId, itemMap, allMovies) => {
|
||||
if (allMovies && itemMap && indexerId in itemMap) {
|
||||
return allMovies[itemMap[indexerId]];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
Reference in New Issue
Block a user