From bdd8bc06cbb23019c3e5474a68e45dec0afc21c8 Mon Sep 17 00:00:00 2001 From: Axel Bocciarelli Date: Tue, 25 Jul 2023 11:37:31 +0200 Subject: [PATCH] Improve UX of numeric input --- ui/package-lock.json | 109 +++++++++++++++++--- ui/package.json | 4 +- ui/src/components/MotorInput/MotorInput.jsx | 79 +++++++------- ui/src/components/PopInput/NumericInput.jsx | 106 +++++++++---------- ui/src/components/PopInput/PopInput.jsx | 5 +- ui/src/components/PopInput/style.css | 12 ++- ui/src/main.css | 97 +++++++++++++++++ 7 files changed, 291 insertions(+), 121 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index 13acadd59..b55ae2800 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -33,6 +33,7 @@ "lodash": "^4.17.21", "plotly.js": "^1.52.3", "popper.js": "^1.16.1", + "rc-input-number": "8.0.3", "react": "^17.0.2", "react-bootstrap": "2.8.0", "react-chat-widget": "^3.1.4", @@ -45,7 +46,6 @@ "react-hook-form": "7.45.0", "react-icons": "^4.3.1", "react-lazyload": "^3.2.0", - "react-numeric-input": "^2.2.3", "react-plotly.js": "^2.4.0", "react-redux": "7.2.6", "react-router": "^6.2.1", @@ -4133,6 +4133,17 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, "node_modules/@react-aria/ssr": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz", @@ -21947,6 +21958,49 @@ "node": ">=0.10.0" } }, + "node_modules/rc-input": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.1.0.tgz", + "integrity": "sha512-izuNXPABQPh4KD7ANFcTrIGp9EZU0FkjTw6AvwCQ/rGPrdDsUTHLsp/Wju/kzGMLJFJWKNF3smbmXRNO23DtXA==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.0.3.tgz", + "integrity": "sha512-GHfWvufXEmwF/wtR8oPZNTuMdFb/rvx/+Sp2bZfaPftM+LFFdO8o3/PaeTk8DKt0Tv+u5Zuf68lqLdGCkmAXRg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.1.0", + "rc-util": "^5.28.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.34.1.tgz", + "integrity": "sha512-SqiUT8Ssgh5C+hu4y887xwCrMNcxLm6ScOo8AFlWYYF3z9uNNiPpwwSjvicqOlWd79rNw1g44rnP7tz9MrO1ZQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -22199,14 +22253,6 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, - "node_modules/react-numeric-input": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-numeric-input/-/react-numeric-input-2.2.3.tgz", - "integrity": "sha512-0hDXY8eznhTNMYfmeXRo/R1Fyx//ub0C/tpXbIeEaTnG72P95MGGMvJbiX5i+mnmiFVT6OCgIR33mke45nNZzQ==", - "peerDependencies": { - "react": ">=0.14.0 || ^15.6.1 || ^16.0.0" - } - }, "node_modules/react-plotly.js": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/react-plotly.js/-/react-plotly.js-2.6.0.tgz", @@ -30901,6 +30947,14 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, + "@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "requires": { + "@babel/runtime": "^7.18.0" + } + }, "@react-aria/ssr": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz", @@ -44495,6 +44549,37 @@ } } }, + "rc-input": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.1.0.tgz", + "integrity": "sha512-izuNXPABQPh4KD7ANFcTrIGp9EZU0FkjTw6AvwCQ/rGPrdDsUTHLsp/Wju/kzGMLJFJWKNF3smbmXRNO23DtXA==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + } + }, + "rc-input-number": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.0.3.tgz", + "integrity": "sha512-GHfWvufXEmwF/wtR8oPZNTuMdFb/rvx/+Sp2bZfaPftM+LFFdO8o3/PaeTk8DKt0Tv+u5Zuf68lqLdGCkmAXRg==", + "requires": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.1.0", + "rc-util": "^5.28.0" + } + }, + "rc-util": { + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.34.1.tgz", + "integrity": "sha512-SqiUT8Ssgh5C+hu4y887xwCrMNcxLm6ScOo8AFlWYYF3z9uNNiPpwwSjvicqOlWd79rNw1g44rnP7tz9MrO1ZQ==", + "requires": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0" + } + }, "react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -44682,12 +44767,6 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, - "react-numeric-input": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-numeric-input/-/react-numeric-input-2.2.3.tgz", - "integrity": "sha512-0hDXY8eznhTNMYfmeXRo/R1Fyx//ub0C/tpXbIeEaTnG72P95MGGMvJbiX5i+mnmiFVT6OCgIR33mke45nNZzQ==", - "requires": {} - }, "react-plotly.js": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/react-plotly.js/-/react-plotly.js-2.6.0.tgz", diff --git a/ui/package.json b/ui/package.json index e74dcc1dd..7c6b2788e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -37,6 +37,7 @@ "lodash": "^4.17.21", "plotly.js": "^1.52.3", "popper.js": "^1.16.1", + "rc-input-number": "8.0.3", "react": "^17.0.2", "react-bootstrap": "2.8.0", "react-chat-widget": "^3.1.4", @@ -49,7 +50,6 @@ "react-hook-form": "7.45.0", "react-icons": "^4.3.1", "react-lazyload": "^3.2.0", - "react-numeric-input": "^2.2.3", "react-plotly.js": "^2.4.0", "react-redux": "7.2.6", "react-router": "^6.2.1", @@ -78,9 +78,9 @@ "cypress": "^12.13.0", "eslint": "8.42.0", "eslint-config-galex": "4.5.2", + "eslint-plugin-import": "2.27.5", "eslint-plugin-jest": "27.2.1", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-import": "2.27.5", "eslint-plugin-react": "7.32.2", "less": "^4.1.2", "less-watch-compiler": "^1.16.3", diff --git a/ui/src/components/MotorInput/MotorInput.jsx b/ui/src/components/MotorInput/MotorInput.jsx index a043e6241..28cb94503 100644 --- a/ui/src/components/MotorInput/MotorInput.jsx +++ b/ui/src/components/MotorInput/MotorInput.jsx @@ -140,59 +140,50 @@ export default class MotorInput extends React.Component { } /> -
- {this.props.saveStep && - this.props.state === MOTOR_STATE.READY && - !this.props.inplace ? ( - - ) : null} - {this.props.state !== MOTOR_STATE.READY ? ( + > + {this.props.inplace ? ( + + {this.props.step} {suffix} + + ) : ( + + )} +
+ ) : ( - ) : null} - {this.props.saveStep && - this.props.state === MOTOR_STATE.READY && - this.props.inplace ? ( - - {this.props.step} {suffix} - - ) : null} - + ))} {this.props.inplace && ( diff --git a/ui/src/components/PopInput/NumericInput.jsx b/ui/src/components/PopInput/NumericInput.jsx index 8960388ec..3077b432b 100644 --- a/ui/src/components/PopInput/NumericInput.jsx +++ b/ui/src/components/PopInput/NumericInput.jsx @@ -1,68 +1,68 @@ -import React from 'react'; -import { Form, InputGroup, Button, ButtonToolbar } from 'react-bootstrap'; -import ReactNumericInput from 'react-numeric-input'; +import React, { useState } from 'react'; +import { Form, Button, ButtonToolbar } from 'react-bootstrap'; +import RcInputNumber from 'rc-input-number'; import { TiTick, TiTimes } from 'react-icons/ti'; -export default class NumericInput extends React.Component { - constructor(props) { - super(props); - this.handleSubmit = this.handleSubmit.bind(this); - this.inputRef = React.createRef(); - } +function NumericInput(props) { + const { initialValue, precision, step, size, busy, onCancel, onSubmit } = + props; + + const [value, setValue] = useState(initialValue); - handleSubmit(evt) { + function handleSubmit(evt) { evt.preventDefault(); - if (!this.props.busy) { - this.props.onSubmit(this.inputRef.current.state.value); + + if (!busy) { + const formData = new FormData(evt.currentTarget); + const val = formData.get('value'); + const parsedVal = Number.parseFloat(val); + + onSubmit(Number.isNaN(parsedVal) ? initialValue : parsedVal); } } - render() { - return ( -
- - {this.props.busy ? ( -
- ) : ( - - )} - - {!this.props.busy && ( - - )} - {!this.props.inplace && ( - - )} - - - - ); - } + return ( +
+