mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-24 22:35:39 -04:00
Renames in Frontend
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import EditAuthorModalContentConnector from './EditAuthorModalContentConnector';
|
||||
|
||||
function EditAuthorModal({ isOpen, onModalClose, ...otherProps }) {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<EditAuthorModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
EditAuthorModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EditAuthorModal;
|
||||
@@ -0,0 +1,39 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||
import EditAuthorModal from './EditAuthorModal';
|
||||
|
||||
const mapDispatchToProps = {
|
||||
clearPendingChanges
|
||||
};
|
||||
|
||||
class EditAuthorModalConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onModalClose = () => {
|
||||
this.props.clearPendingChanges({ section: 'author' });
|
||||
this.props.onModalClose();
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditAuthorModal
|
||||
{...this.props}
|
||||
onModalClose={this.onModalClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditAuthorModalConnector.propTypes = {
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
clearPendingChanges: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(undefined, mapDispatchToProps)(EditAuthorModalConnector);
|
||||
@@ -0,0 +1,9 @@
|
||||
.deleteButton {
|
||||
composes: button from '~Components/Link/Button.css';
|
||||
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.labelIcon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons, inputTypes, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
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 Icon from 'Components/Icon';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import MoveAuthorModal from 'Author/MoveAuthor/MoveAuthorModal';
|
||||
import AuthorMetadataProfilePopoverContent from 'AddAuthor/AuthorMetadataProfilePopoverContent';
|
||||
import styles from './EditAuthorModalContent.css';
|
||||
|
||||
class EditAuthorModalContent extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isConfirmMoveModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onSavePress = () => {
|
||||
const {
|
||||
isPathChanging,
|
||||
onSavePress
|
||||
} = this.props;
|
||||
|
||||
if (isPathChanging && !this.state.isConfirmMoveModalOpen) {
|
||||
this.setState({ isConfirmMoveModalOpen: true });
|
||||
} else {
|
||||
this.setState({ isConfirmMoveModalOpen: false });
|
||||
|
||||
onSavePress(false);
|
||||
}
|
||||
}
|
||||
|
||||
onMoveAuthorPress = () => {
|
||||
this.setState({ isConfirmMoveModalOpen: false });
|
||||
|
||||
this.props.onSavePress(true);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
authorName,
|
||||
item,
|
||||
isSaving,
|
||||
showMetadataProfile,
|
||||
originalPath,
|
||||
onInputChange,
|
||||
onModalClose,
|
||||
onDeleteAuthorPress,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
monitored,
|
||||
qualityProfileId,
|
||||
metadataProfileId,
|
||||
path,
|
||||
tags
|
||||
} = item;
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
Edit - {authorName}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<Form {...otherProps}>
|
||||
<FormGroup>
|
||||
<FormLabel>Monitored</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="monitored"
|
||||
helpText="Download monitored books from this author"
|
||||
{...monitored}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Quality Profile</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.QUALITY_PROFILE_SELECT}
|
||||
name="qualityProfileId"
|
||||
{...qualityProfileId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
showMetadataProfile &&
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
Metadata Profile
|
||||
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
className={styles.labelIcon}
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Metadata Profile"
|
||||
body={<AuthorMetadataProfilePopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.METADATA_PROFILE_SELECT}
|
||||
name="metadataProfileId"
|
||||
helpText="Changes will take place on next author refresh"
|
||||
includeNone={true}
|
||||
{...metadataProfileId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Path</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PATH}
|
||||
name="path"
|
||||
{...path}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Tags</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="tags"
|
||||
{...tags}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
className={styles.deleteButton}
|
||||
kind={kinds.DANGER}
|
||||
onPress={onDeleteAuthorPress}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<SpinnerButton
|
||||
isSpinning={isSaving}
|
||||
onPress={this.onSavePress}
|
||||
>
|
||||
Save
|
||||
</SpinnerButton>
|
||||
</ModalFooter>
|
||||
|
||||
<MoveAuthorModal
|
||||
originalPath={originalPath}
|
||||
destinationPath={path.value}
|
||||
isOpen={this.state.isConfirmMoveModalOpen}
|
||||
onSavePress={this.onSavePress}
|
||||
onMoveAuthorPress={this.onMoveAuthorPress}
|
||||
/>
|
||||
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditAuthorModalContent.propTypes = {
|
||||
authorId: PropTypes.number.isRequired,
|
||||
authorName: PropTypes.string.isRequired,
|
||||
item: PropTypes.object.isRequired,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
showMetadataProfile: PropTypes.bool.isRequired,
|
||||
isPathChanging: PropTypes.bool.isRequired,
|
||||
originalPath: PropTypes.string.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onSavePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
onDeleteAuthorPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EditAuthorModalContent;
|
||||
@@ -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 createAuthorSelector from 'Store/Selectors/createAuthorSelector';
|
||||
import { saveAuthor, setAuthorValue } from 'Store/Actions/authorActions';
|
||||
import EditAuthorModalContent from './EditAuthorModalContent';
|
||||
|
||||
function createIsPathChangingSelector() {
|
||||
return createSelector(
|
||||
(state) => state.authors.pendingChanges,
|
||||
createAuthorSelector(),
|
||||
(pendingChanges, author) => {
|
||||
const path = pendingChanges.path;
|
||||
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return author.path !== path;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.authors,
|
||||
(state) => state.settings.metadataProfiles,
|
||||
createAuthorSelector(),
|
||||
createIsPathChangingSelector(),
|
||||
(authorsState, metadataProfiles, author, isPathChanging) => {
|
||||
const {
|
||||
isSaving,
|
||||
saveError,
|
||||
pendingChanges
|
||||
} = authorsState;
|
||||
|
||||
const authorSettings = _.pick(author, [
|
||||
'monitored',
|
||||
'qualityProfileId',
|
||||
'metadataProfileId',
|
||||
'path',
|
||||
'tags'
|
||||
]);
|
||||
|
||||
const settings = selectSettings(authorSettings, pendingChanges, saveError);
|
||||
|
||||
return {
|
||||
authorName: author.authorName,
|
||||
isSaving,
|
||||
saveError,
|
||||
isPathChanging,
|
||||
originalPath: author.path,
|
||||
item: settings.settings,
|
||||
showMetadataProfile: metadataProfiles.items.length > 1,
|
||||
...settings
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
dispatchSetAuthorValue: setAuthorValue,
|
||||
dispatchSaveAuthor: saveAuthor
|
||||
};
|
||||
|
||||
class EditAuthorModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
|
||||
this.props.onModalClose();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.props.dispatchSetAuthorValue({ name, value });
|
||||
}
|
||||
|
||||
onSavePress = (moveFiles) => {
|
||||
this.props.dispatchSaveAuthor({
|
||||
id: this.props.authorId,
|
||||
moveFiles
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditAuthorModalContent
|
||||
{...this.props}
|
||||
onInputChange={this.onInputChange}
|
||||
onSavePress={this.onSavePress}
|
||||
onMoveAuthorPress={this.onMoveAuthorPress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditAuthorModalContentConnector.propTypes = {
|
||||
authorId: PropTypes.number,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
dispatchSetAuthorValue: PropTypes.func.isRequired,
|
||||
dispatchSaveAuthor: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(EditAuthorModalContentConnector);
|
||||
Reference in New Issue
Block a user