From af27af8d42205bcad812af71df7801720b7b88f8 Mon Sep 17 00:00:00 2001 From: Aditya Toshniwal Date: Mon, 30 Aug 2021 17:01:49 +0530 Subject: [PATCH] Integer and Numeric inputs fixes. --- .../static/js/SchemaView/MappedControl.jsx | 52 ++----------------- .../static/js/components/FormComponents.jsx | 18 ++++++- .../javascript/SchemaView/SchemaView.spec.js | 18 +++++-- 3 files changed, 34 insertions(+), 54 deletions(-) diff --git a/web/pgadmin/static/js/SchemaView/MappedControl.jsx b/web/pgadmin/static/js/SchemaView/MappedControl.jsx index 340c2bbcb..3dfb017b5 100644 --- a/web/pgadmin/static/js/SchemaView/MappedControl.jsx +++ b/web/pgadmin/static/js/SchemaView/MappedControl.jsx @@ -34,28 +34,6 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i onChange && onChange(value); }, []); - const onIntChange = useCallback((e) => { - let value = e; - if(e && e.target) { - value = e.target.value; - } - if(!isNaN(parseInt(value))) { - value = parseInt(value); - } - onChange && onChange(value); - }, []); - - const onNumChange = useCallback((e) => { - let value = e; - if(e && e.target) { - value = e.target.value; - } - if(!isNaN(parseFloat(value))) { - value = parseFloat(value); - } - onChange && onChange(value); - }, []); - if(!visible) { return <>; } @@ -63,9 +41,9 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i /* The mapping uses Form* components as it comes with labels */ switch (type) { case 'int': - return ; + return ; case 'numeric': - return ; + return ; case 'text': return ; case 'multiline': @@ -131,28 +109,6 @@ function MappedCellControlBase({cell, value, id, optionsLoaded, onCellChange, vi onCellChange && onCellChange(value); }, []); - const onIntChange = useCallback((e) => { - let value = e; - if(e && e.target) { - value = e.target.value; - } - if(!isNaN(parseInt(value))) { - value = parseInt(value); - } - onCellChange && onCellChange(value); - }, []); - - const onNumChange = useCallback((e) => { - let value = e; - if(e && e.target) { - value = e.target.value; - } - if(!isNaN(parseFloat(value))) { - value = parseFloat(value); - } - onCellChange && onCellChange(value); - }, []); - /* Some grid cells are based on options selected in other cells. * lets trigger a re-render for the row if optionsLoaded */ @@ -169,9 +125,9 @@ function MappedCellControlBase({cell, value, id, optionsLoaded, onCellChange, vi /* The mapping does not need Form* components as labels are not needed for grid cells */ switch(cell) { case 'int': - return ; + return ; case 'numeric': - return ; + return ; case 'text': return ; case 'password': diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx index 1d7321880..35ca82daf 100644 --- a/web/pgadmin/static/js/components/FormComponents.jsx +++ b/web/pgadmin/static/js/components/FormComponents.jsx @@ -291,11 +291,22 @@ FormInputDateTimePicker.propTypes = { /* Use forwardRef to pass ref prop to OutlinedInput */ export const InputText = forwardRef(({ - cid, helpid, readonly, disabled, maxlength=255, value, onChange, controlProps, ...props}, ref)=>{ + cid, helpid, readonly, disabled, maxlength=255, value, onChange, controlProps, type, ...props}, ref)=>{ const classes = useStyles(); + const patterns = { + 'numeric': '^-?[0-9]\\d*\\.?\\d*$', + 'int': '^-?[0-9]\\d*$', + }; + let onChangeFinal = (e)=>{ + let changeVal = e.target.value; - let onChangeFinal = (changeVal)=>{ + /* For type number, we set type as tel with number regex to get validity.*/ + if(['numeric', 'int'].indexOf(type) > -1) { + if(!e.target.validity.valid && changeVal !== '' && changeVal !== '-') { + return; + } + } if(controlProps?.formatter) { changeVal = controlProps.formatter.toRaw(changeVal); } @@ -317,6 +328,7 @@ export const InputText = forwardRef(({ id: cid, maxLength: maxlength, 'aria-describedby': helpid, + ...(type ? {pattern: patterns[type]} : {}) }} readOnly={Boolean(readonly)} disabled={Boolean(disabled)} @@ -326,6 +338,7 @@ export const InputText = forwardRef(({ onChange={onChangeFinal} {...controlProps} {...props} + {...(['numeric', 'int'].indexOf(type) > -1 ? {type: 'tel'} : {})} /> ); }); @@ -340,6 +353,7 @@ InputText.propTypes = { value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), onChange: PropTypes.func, controlProps: PropTypes.object, + type: PropTypes.string, }; export function FormInputText({hasError, required, label, className, helpMessage, testcid, ...props}) { diff --git a/web/regression/javascript/SchemaView/SchemaView.spec.js b/web/regression/javascript/SchemaView/SchemaView.spec.js index 05471bf92..fd1a48728 100644 --- a/web/regression/javascript/SchemaView/SchemaView.spec.js +++ b/web/regression/javascript/SchemaView/SchemaView.spec.js @@ -43,6 +43,16 @@ function getSchemaAllTypes() { describe('SchemaView', ()=>{ let mount; + let numberChangeEvent = (value)=>{ + return { + target: { + value: value, + validity: { + valid: true, + } + } + }; + }; /* Use createMount so that material ui components gets the required context */ /* https://material-ui.com/guides/testing/#api */ @@ -91,7 +101,7 @@ describe('SchemaView', ()=>{ }, simulateValidData = ()=>{ ctrl.find('MappedFormControl[id="field1"]').find('input').simulate('change', {target: {value: 'val1'}}); - ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', {target: {value: '2'}}); + ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', numberChangeEvent('2')); ctrl.find('MappedFormControl[id="field5"]').find('textarea').simulate('change', {target: {value: 'val5'}}); /* Add a row */ ctrl.find('DataGridView').find('PgIconButton[data-test="add-row"]').find('button').simulate('click'); @@ -117,7 +127,7 @@ describe('SchemaView', ()=>{ }); it('change text', (done)=>{ - ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', {target: {value: '2'}}); + ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', numberChangeEvent('2')); setTimeout(()=>{ ctrl.update(); /* Error should come for field1 as it is empty and noEmpty true */ @@ -210,7 +220,7 @@ describe('SchemaView', ()=>{ }); it('data invalid', (done)=>{ - ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', {target: {value: '2'}}); + ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', numberChangeEvent('2')); ctrl.find('ForwardRef(Tab)[label="SQL"]').find('button').simulate('click'); setTimeout(()=>{ ctrl.update(); @@ -240,7 +250,7 @@ describe('SchemaView', ()=>{ expect(onSave.calls.argsFor(0)[1]).toEqual({ id: undefined, field1: 'val1', - field2: 2, + field2: '2', field5: 'val5', fieldcoll: [ {field3: null, field4: null, field5: 'rval51'},