From 26f23a6e214c74b5b6abaa7b3d3a5282bfd03b97 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Tue, 19 Apr 2022 12:47:29 +0530 Subject: [PATCH] feat: Custom fields in pre-chat form (#4189) --- .../dashboard/components/ui/Switch.vue | 8 +- app/javascript/dashboard/helper/preChat.js | 100 ++++++ .../dashboard/helper/specs/inboxFixture.js | 47 +++ .../dashboard/helper/specs/preChat.spec.js | 76 +++++ .../dashboard/i18n/locale/en/inboxMgmt.json | 16 +- .../inbox/PreChatForm/PreChatFields.vue | 91 ++++++ .../settings/inbox/PreChatForm/Settings.vue | 130 +++++--- .../dashboard/store/modules/attributes.js | 3 + .../modules/specs/attributes/getters.spec.js | 20 ++ app/javascript/packs/widget.js | 13 +- .../FluentIcon/dashboard-icons.json | 3 +- app/javascript/widget/App.vue | 5 +- .../widget/components/PreChat/Form.vue | 308 +++++++++++++----- app/javascript/widget/i18n/locale/en.json | 14 +- app/javascript/widget/mixins/configMixin.js | 12 +- .../widget/mixins/specs/configMixin.spec.js | 30 +- app/javascript/widget/views/Home.vue | 8 +- app/javascript/widget/views/PreChatForm.vue | 20 +- app/models/channel/web_widget.rb | 25 +- app/models/custom_attribute_definition.rb | 2 +- .../api/v1/widget/contacts/show.json.jbuilder | 1 + .../v1/widget/contacts/update.json.jbuilder | 1 + ...4933_add_custom_fields_to_pre_chat_form.rb | 29 ++ spec/models/channel/web_widget_spec.rb | 15 + spec/models/channel/widget_test.rb | 7 - 25 files changed, 824 insertions(+), 160 deletions(-) create mode 100644 app/javascript/dashboard/helper/preChat.js create mode 100644 app/javascript/dashboard/helper/specs/inboxFixture.js create mode 100644 app/javascript/dashboard/helper/specs/preChat.spec.js create mode 100644 app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/PreChatFields.vue create mode 100644 db/migrate/20220316054933_add_custom_fields_to_pre_chat_form.rb create mode 100644 spec/models/channel/web_widget_spec.rb delete mode 100644 spec/models/channel/widget_test.rb diff --git a/app/javascript/dashboard/components/ui/Switch.vue b/app/javascript/dashboard/components/ui/Switch.vue index b0bc32881..7dc4bcbfb 100644 --- a/app/javascript/dashboard/components/ui/Switch.vue +++ b/app/javascript/dashboard/components/ui/Switch.vue @@ -17,8 +17,12 @@ export default { value: { type: Boolean, default: false }, }, methods: { - onClick() { - this.$emit('input', !this.value); + onClick(event) { + if (event.pointerId === -1) { + event.preventDefault(); + } else { + this.$emit('input', !this.value); + } }, }, }; diff --git a/app/javascript/dashboard/helper/preChat.js b/app/javascript/dashboard/helper/preChat.js new file mode 100644 index 000000000..bc5502e5b --- /dev/null +++ b/app/javascript/dashboard/helper/preChat.js @@ -0,0 +1,100 @@ +import i18n from 'widget/i18n/index'; +const defaultTranslations = Object.fromEntries( + Object.entries(i18n).filter(([key]) => key.includes('en')) +).en; + +export const standardFieldKeys = { + emailAddress: { + key: 'EMAIL_ADDRESS', + label: 'Email Id', + placeholder: 'Please enter your email address', + }, + fullName: { + key: 'FULL_NAME', + label: 'Full Name', + placeholder: 'Please enter your full name', + }, + phoneNumber: { + key: 'PHONE_NUMBER', + label: 'Phone Number', + placeholder: 'Please enter your phone number', + }, +}; + +export const getLabel = ({ key, label }) => { + return defaultTranslations.PRE_CHAT_FORM.FIELDS[key] + ? defaultTranslations.PRE_CHAT_FORM.FIELDS[key].LABEL + : label; +}; +export const getPlaceHolder = ({ key, placeholder }) => { + return defaultTranslations.PRE_CHAT_FORM.FIELDS[key] + ? defaultTranslations.PRE_CHAT_FORM.FIELDS[key].PLACEHOLDER + : placeholder; +}; + +export const getCustomFields = ({ standardFields, customAttributes }) => { + let customFields = []; + const { pre_chat_fields: preChatFields } = standardFields; + customAttributes.forEach(attribute => { + const itemExist = preChatFields.find( + item => item.name === attribute.attribute_key + ); + if (!itemExist) { + customFields.push({ + label: attribute.attribute_display_name, + placeholder: attribute.attribute_display_name, + name: attribute.attribute_key, + type: attribute.attribute_display_type, + values: attribute.attribute_values, + field_type: attribute.attribute_model, + required: false, + enabled: false, + }); + } + }); + return customFields; +}; + +export const getFormattedPreChatFields = ({ preChatFields }) => { + return preChatFields.map(item => { + return { + ...item, + label: getLabel({ + key: standardFieldKeys[item.name] + ? standardFieldKeys[item.name].key + : item.name, + label: item.label ? item.label : item.name, + }), + placeholder: getPlaceHolder({ + key: standardFieldKeys[item.name] + ? standardFieldKeys[item.name].key + : item.name, + placeholder: item.placeholder ? item.placeholder : item.name, + }), + }; + }); +}; + +export const getPreChatFields = ({ + preChatFormOptions = {}, + customAttributes = [], +}) => { + const { pre_chat_message, pre_chat_fields } = preChatFormOptions; + let customFields = {}; + let preChatFields = {}; + + const formattedPreChatFields = getFormattedPreChatFields({ + preChatFields: pre_chat_fields, + }); + + customFields = getCustomFields({ + standardFields: { pre_chat_fields: formattedPreChatFields }, + customAttributes, + }); + preChatFields = [...formattedPreChatFields, ...customFields]; + + return { + pre_chat_message, + pre_chat_fields: preChatFields, + }; +}; diff --git a/app/javascript/dashboard/helper/specs/inboxFixture.js b/app/javascript/dashboard/helper/specs/inboxFixture.js new file mode 100644 index 000000000..6622a6de2 --- /dev/null +++ b/app/javascript/dashboard/helper/specs/inboxFixture.js @@ -0,0 +1,47 @@ +export default { + customFields: { + pre_chat_message: 'Share your queries or comments here.', + pre_chat_fields: [ + { + label: 'Email Address', + name: 'emailAddress', + type: 'email', + field_type: 'standard', + required: false, + enabled: false, + + placeholder: 'Please enter your email address', + }, + { + label: 'Full Name', + name: 'fullName', + type: 'text', + field_type: 'standard', + required: false, + enabled: false, + placeholder: 'Please enter your full name', + }, + { + label: 'Phone Number', + name: 'phoneNumber', + type: 'text', + field_type: 'standard', + required: false, + enabled: false, + placeholder: 'Please enter your phone number', + }, + ], + }, + customAttributes: [ + { + id: 101, + attribute_description: 'Order Identifier', + attribute_display_name: 'Order Id', + attribute_display_type: 'number', + attribute_key: 'order_id', + attribute_model: 'conversation_attribute', + attribute_values: Array(0), + created_at: '2021-11-29T10:20:04.563Z', + }, + ], +}; diff --git a/app/javascript/dashboard/helper/specs/preChat.spec.js b/app/javascript/dashboard/helper/specs/preChat.spec.js new file mode 100644 index 000000000..74f3e72f5 --- /dev/null +++ b/app/javascript/dashboard/helper/specs/preChat.spec.js @@ -0,0 +1,76 @@ +import { + getPreChatFields, + getFormattedPreChatFields, + getCustomFields, +} from '../preChat'; +import inboxFixture from './inboxFixture'; + +const { customFields, customAttributes } = inboxFixture; +describe('#Pre chat Helpers', () => { + describe('getPreChatFields', () => { + it('should return correct pre-chat fields form options passed', () => { + expect(getPreChatFields({ preChatFormOptions: customFields })).toEqual( + customFields + ); + }); + }); + describe('getFormattedPreChatFields', () => { + it('should return correct custom fields', () => { + expect( + getFormattedPreChatFields({ + preChatFields: customFields.pre_chat_fields, + }) + ).toEqual([ + { + label: 'Email Address', + name: 'emailAddress', + placeholder: 'Please enter your email address', + type: 'email', + field_type: 'standard', + + required: false, + enabled: false, + }, + { + label: 'Full Name', + name: 'fullName', + placeholder: 'Please enter your full name', + type: 'text', + field_type: 'standard', + required: false, + enabled: false, + }, + { + label: 'Phone Number', + name: 'phoneNumber', + placeholder: 'Please enter your phone number', + type: 'text', + field_type: 'standard', + required: false, + enabled: false, + }, + ]); + }); + }); + describe('getCustomFields', () => { + it('should return correct custom fields', () => { + expect( + getCustomFields({ + standardFields: { pre_chat_fields: customFields.pre_chat_fields }, + customAttributes, + }) + ).toEqual([ + { + enabled: false, + label: 'Order Id', + placeholder: 'Order Id', + name: 'order_id', + required: false, + field_type: 'conversation_attribute', + type: 'number', + values: [], + }, + ]); + }); + }); +}); diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index 365fd92f9..218d1cf95 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": { @@ -433,6 +432,15 @@ }, "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", + "LABEL": "Label", + "PLACE_HOLDER":"Placeholder", + "KEY": "Key", + "TYPE": "Type", + "REQUIRED": "Required" + }, "ENABLE": { "LABEL": "Enable pre chat form", "OPTIONS": { @@ -441,7 +449,7 @@ } }, "PRE_CHAT_MESSAGE": { - "LABEL": "Pre Chat Message", + "LABEL": "Pre chat message", "PLACEHOLDER": "This message would be visible to the users along with the form" }, "REQUIRE_EMAIL": { @@ -465,7 +473,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/inbox/PreChatForm/PreChatFields.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/PreChatFields.vue new file mode 100644 index 000000000..9d2691036 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/PreChatFields.vue @@ -0,0 +1,91 @@ + + + + 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..184e16e0f 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/Settings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/PreChatForm/Settings.vue @@ -1,10 +1,10 @@