From 23cfaf418914f52589b3730fea1d60959cb8117b Mon Sep 17 00:00:00 2001 From: Axel Bocciarelli Date: Mon, 18 Sep 2023 16:19:58 +0200 Subject: [PATCH] Manage `AddSample` form with react-hook-form and improve UX --- ui/src/components/Tasks/AddSample.js | 126 ++++++++++-------- .../components/Tasks/validate_add_sample.js | 21 --- ui/src/main.css | 3 +- 3 files changed, 69 insertions(+), 81 deletions(-) delete mode 100644 ui/src/components/Tasks/validate_add_sample.js diff --git a/ui/src/components/Tasks/AddSample.js b/ui/src/components/Tasks/AddSample.js index fb2843c5b..e87b4c36f 100644 --- a/ui/src/components/Tasks/AddSample.js +++ b/ui/src/components/Tasks/AddSample.js @@ -1,26 +1,22 @@ import React from 'react'; import { connect } from 'react-redux'; -import { reduxForm } from 'redux-form'; -import { Modal, ButtonToolbar, Button, Form } from 'react-bootstrap'; -import { InputField, FieldsRow } from './fields'; -import validate from './validate_add_sample'; +import { Modal, ButtonToolbar, Button, Form, Row, Col } from 'react-bootstrap'; import { bindActionCreators } from 'redux'; import { addSamplesToList } from '../../actions/sampleGrid'; import { addSampleAndMount, addSamplesToQueue } from '../../actions/queue'; import { showList } from '../../actions/queueGUI'; import { useLocation } from 'react-router-dom'; +import { useForm } from 'react-hook-form'; -function getDefaultSampleData(params) { - let prefix = params.sampleName ? params.sampleName : 'noname'; - - if (params.proteinAcronym && params.sampleName) { - prefix = `${params.proteinAcronym}-${prefix}`; - } +const REQUIRED_MSG = 'This field is required'; +const PATTERN = /^[\w+:-]*$/u; +const PATTERN_MSG = 'Characters allowed: A-Z a-z 0-9 _+:-'; +function getSampleData(params) { return { ...params, type: 'Sample', - defaultPrefix: prefix, + defaultPrefix: `${params.proteinAcronym}-${params.sampleName}`, location: 'Manual', loadable: true, tasks: [], @@ -31,22 +27,23 @@ function AddSample(props) { const { show, hide, - invalid, - handleSubmit, addSamplesToList, addSampleAndMount, addSamplesToQueue, showList, } = props; + const { register, formState, handleSubmit } = useForm({ mode: 'onTouched' }); + const { errors, touchedFields } = formState; + const { pathname } = useLocation(); function addAndMount(params) { - const sampleData = getDefaultSampleData(params); + const sampleData = getSampleData(params); addSamplesToList([sampleData]); addSampleAndMount(sampleData); - if (pathname === '/datacollection') { + if (pathname === '/' || pathname === '/datacollection') { showList('current'); } @@ -54,51 +51,72 @@ function AddSample(props) { } function addAndQueue(params) { - const sampleData = getDefaultSampleData(params); + const sampleData = getSampleData(params); addSamplesToList([sampleData]); addSamplesToQueue([sampleData]); hide(); } return ( - -
{ - evt.preventDefault(); - handleSubmit(addAndMount)(); - }} - > + + New Sample - - - - + + + Sample name + + + + {errors.sampleName && ( + + {errors.sampleName.message} + + )} + + + + + Protein acronym + + + + {errors.proteinAcronym && ( + + {errors.proteinAcronym.message} + + )} + + - @@ -109,21 +127,11 @@ function AddSample(props) { ); } -const AddSampleForm = reduxForm({ - form: 'addsample', - validate, -})(AddSample); - -const AddSampleContainer = connect( - (state) => ({ - initialValues: { ...state.taskForm.taskData.parameters }, - }), - (dispatch) => ({ - addSamplesToList: bindActionCreators(addSamplesToList, dispatch), - addSamplesToQueue: bindActionCreators(addSamplesToQueue, dispatch), - addSampleAndMount: bindActionCreators(addSampleAndMount, dispatch), - showList: bindActionCreators(showList, dispatch), - }), -)(AddSampleForm); +const AddSampleContainer = connect(undefined, (dispatch) => ({ + addSamplesToList: bindActionCreators(addSamplesToList, dispatch), + addSamplesToQueue: bindActionCreators(addSamplesToQueue, dispatch), + addSampleAndMount: bindActionCreators(addSampleAndMount, dispatch), + showList: bindActionCreators(showList, dispatch), +}))(AddSample); export default AddSampleContainer; diff --git a/ui/src/components/Tasks/validate_add_sample.js b/ui/src/components/Tasks/validate_add_sample.js deleted file mode 100644 index 5d21c9574..000000000 --- a/ui/src/components/Tasks/validate_add_sample.js +++ /dev/null @@ -1,21 +0,0 @@ -const validate = (values, props) => { - const errors = {}; - if (!props) { - // for some reason redux-form is loaded before the initial status - return errors; - } - const name = values.sampleName ? values.sampleName : ''; - const acr = values.proteinAcronym ? values.proteinAcronym : ''; - const regex = new RegExp(/^[\w+:-]*$/); - - if (name.length === 0 || !regex.test(name)) { - errors.sampleName = 'Missing sample name'; - } - if (acr.length === 0 || !regex.test(acr)) { - errors.proteinAcronym = 'Missing protein acronym'; - } - - return errors; -}; - -export default validate; diff --git a/ui/src/main.css b/ui/src/main.css index 8948a600d..88010d657 100644 --- a/ui/src/main.css +++ b/ui/src/main.css @@ -55,7 +55,8 @@ input[type='color']:focus, z-index: 10000; } -.modal-dialog { +/* Allow opting out of this global override */ +.modal-dialog:not([data-default-styles]) { width: min-content; max-width: 90%; min-width: 50%;