diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb
index 2bda5c07a..d60e4c3e8 100644
--- a/app/controllers/api/v1/accounts/inboxes_controller.rb
+++ b/app/controllers/api/v1/accounts/inboxes_controller.rb
@@ -49,7 +49,6 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
return if permitted_params(channel_attributes)[:channel].blank?
validate_email_channel(channel_attributes) if @inbox.inbox_type == 'Email'
-
@inbox.channel.update!(permitted_params(channel_attributes)[:channel])
update_channel_feature_flags
end
diff --git a/app/controllers/api/v1/widget/base_controller.rb b/app/controllers/api/v1/widget/base_controller.rb
index 38c880526..ad555fc22 100644
--- a/app/controllers/api/v1/widget/base_controller.rb
+++ b/app/controllers/api/v1/widget/base_controller.rb
@@ -68,7 +68,7 @@ class Api::V1::Widget::BaseController < ApplicationController
mergee_contact: @contact
).perform
else
- @contact.update!(email: email, name: contact_name)
+ @contact.update!(email: email, name: contact_name, phone_number: contact_phone_number)
end
end
@@ -80,6 +80,10 @@ class Api::V1::Widget::BaseController < ApplicationController
params[:contact][:name] || contact_email.split('@')[0]
end
+ def contact_phone_number
+ params[:contact][:phone_number]
+ end
+
def browser_params
{
browser_name: browser.name,
diff --git a/app/controllers/api/v1/widget/conversations_controller.rb b/app/controllers/api/v1/widget/conversations_controller.rb
index 8d28345d4..8cfb65be6 100644
--- a/app/controllers/api/v1/widget/conversations_controller.rb
+++ b/app/controllers/api/v1/widget/conversations_controller.rb
@@ -51,6 +51,7 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController
end
def permitted_params
- params.permit(:id, :typing_status, :website_token, :email, contact: [:name, :email], message: [:content, :referer_url, :timestamp, :echo_id])
+ params.permit(:id, :typing_status, :website_token, :email, contact: [:name, :email, :phone_number],
+ message: [:content, :referer_url, :timestamp, :echo_id])
end
end
diff --git a/app/javascript/dashboard/components/buttons/ToggleButton.vue b/app/javascript/dashboard/components/buttons/ToggleButton.vue
new file mode 100644
index 000000000..37328aba5
--- /dev/null
+++ b/app/javascript/dashboard/components/buttons/ToggleButton.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
index 538d6d5f0..6111b90fd 100644
--- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
@@ -187,7 +187,7 @@
}
}
},
- "WHATSAPP": {
+ "WHATSAPP": {
"TITLE": "WhatsApp Channel",
"DESC": "Start supporting your customers via WhatsApp.",
"PROVIDERS": {
@@ -211,7 +211,6 @@
"PLACEHOLDER": "API key",
"APPLY_FOR_ACCESS": "Don't have any API key? Apply for access here",
"ERROR": "Please enter a valid value."
-
},
"SUBMIT_BUTTON": "Create WhatsApp Channel",
"API": {
@@ -432,6 +431,11 @@
},
"PRE_CHAT_FORM": {
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
+ "SET_FIELDS": "Pre chat form fields",
+ "SET_FIELDS_HEADER": {
+ "FIELDS": "Fields",
+ "REQUIRED": "Required"
+ },
"ENABLE": {
"LABEL": "Enable pre chat form",
"OPTIONS": {
@@ -464,7 +468,7 @@
"VALIDATION_ERROR": "Starting time should be before closing time.",
"CHOOSE": "Choose"
},
- "ALL_DAY":"All-Day"
+ "ALL_DAY": "All-Day"
},
"IMAP": {
"TITLE": "IMAP",
diff --git a/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue
index 811fc95c6..b3a4ce9d7 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue
@@ -34,19 +34,10 @@
{{ automation.name }} |
{{ automation.description }} |
-
+ />
|
{{ readableTime(automation.created_on) }} |
@@ -140,11 +131,13 @@ import AddAutomationRule from './AddAutomationRule.vue';
import EditAutomationRule from './EditAutomationRule.vue';
import alertMixin from 'shared/mixins/alertMixin';
import timeMixin from 'dashboard/mixins/time';
+import ToggleButton from 'dashboard/components/buttons/ToggleButton';
export default {
components: {
AddAutomationRule,
EditAutomationRule,
+ ToggleButton,
},
mixins: [alertMixin, timeMixin],
data() {
@@ -290,41 +283,4 @@ export default {
.automation__status-checkbox {
margin: 0;
}
-.toggle-button {
- background-color: var(--s-200);
- position: relative;
- display: inline-flex;
- height: 19px;
- width: 34px;
- border: 2px solid transparent;
- border-radius: var(--border-radius-large);
- cursor: pointer;
- transition-property: background-color;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 200ms;
- flex-shrink: 0;
-}
-
-.toggle-button.active {
- background-color: var(--w-500);
-}
-
-.toggle-button span {
- --space-one-point-five: 1.5rem;
- height: var(--space-one-point-five);
- width: var(--space-one-point-five);
- display: inline-block;
- background-color: var(--white);
- box-shadow: rgb(255, 255, 255) 0px 0px 0px 0px,
- rgba(59, 130, 246, 0.5) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 1px 3px 0px,
- rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;
- transform: translate(0, 0);
- border-radius: 100%;
- transition-property: transform;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 200ms;
-}
-.toggle-button span.active {
- transform: translate(var(--space-one-point-five), var(--space-zero));
-}
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/Settings.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/Settings.vue
index 6c01bc3dd..bf0c22515 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/Settings.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/Settings.vue
@@ -15,28 +15,57 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
({}),
+ default: () => {},
},
disableContactFields: {
type: Boolean,
@@ -83,15 +95,33 @@ export default {
},
},
validations() {
- const identityValidations = {
- fullName: {
- required,
- },
- emailAddress: {
- required,
- email,
- },
- };
+ let identityValidations = {};
+ if (this.isContactFieldRequired('emailAddress')) {
+ identityValidations = {
+ ...identityValidations,
+ emailAddress: {
+ required,
+ email,
+ },
+ };
+ }
+ if (this.isContactFieldRequired('phoneNumber')) {
+ identityValidations = {
+ ...identityValidations,
+ phoneNumber: {
+ required,
+ isPhoneE164OrEmpty,
+ },
+ };
+ }
+ if (this.isContactFieldRequired('fullName')) {
+ identityValidations = {
+ ...identityValidations,
+ fullName: {
+ required,
+ },
+ };
+ }
const messageValidation = {
message: {
@@ -103,18 +133,16 @@ export default {
if (this.hasActiveCampaign) {
return identityValidations;
}
- if (this.areContactFieldsVisible) {
- return {
- ...identityValidations,
- ...messageValidation,
- };
- }
- return messageValidation;
+ return {
+ ...identityValidations,
+ ...messageValidation,
+ };
},
data() {
return {
fullName: '',
emailAddress: '',
+ phoneNumber: '',
message: '',
};
},
@@ -139,11 +167,48 @@ export default {
}
return this.options.preChatMessage;
},
- areContactFieldsVisible() {
- return this.options.requireEmail && !this.disableContactFields;
+ preChatFields() {
+ return this.options.preChatFields || [];
+ },
+ emailErrorMessage() {
+ let errorMessage = '';
+ if (!this.$v.emailAddress.$error) {
+ errorMessage = '';
+ } else if (!this.$v.emailAddress.required) {
+ errorMessage = this.$t(
+ 'PRE_CHAT_FORM.FIELDS.EMAIL_ADDRESS.REQUIRED_ERROR'
+ );
+ } else if (!this.$v.emailAddress.email) {
+ errorMessage = this.$t(
+ 'PRE_CHAT_FORM.FIELDS.EMAIL_ADDRESS.VALID_ERROR'
+ );
+ }
+ return errorMessage;
+ },
+ phoneNumberErrorMessage() {
+ let errorMessage = '';
+ if (!this.$v.phoneNumber.$error) {
+ errorMessage = '';
+ } else if (!this.$v.phoneNumber.required) {
+ errorMessage = this.$t(
+ 'PRE_CHAT_FORM.FIELDS.PHONE_NUMBER.REQUIRED_ERROR'
+ );
+ } else if (!this.$v.phoneNumber.email) {
+ errorMessage = this.$t('PRE_CHAT_FORM.FIELDS.PHONE_NUMBER.VALID_ERROR');
+ }
+ return errorMessage;
},
},
methods: {
+ isContactFieldVisible(field, item) {
+ return (
+ item.name === field &&
+ this.preChatFields.find(option => option.name === field).enabled
+ );
+ },
+ isContactFieldRequired(field) {
+ return this.preChatFields.find(option => option.name === field).required;
+ },
onSubmit() {
this.$v.$touch();
if (this.$v.$invalid) {
@@ -151,6 +216,7 @@ export default {
}
this.$emit('submit', {
fullName: this.fullName,
+ phoneNumber: this.phoneNumber,
emailAddress: this.emailAddress,
message: this.message,
activeCampaignId: this.activeCampaign.id,
diff --git a/app/javascript/widget/i18n/locale/en.json b/app/javascript/widget/i18n/locale/en.json
index 7718ea4d1..94f4dd445 100644
--- a/app/javascript/widget/i18n/locale/en.json
+++ b/app/javascript/widget/i18n/locale/en.json
@@ -43,12 +43,19 @@
"FULL_NAME": {
"LABEL": "Full Name",
"PLACEHOLDER": "Please enter your full name",
- "ERROR": "Full Name is required"
+ "REQUIRED_ERROR": "Full Name is required"
},
"EMAIL_ADDRESS": {
"LABEL": "Email Address",
"PLACEHOLDER": "Please enter your email address",
- "ERROR": "Invalid email address"
+ "REQUIRED_ERROR": "Email Address is required",
+ "VALID_ERROR": "Please enter a valid email address"
+ },
+ "PHONE_NUMBER": {
+ "LABEL": "Phone Number",
+ "PLACEHOLDER": "Please enter your phone number",
+ "REQUIRED_ERROR": "Phone Number is required",
+ "VALID_ERROR": "Phone number should be of E.164 format eg: +1415555555"
},
"MESSAGE": {
"LABEL": "Message",
diff --git a/app/javascript/widget/mixins/configMixin.js b/app/javascript/widget/mixins/configMixin.js
index c91730767..1f1aec538 100644
--- a/app/javascript/widget/mixins/configMixin.js
+++ b/app/javascript/widget/mixins/configMixin.js
@@ -24,12 +24,15 @@ export default {
preChatFormOptions() {
let requireEmail = false;
let preChatMessage = '';
+ let preChatFields = null;
const options = window.chatwootWebChannel.preChatFormOptions || {};
requireEmail = options.require_email;
preChatMessage = options.pre_chat_message;
+ preChatFields = options.pre_chat_fields;
return {
requireEmail,
preChatMessage,
+ preChatFields,
};
},
},
diff --git a/app/javascript/widget/views/PreChatForm.vue b/app/javascript/widget/views/PreChatForm.vue
index cb0b4c217..24700cfcc 100644
--- a/app/javascript/widget/views/PreChatForm.vue
+++ b/app/javascript/widget/views/PreChatForm.vue
@@ -35,13 +35,20 @@ export default {
},
},
methods: {
- onSubmit({ fullName, emailAddress, message, activeCampaignId }) {
+ onSubmit({
+ fullName,
+ emailAddress,
+ message,
+ activeCampaignId,
+ phoneNumber,
+ }) {
if (activeCampaignId) {
bus.$emit('execute-campaign', activeCampaignId);
this.$store.dispatch('contacts/update', {
user: {
email: emailAddress,
name: fullName,
+ phone_number: phoneNumber,
},
});
} else {
@@ -49,6 +56,7 @@ export default {
fullName: fullName,
emailAddress: emailAddress,
message: message,
+ phoneNumber: phoneNumber,
});
}
},
diff --git a/app/models/channel/web_widget.rb b/app/models/channel/web_widget.rb
index 7c3edcc77..59a978c6e 100644
--- a/app/models/channel/web_widget.rb
+++ b/app/models/channel/web_widget.rb
@@ -32,7 +32,8 @@ class Channel::WebWidget < ApplicationRecord
self.table_name = 'channel_web_widgets'
EDITABLE_ATTRS = [:website_url, :widget_color, :welcome_title, :welcome_tagline, :reply_time, :pre_chat_form_enabled,
:continuity_via_email, :hmac_mandatory,
- { pre_chat_form_options: [:pre_chat_message, :require_email] },
+ { pre_chat_form_options: [:pre_chat_message, :require_email,
+ { pre_chat_fields: [:label, :name, :enabled, :type, :enabled, :required] }] },
{ selected_feature_flags: [] }].freeze
validates :website_url, presence: true
diff --git a/db/migrate/20220309103742_add_custom_fields_to_pre_chat_form.rb b/db/migrate/20220309103742_add_custom_fields_to_pre_chat_form.rb
new file mode 100644
index 000000000..c04e11ba7
--- /dev/null
+++ b/db/migrate/20220309103742_add_custom_fields_to_pre_chat_form.rb
@@ -0,0 +1,28 @@
+class AddCustomFieldsToPreChatForm < ActiveRecord::Migration[6.1]
+ def change
+ Channel::WebWidget.find_in_batches do |channels_batch|
+ channels_batch.each do |channel|
+ pre_chat_message = channel[:pre_chat_form_options]['pre_chat_message'] || 'Share your queries or comments here.'
+ pre_chat_fields = pre_chat_fields?(channel)
+ channel[:pre_chat_form_options] = {
+ 'pre_chat_message': pre_chat_message,
+ 'pre_chat_fields': pre_chat_fields
+ }
+ channel.save!
+ end
+ end
+ end
+
+ def pre_chat_fields?(channel)
+ email_enabled = channel[:pre_chat_form_options]['require_email'] || false
+ [
+ {
+ 'label': 'Email Id', 'name': 'emailAddress', 'type': 'email', 'required': true, 'enabled': email_enabled
+ }, {
+ 'label': 'Full name', 'name': 'fullName', 'type': 'text', 'required': true, 'enabled': email_enabled
+ }, {
+ 'label': 'Phone number', 'name': 'phoneNumber', 'type': 'number', 'required': true, 'enabled': false
+ }
+ ]
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2f3334b74..9e8856b8a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2022_02_18_120357) do
+ActiveRecord::Schema.define(version: 2022_03_09_103742) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
|