From a1832d04259f41f8e5e738b3f7c3d0c8d8084919 Mon Sep 17 00:00:00 2001 From: JEFFREY-Bonson Date: Tue, 6 Feb 2024 10:07:57 +0530 Subject: [PATCH] Fix for duplicate field names and render validation messages for service dialogs --- src/dialog-editor/components/abstractModal.ts | 1 + .../components/modal-field/field.html | 6 ++- .../modal-field/modalFieldComponent.ts | 15 +++++++ .../components/modal/modalComponent.ts | 43 ++++++++++++++----- .../services/dialogValidationService.ts | 24 +++++++++-- src/styles/ui-components.scss | 16 +++++++ 6 files changed, 91 insertions(+), 14 deletions(-) diff --git a/src/dialog-editor/components/abstractModal.ts b/src/dialog-editor/components/abstractModal.ts index 684cb04be5..5e6e77a035 100644 --- a/src/dialog-editor/components/abstractModal.ts +++ b/src/dialog-editor/components/abstractModal.ts @@ -36,6 +36,7 @@ export class AbstractModal { uibModalInstance: '<', treeOptions: '<', modalUnchanged: '<', + fieldDuplicates: '<', validation: '<', }; } diff --git a/src/dialog-editor/components/modal-field/field.html b/src/dialog-editor/components/modal-field/field.html index 6c59279237..1ef7be19d3 100644 --- a/src/dialog-editor/components/modal-field/field.html +++ b/src/dialog-editor/components/modal-field/field.html @@ -6,6 +6,10 @@ diff --git a/src/dialog-editor/components/modal-field/modalFieldComponent.ts b/src/dialog-editor/components/modal-field/modalFieldComponent.ts index 6a0ec29144..db81c36189 100644 --- a/src/dialog-editor/components/modal-field/modalFieldComponent.ts +++ b/src/dialog-editor/components/modal-field/modalFieldComponent.ts @@ -149,6 +149,21 @@ class ModalFieldController extends ModalController { this.treeOptions.show = false; } + /** Function to get notification messages for options modal box if any. */ + public modalNotification() { + const notice = { error: false, message: undefined }; + + if (!this.modalFieldIsValid() && this.validation.invalid && this.validation.invalid.message) { + notice.message = this.validation.invalid.message; + notice.error = true; + } else if (this.modalData.validationMessage) { + notice.message = this.modalData.validationMessage; + notice.error = true; + } + + return notice; + } + public modalFieldIsValid() { return this.validation.validateField(this.modalData); } diff --git a/src/dialog-editor/components/modal/modalComponent.ts b/src/dialog-editor/components/modal/modalComponent.ts index faee10226d..c87b49ab63 100644 --- a/src/dialog-editor/components/modal/modalComponent.ts +++ b/src/dialog-editor/components/modal/modalComponent.ts @@ -140,24 +140,46 @@ class ModalController { return this.modalTab === tab; } + /** + * Check for duplicate field names. + * @memberof ModalController + * @function modalUnchanged + */ + public fieldDuplicates() { + const fields: string[] = []; + const {tabId, boxId, fieldId} = this.elementInfo; + const dialogTabs = this.DialogEditor.getDialogTabs(); + this.DialogEditor.getDialogTabs().forEach((tabs, tabIndex) => ( + tabs.dialog_groups.forEach((group, groupIndex) => ( + group.dialog_fields.forEach((field, fieldIndex) => { + const name = (tabId === tabIndex && boxId === groupIndex && fieldId === fieldIndex) + ? this.modalData.name + : field.name; + fields.push(name); + }) + )) + )); + const isDuplicate = fields.filter((item) => item === this.modalData.name).length > 1 ? true : false; + this.modalData.validationMessage = isDuplicate ? sprintf(__('%s is used by another field'), this.modalData.name) : undefined; + return isDuplicate; + } + /** * Check for changes in the modal. * @memberof ModalController * @function modalUnchanged */ public modalUnchanged() { + const {boxId, fieldId, type} = this.elementInfo; + const dialogTabs = this.DialogEditor.getDialogTabs(); + const activeTab = dialogTabs[this.DialogEditor.activeTab]; + const activeBox = activeTab.dialog_groups[boxId]; let elements = { - tab: this.DialogEditor.getDialogTabs()[ - this.DialogEditor.activeTab], - box: this.DialogEditor.getDialogTabs()[ - this.DialogEditor.activeTab].dialog_groups[ - this.elementInfo.boxId], - field: _.get(this.DialogEditor.getDialogTabs()[ - this.DialogEditor.activeTab].dialog_groups[ - this.elementInfo.boxId], 'dialog_fields[' + this.elementInfo.fieldId + ']') + tab: activeTab, + box: activeBox, + field: _.get(activeBox, 'dialog_fields[' + fieldId + ']') }; - return this.elementInfo.type in elements && - _.isMatch(elements[this.elementInfo.type], this.modalData); + return type in elements && _.isMatch(elements[type], this.modalData); } /** @@ -338,6 +360,7 @@ class ModalController { update-dialog-field-responders="modalCtrl.parent.updateDialogFieldResponders" setup-category-options="modalCtrl.parent.setupCategoryOptions" modal-unchanged="modalCtrl.parent.modalUnchanged" + field-duplicates="modalCtrl.parent.fieldDuplicates" validation="modalCtrl.validation" >`; } diff --git a/src/dialog-editor/services/dialogValidationService.ts b/src/dialog-editor/services/dialogValidationService.ts index 06fdb16547..3c8902bc90 100644 --- a/src/dialog-editor/services/dialogValidationService.ts +++ b/src/dialog-editor/services/dialogValidationService.ts @@ -6,6 +6,7 @@ const tagHasCategory = (field) => field.options && field.options.category_id; export default class DialogValidationService { public invalid: any = {}; + public dialogFields: any = []; private validators: any = {}; constructor() { @@ -99,12 +100,31 @@ export default class DialogValidationService { return _.every(this.validators.fields, this.validate(field, label, local)); } + /** + * Run validations across each dialog field elements and check for duplicate field names. + * @memberof DialogValidationService + * @function validateDialogFields + */ + public validateDialogFields(field: any) { + if (!this.validateField(field)) { + return false; + } + const isDuplicate = this.dialogFields.includes(field.name); + if (isDuplicate) { + this.invalid.message = sprintf(__('Duplicate field name found: %s'), field.name); + return false; + } + this.dialogFields.push(field.name); + return true; + } + /** * Run validations across each dialog elements. * @memberof DialogValidationService * @function dialogIsValid */ public dialogIsValid(dialogData: any) { + this.dialogFields = []; this.invalid.message = null; return _.every(dialogData, dialog => @@ -113,9 +133,7 @@ export default class DialogValidationService { this.validateTab(tab) && _.every((tab).dialog_groups, group => this.validateGroup(group) && - _.every((group).dialog_fields, field => - this.validateField(field) - ) + group.dialog_fields.every((field) => this.validateDialogFields(field)) ) ) ); diff --git a/src/styles/ui-components.scss b/src/styles/ui-components.scss index 29d8fdc619..e21d6e4a32 100644 --- a/src/styles/ui-components.scss +++ b/src/styles/ui-components.scss @@ -5,6 +5,22 @@ /* Begin Patternfly Tab overrides used in the Dialog Editor */ +.dialog-editor-tab-notification { + color: #363636; + font-weight: bold; + background: #ffe6e7; + border: 1px solid #cd0000; + padding: 10px; + margin-bottom: 10px; + display: flex; + align-items: center; + gap: 10px; + + i { + font-size: 16px; + } +} + .dialog-editor-tab-list { margin-bottom: 20px !important; }