From f508b564c51843bc6bf0e9eff19df241cb6abeae Mon Sep 17 00:00:00 2001 From: devketanpro Date: Fri, 21 Apr 2023 16:45:14 +0530 Subject: [PATCH 1/4] Fix : When using multilingual option for event fields, all required language fields should be validated [SDESK-6869] --- client/validators/profile.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/validators/profile.ts b/client/validators/profile.ts index 9e0fe31ba..901724b82 100644 --- a/client/validators/profile.ts +++ b/client/validators/profile.ts @@ -1,7 +1,7 @@ import {get, isEmpty} from 'lodash'; import {gettext} from '../utils'; -export const formProfile = ({field, value, profile, errors, messages}) => { +export const formProfile = ({field, value, profile, errors, messages, diff}) => { // If the field is not enabled or no schema defined, then simply return if (!get(profile, `editor.${field}.enabled`, false) || !get(profile, `schema.${field}`)) { return; @@ -11,6 +11,8 @@ export const formProfile = ({field, value, profile, errors, messages}) => { const fieldValue = (typeof value === 'string') ? value.trim() : value; + const field_value = (diff?.translations || []).filter((e) => e.field === field); + if (!schema.required && get(fieldValue, length, 0) < 1) { return; } @@ -38,6 +40,14 @@ export const formProfile = ({field, value, profile, errors, messages}) => { } else if (schema.required && (typeof fieldValue === 'number' ? !fieldValue : isEmpty(fieldValue))) { errors[field] = gettext('This field is required'); messages.push(gettext('{{ name }} is a required field', {name: fieldLabel})); + } else if (schema.required && schema.multilingual) { + const errorMessage = gettext(`${fieldLabel} is a required field`); + + if (field !== 'language' && diff?.languages?.length !== field_value?.length || field_value.some((obj + ) => obj.value === '')) { + errors[field] = gettext('This field is required'); + messages.push(errorMessage); + } } else if (get(schema, 'minlength', 0) > 0 && get(fieldValue, 'length', 0) < schema.minlength) { if (get(schema, 'type', 'string') === 'list') { errors[field] = gettext('Not enough'); From 7e4cdb40c3ef9f9ba6ad5094d033636f1ee584f1 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 24 Apr 2023 18:45:37 +0530 Subject: [PATCH 2/4] refactore code --- client/validators/profile.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/validators/profile.ts b/client/validators/profile.ts index 901724b82..8a47810d7 100644 --- a/client/validators/profile.ts +++ b/client/validators/profile.ts @@ -11,8 +11,6 @@ export const formProfile = ({field, value, profile, errors, messages, diff}) => const fieldValue = (typeof value === 'string') ? value.trim() : value; - const field_value = (diff?.translations || []).filter((e) => e.field === field); - if (!schema.required && get(fieldValue, length, 0) < 1) { return; } @@ -41,12 +39,13 @@ export const formProfile = ({field, value, profile, errors, messages, diff}) => errors[field] = gettext('This field is required'); messages.push(gettext('{{ name }} is a required field', {name: fieldLabel})); } else if (schema.required && schema.multilingual) { - const errorMessage = gettext(`${fieldLabel} is a required field`); - - if (field !== 'language' && diff?.languages?.length !== field_value?.length || field_value.some((obj - ) => obj.value === '')) { + if ( + field !== 'language' && + diff?.languages?.length !== (diff?.translations || []).filter((e) => e.field === field).length || + (diff?.translations || []).some((obj) => obj.field === field && obj.value === '') + ) { errors[field] = gettext('This field is required'); - messages.push(errorMessage); + messages.push(gettext('{{ name }} is a required field', {name: fieldLabel})); } } else if (get(schema, 'minlength', 0) > 0 && get(fieldValue, 'length', 0) < schema.minlength) { if (get(schema, 'type', 'string') === 'list') { From 21b54a60af035c7ed63c361fab918f391c46343b Mon Sep 17 00:00:00 2001 From: devketanpro Date: Wed, 26 Apr 2023 09:10:30 +0530 Subject: [PATCH 3/4] Address comment --- client/validators/profile.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/client/validators/profile.ts b/client/validators/profile.ts index 8a47810d7..55e94d1d4 100644 --- a/client/validators/profile.ts +++ b/client/validators/profile.ts @@ -35,18 +35,29 @@ export const formProfile = ({field, value, profile, errors, messages, diff}) => errors[field] = gettext('Too long'); messages.push(gettext('{{ name }} is too long', {name: fieldLabel})); } - } else if (schema.required && (typeof fieldValue === 'number' ? !fieldValue : isEmpty(fieldValue))) { + } else if (schema.required && !schema.multilingual && ( + typeof fieldValue === 'number' ? !fieldValue : isEmpty(fieldValue))) { errors[field] = gettext('This field is required'); messages.push(gettext('{{ name }} is a required field', {name: fieldLabel})); - } else if (schema.required && schema.multilingual) { - if ( - field !== 'language' && - diff?.languages?.length !== (diff?.translations || []).filter((e) => e.field === field).length || - (diff?.translations || []).some((obj) => obj.field === field && obj.value === '') - ) { + } else if (schema.required && schema.multilingual && field !== 'language') { + const multilingualField = diff?.translations?.filter((e) => e.field === field) || []; + const missingLangs = diff?.languages?.filter((lang) => !multilingualField.some( + (obj) => obj.language === lang)) || []; + const emptyValues = multilingualField.filter((obj) => obj.value === ''); + + missingLangs.forEach((qcode) => { + const name = `${fieldLabel} (${qcode})`; + errors[field] = gettext('This field is required'); - messages.push(gettext('{{ name }} is a required field', {name: fieldLabel})); - } + messages.push(gettext('{{ name }} is a required field', {name})); + }); + + emptyValues.forEach(({language}) => { + const name = `${fieldLabel} (${language})`; + + errors[field] = gettext('This field is required'); + messages.push(gettext('{{ name }} is a required field', {name})); + }); } else if (get(schema, 'minlength', 0) > 0 && get(fieldValue, 'length', 0) < schema.minlength) { if (get(schema, 'type', 'string') === 'list') { errors[field] = gettext('Not enough'); From 32009737d202e8a530ca4c95bce5226148c4d2b0 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Fri, 28 Apr 2023 11:39:09 +0530 Subject: [PATCH 4/4] Optimize multilingual validation --- client/validators/profile.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/client/validators/profile.ts b/client/validators/profile.ts index 55e94d1d4..b4d849945 100644 --- a/client/validators/profile.ts +++ b/client/validators/profile.ts @@ -41,23 +41,35 @@ export const formProfile = ({field, value, profile, errors, messages, diff}) => messages.push(gettext('{{ name }} is a required field', {name: fieldLabel})); } else if (schema.required && schema.multilingual && field !== 'language') { const multilingualField = diff?.translations?.filter((e) => e.field === field) || []; - const missingLangs = diff?.languages?.filter((lang) => !multilingualField.some( - (obj) => obj.language === lang)) || []; + const missingLangs = diff?.languages?.filter((lang) => !multilingualField.some(( + obj) => obj.language === lang)) || []; const emptyValues = multilingualField.filter((obj) => obj.value === ''); missingLangs.forEach((qcode) => { const name = `${fieldLabel} (${qcode})`; + const fieldError = `${field}.${qcode}`; - errors[field] = gettext('This field is required'); + errors[fieldError] = gettext('This field is required'); messages.push(gettext('{{ name }} is a required field', {name})); }); emptyValues.forEach(({language}) => { const name = `${fieldLabel} (${language})`; + const fieldError = `${field}.${language}`; - errors[field] = gettext('This field is required'); + errors[fieldError] = gettext('This field is required'); messages.push(gettext('{{ name }} is a required field', {name})); }); + + Object.keys(errors).forEach((fieldError) => { + const [fieldName, lang] = fieldError.split('.'); + + if (fieldName === field && diff.languages.includes(lang)) { + if (!missingLangs.includes(lang) && !emptyValues.some((obj) => obj.language === lang)) { + delete errors[fieldError]; + } + } + }); } else if (get(schema, 'minlength', 0) > 0 && get(fieldValue, 'length', 0) < schema.minlength) { if (get(schema, 'type', 'string') === 'list') { errors[field] = gettext('Not enough');