Merge pull request #8331 from andrej-scinote/aj_SCI_11470

Improve validation at publishing forms [SCI-11470]
This commit is contained in:
andrej-scinote 2025-03-25 12:26:16 +01:00 committed by GitHub
commit c25ae031ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 58 additions and 21 deletions

View file

@ -56,7 +56,7 @@
:placeholder="i18n.t('forms.show.description_placeholder')" />
</div>
</div>
<component :is="this.editField.attributes.type" :field="editField" @updateField="updateField()" @syncField="syncField" />
<component :is="this.editField.attributes.type" ref="editField" :field="editField" @updateField="updateField()" @syncField="syncField" @validChanged="checkValidField" />
<div class="bg-sn-super-light-grey rounded p-4">
<div class="flex items-center gap-4">
<h5>{{ i18n.t('forms.show.mark_as_na') }}</h5>
@ -104,7 +104,8 @@ export default {
},
data() {
return {
editField: { ...this.field }
editField: { ...this.field },
isValid: false
};
},
created() {
@ -115,6 +116,19 @@ export default {
if (!this.editField.attributes.description) {
this.editField.attributes.description = '';
}
this.isValid = this.editField.isValid;
},
mounted() {
this.checkValidField();
},
watch: {
isValid() {
this.$emit('validChanged');
},
validField() {
this.checkValidField();
}
},
mounted() {
SmartAnnotation.init($(this.$refs.description), false);
@ -124,10 +138,10 @@ export default {
return this.nameValid && this.descriptionValid;
},
nameValid() {
return this.editField.attributes.name.length > 0 && this.editField.attributes.name.length <= GLOBAL_CONSTANTS.NAME_MAX_LENGTH;
return this.editField.attributes.name?.length > 0 && this.editField.attributes.name.length <= GLOBAL_CONSTANTS.NAME_MAX_LENGTH;
},
descriptionValid() {
return this.editField.attributes.description.length <= GLOBAL_CONSTANTS.TEXT_MAX_LENGTH;
return this.editField.attributes.description?.length <= GLOBAL_CONSTANTS.TEXT_MAX_LENGTH;
},
nameFieldError() {
if (this.editField.attributes.name.length === 0) {
@ -150,7 +164,7 @@ export default {
},
methods: {
updateField() {
if (!this.validField) {
if (!this.isValid) {
return;
}
this.editField.attributes.description = this.$refs.description.value; // SmartAnnotation does not update the model
@ -165,6 +179,9 @@ export default {
},
syncField(field) {
this.editField = field;
},
checkValidField() {
this.isValid = this.$refs.editField?.validField !== false && this.validField;
}
}
};

View file

@ -10,6 +10,9 @@ export default {
}
},
deep: true
},
validField() {
this.$emit('validChanged');
}
},
computed: {

View file

@ -31,19 +31,25 @@
:options="responseValidationTypes"
:value="responseValidation.type" />
</div>
<div class="sci-input-container-v2" :class="{ 'error': !responseValidationIsValid && responseValidation.max }" >
<input type="number" class="sci-input !bg-white"
:disabled="!responseValidationEnabled"
@change="updateField"
:placeholder="i18n.t('forms.show.validations.response_validation.min_placeholder')"
v-model="responseValidation.min" />
<div>
<div class="sci-input-container-v2" :class="{ 'error': !responseValidationIsValid && responseValidation.max }">
<input type="number" class="sci-input !bg-white"
:disabled="!responseValidationEnabled"
@change="updateField"
:placeholder="i18n.t('forms.show.validations.response_validation.min_placeholder')"
v-model="responseValidation.min" />
</div>
<p v-if="!responseValidationIsValid && responseValidation.max" class="sci-error-text" > {{ i18n.t('forms.fields.not_valid_range') }} </p>
</div>
<div class="sci-input-container-v2" :class="{ 'error': !responseValidationIsValid && responseValidation.min }">
<input type="number" class="sci-input !bg-white"
:disabled="!responseValidationEnabled"
@change="updateField"
:placeholder="i18n.t('forms.show.validations.response_validation.max_placeholder')"
v-model="responseValidation.max" />
<div>
<div class="sci-input-container-v2" :class="{ 'error': !responseValidationIsValid && responseValidation.min }">
<input type="number" class="sci-input !bg-white"
:disabled="!responseValidationEnabled"
@change="updateField"
:placeholder="i18n.t('forms.show.validations.response_validation.max_placeholder')"
v-model="responseValidation.max" />
</div>
<p v-if="!responseValidationIsValid && responseValidation.min" class="sci-error-text" > {{ i18n.t('forms.fields.not_valid_range') }} </p>
</div>
<div class="col-span-3 sci-input-container-v2" :class="{'error': !validationMessageValid}" :data-error="validationMessageError">
<input type="text" class="sci-input !bg-white"
@ -82,13 +88,13 @@ export default {
return this.editField.attributes.data.validations.response_validation;
},
responseValidationEnabled() {
return this.responseValidation.enabled;
return this.responseValidation?.enabled;
},
responseValidationTypes() {
return [['between', 'Between']];
},
responseValidationIsValid() {
return (this.responseValidation.min && this.responseValidation.max && this.responseValidation.min < this.responseValidation.max)
return (this.responseValidation?.min && this.responseValidation?.max && this.responseValidation?.min < this.responseValidation?.max)
|| !this.responseValidationEnabled;
},
validField() {

View file

@ -38,7 +38,7 @@
<button v-if="form.attributes.urls.publish"
class="btn btn-primary"
@click="publishForm"
:disabled="submitting"
:disabled="submitting || !isValid"
data-e2e="e2e-BT-forms-builder-publish">
{{ i18n.t('forms.show.publish') }}
</button>
@ -74,6 +74,7 @@
>
<i class="sn-icon rounded text-sn-blue bg-sn-super-light-blue p-1" :class="fieldIcon[element.attributes.data.type]"></i>
<span :title="element.attributes.name" class="truncate">{{ element.attributes.name }}</span>
<i v-if="element.isValid == false" class="ml-auto text-sn-delete-red sn-icon sn-icon-alert-warning"></i>
</div>
</div>
</template>
@ -98,11 +99,13 @@
<EditField
:key="activeField.id"
v-if="activeField.id"
ref="editField"
:field="activeField"
:icon="fieldIcon[activeField.attributes.data.type]"
@update="updateField"
@delete="deleteField"
@duplicate="duplicateField"
@validChanged="isValidChanged"
/>
<div v-if="!activeField.id"
class="text-xl font-semibold text-sn-grey font-inter flex items-center justify-center w-full h-full">
@ -179,10 +182,18 @@ export default {
savedFields: [],
activeField: {},
preview: false,
submitting: false
submitting: false,
isValid: false
};
},
methods: {
isValidChanged() {
if (this.$refs.editField?.field) {
const index = this.fields.findIndex((f) => f.id === this.$refs.editField.field.id);
this.fields[index].isValid = this.$refs.editField.isValid;
this.isValid = !this.fields.some((field) => field.isValid === false);
}
},
syncSavedFields() {
this.savedFields = this.fields.map((f) => ({ ...f }));
},