Skip to content

Commit

Permalink
Fix for duplicate field names and render validation messages for serv…
Browse files Browse the repository at this point in the history
…ice dialogs
  • Loading branch information
jeffibm committed Feb 13, 2024
1 parent f1aca13 commit a1832d0
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/dialog-editor/components/abstractModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class AbstractModal {
uibModalInstance: '<',
treeOptions: '<',
modalUnchanged: '<',
fieldDuplicates: '<',
validation: '<',
};
}
6 changes: 5 additions & 1 deletion src/dialog-editor/components/modal-field/field.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ <h4 class="modal-title" id="myModalLabel" translate>Edit Field Details</h4>
</div>

<div class="modal-body">
<div class="dialog-editor-tab-notification" ng-if="vm.modalNotification().error">
<i class="pficon pficon-error-circle-o"></i>
{{vm.modalNotification().message}}
</div>
<ul class="nav nav-tabs dialog-editor-tab-list">
<li ng-class="{active:vm.modalTabIsSet('element_information')}">
<a ng-click="vm.modalTabSet('element_information')" translate>Field Information</a>
Expand Down Expand Up @@ -141,7 +145,7 @@ <h4 class="modal-title" id="myModalLabel" translate>Edit Field Details</h4>
<button type="button"
class="btn btn-primary"
ng-click="vm.closeModal(true)"
ng-disabled="vm.modalUnchanged() || !vm.modalFieldIsValid()"
ng-disabled="vm.modalUnchanged() || vm.fieldDuplicates() || !vm.modalFieldIsValid()"
ng-attr-title="{{vm.modalFieldIsValid() ? '' : vm.validation.invalid.message}}" translate>Save
</button>
</div>
15 changes: 15 additions & 0 deletions src/dialog-editor/components/modal-field/modalFieldComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
43 changes: 33 additions & 10 deletions src/dialog-editor/components/modal/modalComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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"
></${component}>`;
}
Expand Down
24 changes: 21 additions & 3 deletions src/dialog-editor/services/dialogValidationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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 =>
Expand All @@ -113,9 +133,7 @@ export default class DialogValidationService {
this.validateTab(tab) &&
_.every((<any>tab).dialog_groups, group =>
this.validateGroup(group) &&
_.every((<any>group).dialog_fields, field =>
this.validateField(field)
)
group.dialog_fields.every((field) => this.validateDialogFields(field))
)
)
);
Expand Down
16 changes: 16 additions & 0 deletions src/styles/ui-components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit a1832d0

Please sign in to comment.