feat: Add regex validation on form message inputs (#2317)

Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
Sivin Varghese
2021-06-08 16:32:01 +05:30
committed by GitHub
parent 0a087c95fd
commit 67ce6f5704
5 changed files with 84 additions and 14 deletions

View File

@@ -44,6 +44,9 @@ Metrics/BlockLength:
- '**/routes.rb' - '**/routes.rb'
- 'config/environments/*' - 'config/environments/*'
- db/schema.rb - db/schema.rb
Metrics/ModuleLength:
Exclude:
- lib/woot_message_seeder.rb
Rails/ApplicationController: Rails/ApplicationController:
Exclude: Exclude:
- 'app/controllers/api/v1/widget/messages_controller.rb' - 'app/controllers/api/v1/widget/messages_controller.rb'

View File

@@ -1,12 +1,33 @@
<template> <template>
<div class="form chat-bubble agent"> <div class="form chat-bubble agent">
<form @submit.prevent="onSubmit"> <form @submit.prevent="onSubmit">
<div v-for="item in items" :key="item.key" class="form-block"> <div
v-for="item in items"
:key="item.key"
class="form-block"
:class="{
'has-submitted': hasSubmitted,
}"
>
<label>{{ item.label }}</label> <label>{{ item.label }}</label>
<input <input
v-if="item.type === 'email' || item.type === 'text'" v-if="item.type === 'email'"
v-model="formValues[item.name]" v-model="formValues[item.name]"
:type="item.type" :type="item.type"
:pattern="item.regex"
:title="item.title"
:required="item.required && 'required'"
:name="item.name"
:placeholder="item.placeholder"
:disabled="!!submittedValues.length"
/>
<input
v-else-if="item.type === 'text'"
v-model="formValues[item.name]"
:required="item.required && 'required'"
:pattern="item.pattern"
:title="item.title"
:type="item.type"
:name="item.name" :name="item.name"
:placeholder="item.placeholder" :placeholder="item.placeholder"
:disabled="!!submittedValues.length" :disabled="!!submittedValues.length"
@@ -14,6 +35,8 @@
<textarea <textarea
v-else-if="item.type === 'text_area'" v-else-if="item.type === 'text_area'"
v-model="formValues[item.name]" v-model="formValues[item.name]"
:required="item.required && 'required'"
:title="item.title"
:name="item.name" :name="item.name"
:placeholder="item.placeholder" :placeholder="item.placeholder"
:disabled="!!submittedValues.length" :disabled="!!submittedValues.length"
@@ -21,6 +44,7 @@
<select <select
v-else-if="item.type === 'select'" v-else-if="item.type === 'select'"
v-model="formValues[item.name]" v-model="formValues[item.name]"
:required="item.required && 'required'"
> >
<option <option
v-for="option in item.options" v-for="option in item.options"
@@ -30,13 +54,16 @@
{{ option.label }} {{ option.label }}
</option> </option>
</select> </select>
<span class="error-message">
{{ item.pattern_error || $t('CHAT_FORM.INVALID.FIELD') }}
</span>
</div> </div>
<button <button
v-if="!submittedValues.length" v-if="!submittedValues.length"
class="button block" class="button block"
type="submit" type="submit"
:disabled="!isFormValid"
:style="{ background: widgetColor, borderColor: widgetColor }" :style="{ background: widgetColor, borderColor: widgetColor }"
@click="onSubmitClick"
> >
{{ buttonLabel || $t('COMPONENTS.FORM_BUBBLE.SUBMIT') }} {{ buttonLabel || $t('COMPONENTS.FORM_BUBBLE.SUBMIT') }}
</button> </button>
@@ -64,6 +91,7 @@ export default {
data() { data() {
return { return {
formValues: {}, formValues: {},
hasSubmitted: false,
}; };
}, },
computed: { computed: {
@@ -84,6 +112,9 @@ export default {
} }
}, },
methods: { methods: {
onSubmitClick() {
this.hasSubmitted = true;
},
onSubmit() { onSubmit() {
if (!this.isFormValid) { if (!this.isFormValid) {
return; return;
@@ -171,5 +202,29 @@ export default {
.button { .button {
font-size: $font-size-default; font-size: $font-size-default;
} }
.error-message {
display: none;
margin-top: $space-smaller;
color: $color-error;
}
.has-submitted {
input:invalid {
border: 1px solid $color-error;
}
input:invalid + .error-message {
display: block;
}
textarea:invalid {
border: 1px solid $color-error;
}
textarea:invalid + .error-message {
display: block;
}
}
} }
</style> </style>

View File

@@ -51,5 +51,10 @@
} }
} }
}, },
"FILE_SIZE_LIMIT": "File exceeds the {MAXIMUM_FILE_UPLOAD_SIZE} attachment limit" "FILE_SIZE_LIMIT": "File exceeds the {MAXIMUM_FILE_UPLOAD_SIZE} attachment limit",
"CHAT_FORM": {
"INVALID": {
"FIELD": "Invalid field"
}
}
} }

View File

@@ -2,7 +2,7 @@ class ContentAttributeValidator < ActiveModel::Validator
ALLOWED_SELECT_ITEM_KEYS = [:title, :value].freeze ALLOWED_SELECT_ITEM_KEYS = [:title, :value].freeze
ALLOWED_CARD_ITEM_KEYS = [:title, :description, :media_url, :actions].freeze ALLOWED_CARD_ITEM_KEYS = [:title, :description, :media_url, :actions].freeze
ALLOWED_CARD_ITEM_ACTION_KEYS = [:text, :type, :payload, :uri].freeze ALLOWED_CARD_ITEM_ACTION_KEYS = [:text, :type, :payload, :uri].freeze
ALLOWED_FORM_ITEM_KEYS = [:type, :placeholder, :label, :name, :options, :default].freeze ALLOWED_FORM_ITEM_KEYS = [:type, :placeholder, :label, :name, :options, :default, :required, :pattern, :title, :pattern_error].freeze
ALLOWED_ARTICLE_KEYS = [:title, :description, :link].freeze ALLOWED_ARTICLE_KEYS = [:title, :description, :link].freeze
def validate(record) def validate(record)

View File

@@ -74,16 +74,23 @@ module WootMessageSeeder
message_type: :template, message_type: :template,
content_type: 'form', content_type: 'form',
content: 'form', content: 'form',
content_attributes: { content_attributes: sample_form
items: [ )
{ name: 'email', placeholder: 'Please enter your email', type: 'email', label: 'Email' }, end
{ name: 'text_area', placeholder: 'Please enter text', type: 'text_area', label: 'Large Text' },
{ name: 'text', placeholder: 'Please enter text', type: 'text', label: 'text', default: 'defaut value' }, def self.sample_form
{ name: 'select', label: 'Select Option', type: 'select', options: [{ label: '🌯 Burito', value: 'Burito' }, {
{ label: '🍝 Pasta', value: 'Pasta' }] } "items": [
{ "name": 'email', "placeholder": 'Please enter your email', "type": 'email', "label": 'Email', "required": 'required',
"pattern_error": 'Please fill this field', "pattern": '^[^\s@]+@[^\s@]+\.[^\s@]+$' },
{ "name": 'text_area', "placeholder": 'Please enter text', "type": 'text_area', "label": 'Large Text', "required": 'required',
"pattern_error": 'Please fill this field' },
{ "name": 'text', "placeholder": 'Please enter text', "type": 'text', "label": 'text', "default": 'defaut value', "required": 'required',
"pattern": '^[a-zA-Z ]*$', "pattern_error": 'Only alphabets are allowed' },
{ "name": 'select', "label": 'Select Option', "type": 'select', "options": [{ "label": '🌯 Burito', "value": 'Burito' },
{ "label": '🍝 Pasta', "value": 'Pasta' }] }
] ]
} }
)
end end
def self.create_sample_articles_message(conversation) def self.create_sample_articles_message(conversation)