mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-25 22:46:31 -04:00
v3 UI
This commit is contained in:
committed by
Taloth Saldono
parent
99feff549d
commit
5894b4fd95
@@ -0,0 +1,193 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import ReactSlider from 'react-slider';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Label from 'Components/Label';
|
||||
import NumberInput from 'Components/Form/NumberInput';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import styles from './QualityDefinition.css';
|
||||
|
||||
const slider = {
|
||||
min: 0,
|
||||
max: 200,
|
||||
step: 0.1
|
||||
};
|
||||
|
||||
function getValue(value) {
|
||||
if (value < slider.min) {
|
||||
return slider.min;
|
||||
}
|
||||
|
||||
if (value > slider.max) {
|
||||
return slider.max;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
class QualityDefinition extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._forceUpdateTimeout = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// A hack to deal with a bug in the slider component until a fix for it
|
||||
// lands and an updated version is available.
|
||||
// See: https://github.com/mpowaga/react-slider/issues/115
|
||||
|
||||
this._forceUpdateTimeout = setTimeout(() => this.forceUpdate(), 1);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._forceUpdateTimeout) {
|
||||
clearTimeout(this._forceUpdateTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onSizeChange = ([minSize, maxSize]) => {
|
||||
maxSize = maxSize === slider.max ? null : maxSize;
|
||||
|
||||
this.props.onSizeChange({ minSize, maxSize });
|
||||
}
|
||||
|
||||
onMinSizeChange = ({ value }) => {
|
||||
const minSize = getValue(value);
|
||||
|
||||
this.props.onSizeChange({
|
||||
minSize,
|
||||
maxSize: this.props.maxSize
|
||||
});
|
||||
}
|
||||
|
||||
onMaxSizeChange = ({ value }) => {
|
||||
const maxSize = value === slider.max ? null : getValue(value);
|
||||
|
||||
this.props.onSizeChange({
|
||||
minSize: this.props.minSize,
|
||||
maxSize
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
id,
|
||||
quality,
|
||||
title,
|
||||
minSize,
|
||||
maxSize,
|
||||
advancedSettings,
|
||||
onTitleChange
|
||||
} = this.props;
|
||||
|
||||
const minBytes = minSize * 1024 * 1024;
|
||||
const minThirty = formatBytes(minBytes * 30, 2);
|
||||
const minSixty = formatBytes(minBytes * 60, 2);
|
||||
|
||||
const maxBytes = maxSize && maxSize * 1024 * 1024;
|
||||
const maxThirty = maxBytes ? formatBytes(maxBytes * 30, 2) : 'Unlimited';
|
||||
const maxSixty = maxBytes ? formatBytes(maxBytes * 60, 2) : 'Unlimited';
|
||||
|
||||
return (
|
||||
<div className={styles.qualityDefinition}>
|
||||
<div className={styles.quality}>
|
||||
{quality.name}
|
||||
</div>
|
||||
|
||||
<div className={styles.title}>
|
||||
<TextInput
|
||||
name={`${id}.${title}`}
|
||||
value={title}
|
||||
onChange={onTitleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.sizeLimit}>
|
||||
<ReactSlider
|
||||
min={slider.min}
|
||||
max={slider.max}
|
||||
step={slider.step}
|
||||
minDistance={10}
|
||||
value={[minSize || slider.min, maxSize || slider.max]}
|
||||
withBars={true}
|
||||
snapDragDisabled={true}
|
||||
className={styles.slider}
|
||||
barClassName={styles.bar}
|
||||
handleClassName={styles.handle}
|
||||
onChange={this.onSizeChange}
|
||||
/>
|
||||
|
||||
<div className={styles.sizes}>
|
||||
<div>
|
||||
<Label kind={kinds.WARNING}>{minThirty}</Label>
|
||||
<Label kind={kinds.INFO}>{minSixty}</Label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label kind={kinds.WARNING}>{maxThirty}</Label>
|
||||
<Label kind={kinds.INFO}>{maxSixty}</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
advancedSettings &&
|
||||
<div className={styles.megabytesPerMinute}>
|
||||
<div>
|
||||
Min
|
||||
|
||||
<NumberInput
|
||||
className={styles.sizeInput}
|
||||
name={`${id}.min`}
|
||||
value={minSize || slider.min}
|
||||
min={slider.min}
|
||||
max={maxSize ? maxSize - 10 : slider.max - 10}
|
||||
isFloat={true}
|
||||
onChange={this.onMinSizeChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
Max
|
||||
|
||||
<NumberInput
|
||||
className={styles.sizeInput}
|
||||
name={`${id}.min`}
|
||||
value={maxSize || slider.max}
|
||||
min={minSize + 10}
|
||||
max={slider.max}
|
||||
isFloat={true}
|
||||
onChange={this.onMaxSizeChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
QualityDefinition.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
quality: PropTypes.object.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
minSize: PropTypes.number,
|
||||
maxSize: PropTypes.number,
|
||||
advancedSettings: PropTypes.bool.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onSizeChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default QualityDefinition;
|
||||
Reference in New Issue
Block a user