feat: Support Regex validation for custom attributes (#7856)
This allows a user to add/update a custom regex and a cue while defining custom attributes(Only applicable for type- text). While adding/editing custom attributes, the values are validated against the attribute definition regex, and if it is incorrect, a cue message or default error message is shown and restricts invalid values from being saved. Fixes: #6866
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
emoji=""
|
||||
:value="attribute.value"
|
||||
:show-actions="true"
|
||||
:attribute-regex="attribute.regex_pattern"
|
||||
:regex-cue="attribute.regex_cue"
|
||||
:class="attributeClass"
|
||||
@update="onUpdate"
|
||||
@delete="onDelete"
|
||||
|
||||
@@ -86,6 +86,30 @@
|
||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LIST.ERROR') }}
|
||||
</label>
|
||||
</div>
|
||||
<div v-if="isAttributeTypeText">
|
||||
<input
|
||||
v-model="regexEnabled"
|
||||
type="checkbox"
|
||||
@input="toggleRegexEnabled"
|
||||
/>
|
||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.ENABLE_REGEX.LABEL') }}
|
||||
</div>
|
||||
<woot-input
|
||||
v-if="isAttributeTypeText && isRegexEnabled"
|
||||
v-model="regexPattern"
|
||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.LABEL')"
|
||||
type="text"
|
||||
:placeholder="
|
||||
$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.PLACEHOLDER')
|
||||
"
|
||||
/>
|
||||
<woot-input
|
||||
v-if="isAttributeTypeText && isRegexEnabled"
|
||||
v-model="regexCue"
|
||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.LABEL')"
|
||||
type="text"
|
||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.PLACEHOLDER')"
|
||||
/>
|
||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||
<woot-submit-button
|
||||
:disabled="isButtonDisabled"
|
||||
@@ -124,6 +148,9 @@ export default {
|
||||
attributeModel: 0,
|
||||
attributeType: 0,
|
||||
attributeKey: '',
|
||||
regexPattern: null,
|
||||
regexCue: null,
|
||||
regexEnabled: false,
|
||||
models: ATTRIBUTE_MODELS,
|
||||
types: ATTRIBUTE_TYPES,
|
||||
values: [],
|
||||
@@ -163,6 +190,12 @@ export default {
|
||||
isAttributeTypeList() {
|
||||
return this.attributeType === 6;
|
||||
},
|
||||
isAttributeTypeText() {
|
||||
return this.attributeType === 0;
|
||||
},
|
||||
isRegexEnabled() {
|
||||
return this.regexEnabled;
|
||||
},
|
||||
},
|
||||
|
||||
validations: {
|
||||
@@ -201,11 +234,18 @@ export default {
|
||||
onDisplayNameChange() {
|
||||
this.attributeKey = convertToAttributeSlug(this.displayName);
|
||||
},
|
||||
toggleRegexEnabled() {
|
||||
this.regexEnabled = !this.regexEnabled;
|
||||
},
|
||||
async addAttributes() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
if (!this.regexEnabled) {
|
||||
this.regexPattern = null;
|
||||
this.regexCue = null;
|
||||
}
|
||||
try {
|
||||
await this.$store.dispatch('attributes/create', {
|
||||
attribute_display_name: this.displayName,
|
||||
@@ -214,6 +254,10 @@ export default {
|
||||
attribute_display_type: this.attributeType,
|
||||
attribute_key: this.attributeKey,
|
||||
attribute_values: this.attributeListValues,
|
||||
regex_pattern: this.regexPattern
|
||||
? new RegExp(this.regexPattern).toString()
|
||||
: null,
|
||||
regex_cue: this.regexCue,
|
||||
});
|
||||
this.alertMessage = this.$t('ATTRIBUTES_MGMT.ADD.API.SUCCESS_MESSAGE');
|
||||
this.onClose();
|
||||
|
||||
@@ -70,6 +70,30 @@
|
||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LIST.ERROR') }}
|
||||
</label>
|
||||
</div>
|
||||
<div v-if="isAttributeTypeText">
|
||||
<input
|
||||
v-model="regexEnabled"
|
||||
type="checkbox"
|
||||
@input="toggleRegexEnabled"
|
||||
/>
|
||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.ENABLE_REGEX.LABEL') }}
|
||||
</div>
|
||||
<woot-input
|
||||
v-if="isAttributeTypeText && isRegexEnabled"
|
||||
v-model="regexPattern"
|
||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.LABEL')"
|
||||
type="text"
|
||||
:placeholder="
|
||||
$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.PLACEHOLDER')
|
||||
"
|
||||
/>
|
||||
<woot-input
|
||||
v-if="isAttributeTypeText && isRegexEnabled"
|
||||
v-model="regexCue"
|
||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.LABEL')"
|
||||
type="text"
|
||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.PLACEHOLDER')"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||
<woot-button :is-loading="isUpdating" :disabled="isButtonDisabled">
|
||||
@@ -88,9 +112,10 @@ import { mapGetters } from 'vuex';
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import { ATTRIBUTE_TYPES } from './constants';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import customAttributeMixin from '../../../../mixins/customAttributeMixin';
|
||||
export default {
|
||||
components: {},
|
||||
mixins: [alertMixin],
|
||||
mixins: [alertMixin, customAttributeMixin],
|
||||
props: {
|
||||
selectedAttribute: {
|
||||
type: Object,
|
||||
@@ -106,6 +131,9 @@ export default {
|
||||
displayName: '',
|
||||
description: '',
|
||||
attributeType: 0,
|
||||
regexPattern: null,
|
||||
regexCue: null,
|
||||
regexEnabled: false,
|
||||
types: ATTRIBUTE_TYPES,
|
||||
show: true,
|
||||
attributeKey: '',
|
||||
@@ -152,6 +180,7 @@ export default {
|
||||
this.isAttributeTypeList && this.isTouched && this.values.length === 0
|
||||
);
|
||||
},
|
||||
|
||||
pageTitle() {
|
||||
return `${this.$t('ATTRIBUTES_MGMT.EDIT.TITLE')} - ${
|
||||
this.selectedAttribute.attribute_display_name
|
||||
@@ -173,6 +202,12 @@ export default {
|
||||
isAttributeTypeList() {
|
||||
return this.attributeType === 6;
|
||||
},
|
||||
isAttributeTypeText() {
|
||||
return this.attributeType === 0;
|
||||
},
|
||||
isRegexEnabled() {
|
||||
return this.regexEnabled;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setFormValues();
|
||||
@@ -189,10 +224,16 @@ export default {
|
||||
this.$refs.tagInput.$el.focus();
|
||||
},
|
||||
setFormValues() {
|
||||
const regexPattern = this.selectedAttribute.regex_pattern
|
||||
? this.getRegexp(this.selectedAttribute.regex_pattern).source
|
||||
: null;
|
||||
this.displayName = this.selectedAttribute.attribute_display_name;
|
||||
this.description = this.selectedAttribute.attribute_description;
|
||||
this.attributeType = this.selectedAttributeType;
|
||||
this.attributeKey = this.selectedAttribute.attribute_key;
|
||||
this.regexPattern = regexPattern;
|
||||
this.regexCue = this.selectedAttribute.regex_cue;
|
||||
this.regexEnabled = regexPattern != null;
|
||||
this.values = this.setAttributeListValue;
|
||||
},
|
||||
async editAttributes() {
|
||||
@@ -200,14 +241,21 @@ export default {
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
if (!this.regexEnabled) {
|
||||
this.regexPattern = null;
|
||||
this.regexCue = null;
|
||||
}
|
||||
try {
|
||||
await this.$store.dispatch('attributes/update', {
|
||||
id: this.selectedAttribute.id,
|
||||
attribute_description: this.description,
|
||||
attribute_display_name: this.displayName,
|
||||
attribute_values: this.updatedAttributeListValues,
|
||||
regex_pattern: this.regexPattern
|
||||
? new RegExp(this.regexPattern).toString()
|
||||
: null,
|
||||
regex_cue: this.regexCue,
|
||||
});
|
||||
|
||||
this.alertMessage = this.$t('ATTRIBUTES_MGMT.EDIT.API.SUCCESS_MESSAGE');
|
||||
this.onClose();
|
||||
} catch (error) {
|
||||
@@ -218,6 +266,9 @@ export default {
|
||||
this.showAlert(this.alertMessage);
|
||||
}
|
||||
},
|
||||
toggleRegexEnabled() {
|
||||
this.regexEnabled = !this.regexEnabled;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user