parent
eca9b87571
commit
4b66d99029
@ -1,25 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import EditMovieModalContentConnector from './EditMovieModalContentConnector';
|
||||
|
||||
function EditMovieModal({ isOpen, onModalClose, ...otherProps }) {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<EditMovieModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
EditMovieModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EditMovieModal;
|
@ -1,39 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||
import EditMovieModal from './EditMovieModal';
|
||||
|
||||
const mapDispatchToProps = {
|
||||
clearPendingChanges
|
||||
};
|
||||
|
||||
class EditMovieModalConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onModalClose = () => {
|
||||
this.props.clearPendingChanges({ section: 'movies' });
|
||||
this.props.onModalClose();
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditMovieModal
|
||||
{...this.props}
|
||||
onModalClose={this.onModalClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditMovieModalConnector.propTypes = {
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
clearPendingChanges: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(undefined, mapDispatchToProps)(EditMovieModalConnector);
|
@ -1,5 +0,0 @@
|
||||
.deleteButton {
|
||||
composes: button from '~Components/Link/Button.css';
|
||||
|
||||
margin-right: auto;
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
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 SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
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, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditMovieModalContent.css';
|
||||
|
||||
class EditMovieModalContent 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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
title,
|
||||
item,
|
||||
isSaving,
|
||||
originalPath,
|
||||
onInputChange,
|
||||
onModalClose,
|
||||
onDeleteMoviePress,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
monitored,
|
||||
qualityProfileId,
|
||||
minimumAvailability,
|
||||
// Id,
|
||||
path,
|
||||
tags
|
||||
} = item;
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{translate('Edit')} - {title}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<Form
|
||||
{...otherProps}
|
||||
>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Monitored')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="monitored"
|
||||
helpText={translate('MonitoredHelpText')}
|
||||
{...monitored}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('MinimumAvailability')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.AVAILABILITY_SELECT}
|
||||
name="minimumAvailability"
|
||||
{...minimumAvailability}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('QualityProfile')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.QUALITY_PROFILE_SELECT}
|
||||
name="qualityProfileId"
|
||||
{...qualityProfileId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Path')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PATH}
|
||||
name="path"
|
||||
{...path}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Tags')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="tags"
|
||||
{...tags}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button
|
||||
className={styles.deleteButton}
|
||||
kind={kinds.DANGER}
|
||||
onPress={onDeleteMoviePress}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Cancel')}
|
||||
</Button>
|
||||
|
||||
<SpinnerButton
|
||||
isSpinning={isSaving}
|
||||
onPress={this.onSavePress}
|
||||
>
|
||||
{translate('Save')}
|
||||
</SpinnerButton>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditMovieModalContent.propTypes = {
|
||||
indexerId: PropTypes.number.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
item: PropTypes.object.isRequired,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
isPathChanging: PropTypes.bool.isRequired,
|
||||
originalPath: PropTypes.string.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onSavePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
onDeleteMoviePress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EditMovieModalContent;
|
@ -1,115 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { saveMovie, setMovieValue } from 'Store/Actions/movieActions';
|
||||
import createIndexerSelector from 'Store/Selectors/createIndexerSelector';
|
||||
import selectSettings from 'Store/Selectors/selectSettings';
|
||||
import EditMovieModalContent from './EditMovieModalContent';
|
||||
|
||||
function createIsPathChangingSelector() {
|
||||
return createSelector(
|
||||
(state) => state.movies.pendingChanges,
|
||||
createIndexerSelector(),
|
||||
(pendingChanges, movie) => {
|
||||
const path = pendingChanges.path;
|
||||
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return movie.path !== path;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.movies,
|
||||
createIndexerSelector(),
|
||||
createIsPathChangingSelector(),
|
||||
(moviesState, movie, isPathChanging) => {
|
||||
const {
|
||||
isSaving,
|
||||
saveError,
|
||||
pendingChanges
|
||||
} = moviesState;
|
||||
|
||||
const movieSettings = {
|
||||
monitored: movie.monitored,
|
||||
qualityProfileId: movie.qualityProfileId,
|
||||
minimumAvailability: movie.minimumAvailability,
|
||||
path: movie.path,
|
||||
tags: movie.tags
|
||||
};
|
||||
|
||||
const settings = selectSettings(movieSettings, pendingChanges, saveError);
|
||||
|
||||
return {
|
||||
title: movie.title,
|
||||
isSaving,
|
||||
saveError,
|
||||
isPathChanging,
|
||||
originalPath: movie.path,
|
||||
item: settings.settings,
|
||||
...settings
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
dispatchSetMovieValue: setMovieValue,
|
||||
dispatchSaveMovie: saveMovie
|
||||
};
|
||||
|
||||
class EditMovieModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
|
||||
this.props.onModalClose();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.props.dispatchSetMovieValue({ name, value });
|
||||
}
|
||||
|
||||
onSavePress = (moveFiles) => {
|
||||
this.props.dispatchSaveMovie({
|
||||
id: this.props.indexerId,
|
||||
moveFiles
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditMovieModalContent
|
||||
{...this.props}
|
||||
onInputChange={this.onInputChange}
|
||||
onSavePress={this.onSavePress}
|
||||
onMoveMoviePress={this.onMoveMoviePress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditMovieModalContentConnector.propTypes = {
|
||||
indexerId: PropTypes.number,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
dispatchSetMovieValue: PropTypes.func.isRequired,
|
||||
dispatchSaveMovie: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(EditMovieModalContentConnector);
|
@ -1,14 +0,0 @@
|
||||
.progress {
|
||||
composes: container from '~Components/ProgressBar.css';
|
||||
|
||||
border-radius: 0;
|
||||
background-color: #5b5b5b;
|
||||
color: $white;
|
||||
transition: width 200ms ease;
|
||||
}
|
||||
|
||||
.progressBar {
|
||||
composes: progressBar from '~Components/ProgressBar.css';
|
||||
|
||||
transition: width 200ms ease;
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import ProgressBar from 'Components/ProgressBar';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import getProgressBarKind from 'Utilities/Movie/getProgressBarKind';
|
||||
import getQueueStatusText from 'Utilities/Movie/getQueueStatusText';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './MovieIndexProgressBar.css';
|
||||
|
||||
function MovieIndexProgressBar(props) {
|
||||
const {
|
||||
monitored,
|
||||
status,
|
||||
hasFile,
|
||||
isAvailable,
|
||||
posterWidth,
|
||||
detailedProgressBar,
|
||||
queueStatus,
|
||||
queueState
|
||||
} = props;
|
||||
|
||||
const progress = 100;
|
||||
const queueStatusText = getQueueStatusText(queueStatus, queueState);
|
||||
let movieStatus = (status === 'released' && hasFile) ? 'downloaded' : status;
|
||||
|
||||
if (movieStatus === 'deleted') {
|
||||
movieStatus = 'Missing';
|
||||
|
||||
if (hasFile) {
|
||||
movieStatus = 'Downloaded';
|
||||
}
|
||||
} else if (hasFile) {
|
||||
movieStatus = 'Downloaded';
|
||||
} else if (isAvailable && !hasFile) {
|
||||
movieStatus = 'Missing';
|
||||
} else {
|
||||
movieStatus = 'NotAvailable';
|
||||
}
|
||||
|
||||
return (
|
||||
<ProgressBar
|
||||
className={styles.progressBar}
|
||||
containerClassName={styles.progress}
|
||||
progress={progress}
|
||||
kind={getProgressBarKind(status, monitored, hasFile, isAvailable, queueStatusText)}
|
||||
size={detailedProgressBar ? sizes.MEDIUM : sizes.SMALL}
|
||||
showText={detailedProgressBar}
|
||||
width={posterWidth}
|
||||
text={(queueStatusText) ? queueStatusText : translate(movieStatus)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
MovieIndexProgressBar.propTypes = {
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
hasFile: PropTypes.bool.isRequired,
|
||||
isAvailable: PropTypes.bool.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
posterWidth: PropTypes.number.isRequired,
|
||||
detailedProgressBar: PropTypes.bool.isRequired,
|
||||
queueStatus: PropTypes.string,
|
||||
queueState: PropTypes.string
|
||||
};
|
||||
|
||||
export default MovieIndexProgressBar;
|
@ -0,0 +1,9 @@
|
||||
.status {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.statusIcon {
|
||||
width: 20px !important;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
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 styles from './IndexerStatusCell.css';
|
||||
|
||||
function IndexerStatusCell(props) {
|
||||
const {
|
||||
className,
|
||||
enabled,
|
||||
component: Component,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Component
|
||||
className={className}
|
||||
{...otherProps}
|
||||
>
|
||||
{
|
||||
!enabled &&
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
name={icons.BLACKLIST}
|
||||
title={enabled ? 'Indexer is Enabled' : 'Indexer is Disabled'}
|
||||
/>
|
||||
}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
|
||||
IndexerStatusCell.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
enabled: PropTypes.bool.isRequired,
|
||||
component: PropTypes.elementType
|
||||
};
|
||||
|
||||
IndexerStatusCell.defaultProps = {
|
||||
className: styles.status,
|
||||
component: VirtualTableRowCell
|
||||
};
|
||||
|
||||
export default IndexerStatusCell;
|
@ -0,0 +1,24 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import FilterModal from 'Components/Filter/FilterModal';
|
||||
import { setReleasesFilter } from 'Store/Actions/releaseActions';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.releases.items,
|
||||
(state) => state.releases.filterBuilderProps,
|
||||
(sectionItems, filterBuilderProps) => {
|
||||
return {
|
||||
sectionItems,
|
||||
filterBuilderProps,
|
||||
customFilterType: 'releases'
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
dispatchSetFilter: setReleasesFilter
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(FilterModal);
|
@ -1,16 +1,23 @@
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
|
||||
namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
public class IndexerQueryEvent : IEvent
|
||||
{
|
||||
public int IndexerId { get; set; }
|
||||
public string Query { get; set; }
|
||||
public SearchCriteriaBase Query { get; set; }
|
||||
public long Time { get; set; }
|
||||
public bool Successful { get; set; }
|
||||
public int? Results { get; set; }
|
||||
|
||||
public IndexerQueryEvent(int indexerId, string query)
|
||||
public IndexerQueryEvent(int indexerId, SearchCriteriaBase query, long time, bool successful, int? results = null)
|
||||
{
|
||||
IndexerId = indexerId;
|
||||
Query = query;
|
||||
Time = time;
|
||||
Successful = successful;
|
||||
Results = results;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in new issue