diff --git a/frontend/src/Components/Form/NumberInput.js b/frontend/src/Components/Form/NumberInput.js
index 20b6fd0a1..c03871a44 100644
--- a/frontend/src/Components/Form/NumberInput.js
+++ b/frontend/src/Components/Form/NumberInput.js
@@ -2,44 +2,86 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import TextInput from './TextInput';
+function parseValue(props, value) {
+ const {
+ isFloat,
+ min,
+ max
+ } = props;
+
+ if (value == null) {
+ return min;
+ }
+
+ let newValue = isFloat ? parseFloat(value) : parseInt(value);
+
+ if (min != null && newValue != null && newValue < min) {
+ newValue = min;
+ } else if (max != null && newValue != null && newValue > max) {
+ newValue = max;
+ }
+
+ return newValue;
+}
+
class NumberInput extends Component {
+ //
+ // Lifecycle
+
+ constructor(props, context) {
+ super(props, context);
+
+ this.state = {
+ value: props.value.toString(),
+ isFocused: false
+ };
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if (this.props.value !== prevProps.value && !this.state.isFocused) {
+ this.setState({ value: this.props.value.toString() });
+ }
+ }
+
//
// Listeners
onChange = ({ name, value }) => {
- let newValue = null;
-
- if (value) {
- newValue = this.props.isFloat ? parseFloat(value) : parseInt(value);
- }
+ this.setState({ value });
this.props.onChange({
name,
- value: newValue
+ value: parseValue(this.props, value)
});
+
+ }
+
+ onFocus = () => {
+ this.setState({ isFocused: true });
}
onBlur = () => {
const {
name,
- value,
- min,
- max,
onChange
} = this.props;
- let newValue = value;
+ const { value } = this.state;
+ const parsedValue = parseValue(this.props, value);
- if (min != null && newValue != null && newValue < min) {
- newValue = min;
- } else if (max != null && newValue != null && newValue > max) {
- newValue = max;
+ if (parsedValue.toString() === value) {
+ this.setState({ isFocused: false });
+ } else {
+ this.setState({
+ value: parsedValue.toString(),
+ isFocused: false
+ });
}
onChange({
name,
- value: newValue
+ value: parseValue(this.props, this.state.value)
});
}
@@ -47,18 +89,16 @@ class NumberInput extends Component {
// Render
render() {
- const {
- value,
- ...otherProps
- } = this.props;
+ const value = this.state.value;
return (
);
}
diff --git a/frontend/src/Components/Form/TextInput.js b/frontend/src/Components/Form/TextInput.js
index 92c0f4baf..9feefa616 100644
--- a/frontend/src/Components/Form/TextInput.js
+++ b/frontend/src/Components/Form/TextInput.js
@@ -127,6 +127,7 @@ class TextInput extends Component {
hasError,
hasWarning,
hasButton,
+ step,
onBlur
} = this.props;
@@ -146,6 +147,7 @@ class TextInput extends Component {
)}
name={name}
value={value}
+ step={step}
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={onBlur}
@@ -168,6 +170,7 @@ TextInput.propTypes = {
hasError: PropTypes.bool,
hasWarning: PropTypes.bool,
hasButton: PropTypes.bool,
+ step: PropTypes.number,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.js b/frontend/src/Settings/Quality/Definition/QualityDefinition.js
index 2ff558037..ea5075334 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.js
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinition.js
@@ -2,28 +2,38 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import ReactSlider from 'react-slider';
import formatBytes from 'Utilities/Number/formatBytes';
+import roundNumber from 'Utilities/Number/roundNumber';
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 MIN = 0;
+const MAX = 400;
+
const slider = {
- min: 0,
- max: 200,
+ min: MIN,
+ max: roundNumber(Math.pow(MAX, 1 / 1.1)),
step: 0.1
};
-function getValue(value) {
- if (value < slider.min) {
- return slider.min;
+function getValue(inputValue) {
+ if (inputValue < MIN) {
+ return MIN;
}
- if (value > slider.max) {
- return slider.max;
+ if (inputValue > MAX) {
+ return MAX;
}
- return value;
+ return roundNumber(inputValue);
+}
+
+function getSliderValue(value, defaultValue) {
+ const sliderValue = value ? Math.pow(value, 1 / 1.1) : defaultValue;
+
+ return roundNumber(sliderValue);
}
class QualityDefinition extends Component {
@@ -35,6 +45,11 @@ class QualityDefinition extends Component {
super(props, context);
this._forceUpdateTimeout = null;
+
+ this.state = {
+ sliderMinSize: getSliderValue(props.minSize, slider.min),
+ sliderMaxSize: getSliderValue(props.maxSize, slider.max)
+ };
}
componentDidMount() {
@@ -54,15 +69,37 @@ class QualityDefinition extends Component {
//
// Listeners
- onSizeChange = ([minSize, maxSize]) => {
- maxSize = maxSize === slider.max ? null : maxSize;
+ onSliderChange = ([sliderMinSize, sliderMaxSize]) => {
+ this.setState({
+ sliderMinSize,
+ sliderMaxSize
+ });
- this.props.onSizeChange({ minSize, maxSize });
+ this.props.onSizeChange({
+ minSize: roundNumber(Math.pow(sliderMinSize, 1.1)),
+ maxSize: sliderMaxSize === slider.max ? null : roundNumber(Math.pow(sliderMaxSize, 1.1))
+ });
+ }
+
+ onAfterSliderChange = () => {
+ const {
+ minSize,
+ maxSize
+ } = this.props;
+
+ this.setState({
+ sliderMiSize: getSliderValue(minSize, slider.min),
+ sliderMaxSize: getSliderValue(maxSize, slider.max)
+ });
}
onMinSizeChange = ({ value }) => {
const minSize = getValue(value);
+ this.setState({
+ sliderMinSize: getSliderValue(minSize, slider.min)
+ });
+
this.props.onSizeChange({
minSize,
maxSize: this.props.maxSize
@@ -70,7 +107,11 @@ class QualityDefinition extends Component {
}
onMaxSizeChange = ({ value }) => {
- const maxSize = value === slider.max ? null : getValue(value);
+ const maxSize = value === MAX ? null : getValue(value);
+
+ this.setState({
+ sliderMaxSize: getSliderValue(maxSize, slider.max)
+ });
this.props.onSizeChange({
minSize: this.props.minSize,
@@ -92,6 +133,11 @@ class QualityDefinition extends Component {
onTitleChange
} = this.props;
+ const {
+ sliderMinSize,
+ sliderMaxSize
+ } = this.state;
+
const minBytes = minSize * 1024 * 1024;
const minThirty = formatBytes(minBytes * 30, 2);
const minSixty = formatBytes(minBytes * 60, 2);
@@ -120,13 +166,14 @@ class QualityDefinition extends Component {
max={slider.max}
step={slider.step}
minDistance={10}
- value={[minSize || slider.min, maxSize || slider.max]}
+ value={[sliderMinSize, sliderMaxSize]}
withBars={true}
snapDragDisabled={true}
className={styles.slider}
barClassName={styles.bar}
handleClassName={styles.handle}
- onChange={this.onSizeChange}
+ onChange={this.onSliderChange}
+ onAfterChange={this.onAfterSliderChange}
/>
@@ -151,9 +198,10 @@ class QualityDefinition extends Component {
@@ -165,9 +213,10 @@ class QualityDefinition extends Component {
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js b/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js
index 9404dfd9f..a76c9440f 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js
@@ -5,12 +5,6 @@ import { setQualityDefinitionValue } from 'Store/Actions/settingsActions';
import { clearPendingChanges } from 'Store/Actions/baseActions';
import QualityDefinition from './QualityDefinition';
-function mapStateToProps(state) {
- return {
- advancedSettings: state.settings.advancedSettings
- };
-}
-
const mapDispatchToProps = {
setQualityDefinitionValue,
clearPendingChanges
@@ -40,7 +34,7 @@ class QualityDefinitionConnector extends Component {
this.props.setQualityDefinitionValue({ id, name: 'minSize', value: minSize });
}
- if (minSize !== currentMaxSize) {
+ if (maxSize !== currentMaxSize) {
this.props.setQualityDefinitionValue({ id, name: 'maxSize', value: maxSize });
}
}
@@ -67,4 +61,4 @@ QualityDefinitionConnector.propTypes = {
clearPendingChanges: PropTypes.func.isRequired
};
-export default connect(mapStateToProps, mapDispatchToProps)(QualityDefinitionConnector);
+export default connect(null, mapDispatchToProps)(QualityDefinitionConnector);
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitions.js b/frontend/src/Settings/Quality/Definition/QualityDefinitions.js
index 18db844f8..f8050a7e7 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitions.js
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinitions.js
@@ -13,6 +13,7 @@ class QualityDefinitions extends Component {
render() {
const {
items,
+ advancedSettings,
...otherProps
} = this.props;
@@ -26,7 +27,14 @@ class QualityDefinitions extends Component {
Quality
Title
Size Limit
-
Megabytes Per Minute
+
+ {
+ advancedSettings ?
+
+ Megabytes Per Minute
+
:
+ null
+ }
@@ -36,6 +44,7 @@ class QualityDefinitions extends Component {
);
})
@@ -57,7 +66,8 @@ QualityDefinitions.propTypes = {
isFetching: PropTypes.bool.isRequired,
error: PropTypes.object,
defaultProfile: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired
+ items: PropTypes.arrayOf(PropTypes.object).isRequired,
+ advancedSettings: PropTypes.bool.isRequired
};
export default QualityDefinitions;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js b/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js
index 9a3e0a90c..c2f830afd 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js
@@ -9,7 +9,8 @@ import QualityDefinitions from './QualityDefinitions';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.qualityDefinitions,
- (qualityDefinitions) => {
+ (state) => state.settings.advancedSettings,
+ (qualityDefinitions, advancedSettings) => {
const items = qualityDefinitions.items.map((item) => {
const pendingChanges = qualityDefinitions.pendingChanges[item.id] || {};
@@ -19,7 +20,8 @@ function createMapStateToProps() {
return {
...qualityDefinitions,
items,
- hasPendingChanges: !_.isEmpty(qualityDefinitions.pendingChanges)
+ hasPendingChanges: !_.isEmpty(qualityDefinitions.pendingChanges),
+ advancedSettings
};
}
);
diff --git a/frontend/src/Utilities/Number/roundNumber.js b/frontend/src/Utilities/Number/roundNumber.js
new file mode 100644
index 000000000..e1a19018f
--- /dev/null
+++ b/frontend/src/Utilities/Number/roundNumber.js
@@ -0,0 +1,5 @@
+export default function roundNumber(input, decimalPlaces = 1) {
+ const multiplier = Math.pow(10, decimalPlaces);
+
+ return Math.round(input * multiplier) / multiplier;
+}