From 3ccf0a6ca61a940e3eb4d9d33dcbc13dd6873509 Mon Sep 17 00:00:00 2001 From: Irakli Chalagashvili Date: Thu, 26 Jan 2023 16:32:14 +0400 Subject: [PATCH] ENG-4362 refactor validations and fix tech debt --- src/ui/common/attributes/AttributeInfo.js | 4 +- .../user-profile/common/UserProfileField.js | 78 ++++++++++--------- src/ui/user-profile/common/UserProfileForm.js | 2 +- src/ui/users/my-profile/MyProfileEditForm.js | 63 +++++---------- 4 files changed, 66 insertions(+), 81 deletions(-) diff --git a/src/ui/common/attributes/AttributeInfo.js b/src/ui/common/attributes/AttributeInfo.js index 06ef4fcbc..c18a87313 100644 --- a/src/ui/common/attributes/AttributeInfo.js +++ b/src/ui/common/attributes/AttributeInfo.js @@ -9,7 +9,7 @@ import FormLabel from 'ui/common/form/FormLabel'; import SwitchRenderer from 'ui/common/form/SwitchRenderer'; import { MODE_EDIT, MODE_ADD } from 'state/data-types/const'; -const maxLength10 = maxLength(10); +const maxLength15 = maxLength(15); const maxLength50 = maxLength(50); const AttributeInfo = ({ isSearchable, isIndexable, mode }) => { @@ -65,7 +65,7 @@ const AttributeInfo = ({ isSearchable, isIndexable, mode }) => { label={ } - validate={[required, maxLength10]} + validate={[required, maxLength15]} disabled={mode === MODE_EDIT} /> { } }; -const userProfileValidators = {}; +export const generateValidatorFunc = ( + value, validatorFuncName, validatorFunc, + validatorArray, parseValueFunc, customErrorId, +) => { + const userProfileValidators = {}; + if (value === null || value === undefined) { + return; + } + const parsedValue = parseValueFunc ? parseValueFunc(value) : value; + if (!userProfileValidators[validatorFuncName]) { + userProfileValidators[validatorFuncName] = {}; + } + if (!userProfileValidators[validatorFuncName][value]) { + userProfileValidators[validatorFuncName] = { + ...userProfileValidators[validatorFuncName], + [value]: validatorFunc(parsedValue, customErrorId), + }; + } + validatorArray.push(userProfileValidators[validatorFuncName][value]); +}; -const UserProfileField = ({ attribute, intl }) => { +export const UserProfileField = ({ attribute, intl, disabled }) => { const { validationRules } = attribute || {}; const { minLength: textMinLen, maxLength: textMaxLen, regex, rangeEndNumber, rangeStartNumber, } = validationRules || {}; - const generateValidatorFunc = ( - value, validatorFuncName, validatorFunc, - validatorArray, parseValueFunc, customErrorId, - ) => { - if (value === null || value === undefined) { - return; - } - const parsedValue = parseValueFunc ? parseValueFunc(value) : value; - if (!userProfileValidators[validatorFuncName]) { - userProfileValidators[validatorFuncName] = {}; - } - if (!userProfileValidators[validatorFuncName][value]) { - userProfileValidators[validatorFuncName] = { - ...userProfileValidators[validatorFuncName], - [value]: validatorFunc(parsedValue, customErrorId), - }; - } - validatorArray.push(userProfileValidators[validatorFuncName][value]); - }; - - const validateArray = [...(attribute.mandatory ? [required] : [])]; - generateValidatorFunc(textMinLen, 'minLength', minLength, validateArray); - generateValidatorFunc(textMaxLen, 'maxLength', maxLength, validateArray); - generateValidatorFunc( - regex, 'regex', matchRegex, validateArray, RegexParser, - attribute.type === 'Email' && 'validateForm.email', - ); - generateValidatorFunc(rangeEndNumber, 'rangeEndNumber', maxValue, validateArray); - generateValidatorFunc(rangeStartNumber, 'rangeStartNumber', minValue, validateArray); + const vArray = useMemo(() => { + const validateArray = [...(attribute.mandatory ? [required] : [])]; + generateValidatorFunc(textMinLen, 'minLength', minLength, validateArray); + generateValidatorFunc(textMaxLen, 'maxLength', maxLength, validateArray); + generateValidatorFunc( + regex, 'regex', matchRegex, validateArray, RegexParser, + attribute.type === 'Email' && 'validateForm.email', + ); + generateValidatorFunc(rangeEndNumber, 'rangeEndNumber', maxValue, validateArray); + generateValidatorFunc(rangeStartNumber, 'rangeStartNumber', minValue, validateArray); + return validateArray; + }, [attribute.mandatory, attribute.type, rangeEndNumber, rangeStartNumber, + regex, textMaxLen, textMinLen]); + return ( { helpText={getHelpMessage(attribute.validationRules, intl)} required={attribute.mandatory} />} - validate={validateArray} + validate={vArray} readOnly={readOnlyFields.includes(attribute.code)} data-testid={`UserProfileForm__${attribute.code}Field`} + disabled={disabled} />); }; @@ -154,6 +159,11 @@ const basicAttributeShape = PropTypes.shape({ UserProfileField.propTypes = { attribute: basicAttributeShape.isRequired, intl: intlShape.isRequired, + disabled: PropTypes.bool, +}; + +UserProfileField.defaultProps = { + disabled: false, }; export const CompositeField = ({ @@ -221,5 +231,3 @@ CompositeField.defaultProps = { fieldName: '', noLabel: false, }; - -export default UserProfileField; diff --git a/src/ui/user-profile/common/UserProfileForm.js b/src/ui/user-profile/common/UserProfileForm.js index d3d9d0289..7a63be9e6 100644 --- a/src/ui/user-profile/common/UserProfileForm.js +++ b/src/ui/user-profile/common/UserProfileForm.js @@ -6,7 +6,7 @@ import { Button, Row, Col, FormGroup } from 'patternfly-react'; import { required } from '@entando/utils'; import { FormattedMessage, defineMessages, injectIntl, intlShape } from 'react-intl'; import RenderTextInput from 'ui/common/form/RenderTextInput'; -import UserProfileField, { CompositeField } from 'ui/user-profile/common/UserProfileField'; +import { UserProfileField, CompositeField } from 'ui/user-profile/common/UserProfileField'; import FormLabel from 'ui/common/form/FormLabel'; import RenderListField from 'ui/common/form/RenderListField'; diff --git a/src/ui/users/my-profile/MyProfileEditForm.js b/src/ui/users/my-profile/MyProfileEditForm.js index 899767e16..276e7a4a6 100644 --- a/src/ui/users/my-profile/MyProfileEditForm.js +++ b/src/ui/users/my-profile/MyProfileEditForm.js @@ -1,7 +1,7 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import get from 'lodash/get'; -import { reduxForm, Field, FieldArray, FormSection } from 'redux-form'; +import { reduxForm, FieldArray, FormSection } from 'redux-form'; import { FormattedMessage, defineMessages, injectIntl, intlShape } from 'react-intl'; import { Panel } from 'react-bootstrap'; import { Form, Button, Row, Col } from 'patternfly-react'; @@ -15,9 +15,7 @@ import { TYPE_BOOLEAN, TYPE_THREESTATE, TYPE_ENUMERATOR, TYPE_ENUMERATOR_MAP, TYPE_MONOLIST, TYPE_LIST, TYPE_COMPOSITE, } from 'state/data-types/const'; -import { getComponentType } from 'helpers/entities'; - -const defaultAttrCodes = ['fullname', 'email']; +import { UserProfileField } from 'ui/user-profile/common/UserProfileField'; const getComponentOptions = (component, intl) => { const booleanOptions = getTranslatedOptions(intl, BOOLEAN_OPTIONS); @@ -74,42 +72,6 @@ const getHelpMessage = (validationRules, intl) => { return null; }; -const field = (intl, attribute, disabled) => { - const labelProp = defaultAttrCodes.includes(attribute.code) ? ({ - labelId: `user.table.${attribute.code}`, - }) : ({ - labelText: attribute.name, - }); - - return ( - } - disabled={disabled} - /> - ); -}; - -const renderCompositeAttribute = (intl, compositeAttributes, disabled) => - compositeAttributes.map(attribute => field(intl, attribute, disabled)); - export class MyProfileEditFormBody extends Component { constructor(props) { super(props); @@ -151,11 +113,23 @@ export class MyProfileEditFormBody extends Component { render() { const { profileTypesAttributes, defaultLanguage, languages, intl, userEmail, onChangeProfilePicture, - userProfileForm, + userProfileForm, invalid, submitting, } = this.props; const { editMode } = this.state; + const field = (attribute, disabled) => ( + + ); + + const renderCompositeAttribute = (compositeAttributes, disabled) => + compositeAttributes.map(attribute => field(attribute, disabled)); + const renderFieldArray = (attributeCode, attribute, component, language) => ( - { renderCompositeAttribute(intl, attribute.compositeAttributes, !editMode)} + {renderCompositeAttribute(attribute.compositeAttributes, !editMode)} @@ -223,7 +197,7 @@ export class MyProfileEditFormBody extends Component { ); } - return field(intl, attribute, !editMode); + return field(attribute, !editMode); }); const { profilepicture } = userProfileForm; @@ -250,6 +224,7 @@ export class MyProfileEditFormBody extends Component { type="submit" bsStyle="primary" data-testid="profile_saveBtn" + disabled={invalid || submitting} > @@ -324,6 +299,8 @@ MyProfileEditFormBody.propTypes = { profilepicture: PropTypes.string, }), onChangeProfilePicture: PropTypes.func.isRequired, + invalid: PropTypes.bool.isRequired, + submitting: PropTypes.bool.isRequired, }; MyProfileEditFormBody.defaultProps = {