From 037ffc7419bbc196eca17d7def51ab4255e20932 Mon Sep 17 00:00:00 2001 From: Pranav Raj S Date: Tue, 16 Feb 2021 00:14:13 +0530 Subject: [PATCH] feat: Add a pre-chat form on widget (#1769) --- .../api/v1/widget/base_controller.rb | 65 ++++++++- .../api/v1/widget/conversations_controller.rb | 10 +- .../api/v1/widget/messages_controller.rb | 65 +-------- app/javascript/widget/App.vue | 10 -- app/javascript/widget/api/conversation.js | 7 + app/javascript/widget/api/endPoints.js | 20 +++ .../widget/components/ChatHeader.vue | 2 - .../widget/components/ChatHeaderExpanded.vue | 4 +- .../widget/components/Form/Input.vue | 59 +++++++++ .../widget/components/Form/TextArea.vue | 63 +++++++++ .../widget/components/PreChat/Form.vue | 117 +++++++++++++++++ app/javascript/widget/i18n/locale/en.json | 21 ++- app/javascript/widget/mixins/configMixin.js | 10 ++ .../store/modules/conversation/actions.js | 20 +++ .../store/modules/conversation/getters.js | 1 + .../store/modules/conversation/index.js | 1 + .../store/modules/conversation/mutations.js | 7 + .../specs/conversation/actions.spec.js | 37 ++++++ .../specs/conversation/getters.spec.js | 5 + .../specs/conversation/mutations.spec.js | 11 ++ app/javascript/widget/views/Home.vue | 124 ++++++++++-------- app/javascript/widget/views/Router.vue | 28 ---- app/javascript/widget/views/Unread.vue | 20 +-- app/models/channel/web_widget.rb | 26 ++-- .../v1/models/_widget_message.json.jbuilder | 9 ++ .../widget/conversations/create.json.jbuilder | 10 ++ app/views/widgets/show.html.erb | 4 +- config/routes.rb | 2 +- ...request_for_email_on_channel_web_widget.rb | 15 +++ db/schema.rb | 6 +- .../widget/conversations_controller_spec.rb | 25 ++++ 31 files changed, 604 insertions(+), 200 deletions(-) create mode 100644 app/javascript/widget/components/Form/Input.vue create mode 100644 app/javascript/widget/components/Form/TextArea.vue create mode 100644 app/javascript/widget/components/PreChat/Form.vue create mode 100644 app/views/api/v1/models/_widget_message.json.jbuilder create mode 100644 app/views/api/v1/widget/conversations/create.json.jbuilder create mode 100644 db/migrate/20210212154240_add_request_for_email_on_channel_web_widget.rb diff --git a/app/controllers/api/v1/widget/base_controller.rb b/app/controllers/api/v1/widget/base_controller.rb index 1d377d69d..52f19595e 100644 --- a/app/controllers/api/v1/widget/base_controller.rb +++ b/app/controllers/api/v1/widget/base_controller.rb @@ -20,11 +20,7 @@ class Api::V1::Widget::BaseController < ApplicationController end def auth_token_params - @auth_token_params ||= ::Widget::TokenService.new(token: request.headers[header_name]).decode_token - end - - def header_name - 'X-Auth-Token' + @auth_token_params ||= ::Widget::TokenService.new(token: request.headers['X-Auth-Token']).decode_token end def set_web_widget @@ -39,6 +35,50 @@ class Api::V1::Widget::BaseController < ApplicationController @contact = @contact_inbox.contact end + def create_conversation + ::Conversation.create!(conversation_params) + end + + def inbox + @inbox ||= ::Inbox.find_by(id: auth_token_params[:inbox_id]) + end + + def conversation_params + # FIXME: typo referrer in additional attributes, will probably require a migration. + { + account_id: inbox.account_id, + inbox_id: inbox.id, + contact_id: @contact.id, + contact_inbox_id: @contact_inbox.id, + additional_attributes: { + browser: browser_params, + referer: permitted_params[:message][:referer_url], + initiated_at: timestamp_params + } + } + end + + def update_contact(email) + contact_with_email = @current_account.contacts.find_by(email: email) + if contact_with_email + @contact = ::ContactMergeAction.new( + account: @current_account, + base_contact: contact_with_email, + mergee_contact: @contact + ).perform + else + @contact.update!(email: email, name: contact_name) + end + end + + def contact_email + permitted_params[:contact][:email].downcase + end + + def contact_name + params[:contact][:name] || contact_email.split('@')[0] + end + def browser_params { browser_name: browser.name, @@ -48,4 +88,19 @@ class Api::V1::Widget::BaseController < ApplicationController platform_version: browser.platform.version } end + + def timestamp_params + { timestamp: permitted_params[:message][:timestamp] } + end + + def message_params + { + account_id: conversation.account_id, + sender: @contact, + content: permitted_params[:message][:content], + inbox_id: conversation.inbox_id, + echo_id: permitted_params[:message][:echo_id], + message_type: :incoming + } + end end diff --git a/app/controllers/api/v1/widget/conversations_controller.rb b/app/controllers/api/v1/widget/conversations_controller.rb index bafd008f9..2c8cede47 100644 --- a/app/controllers/api/v1/widget/conversations_controller.rb +++ b/app/controllers/api/v1/widget/conversations_controller.rb @@ -5,6 +5,14 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController @conversation = conversation end + def create + ActiveRecord::Base.transaction do + update_contact(contact_email) if @contact.email.blank? + @conversation = create_conversation + conversation.messages.create(message_params) + end + end + def update_last_seen head :ok && return if conversation.nil? @@ -43,6 +51,6 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController end def permitted_params - params.permit(:id, :typing_status, :website_token, :email) + params.permit(:id, :typing_status, :website_token, :email, contact: [:name, :email], message: [:content, :referer_url, :timestamp, :echo_id]) end end diff --git a/app/controllers/api/v1/widget/messages_controller.rb b/app/controllers/api/v1/widget/messages_controller.rb index c98138366..6def00a3a 100644 --- a/app/controllers/api/v1/widget/messages_controller.rb +++ b/app/controllers/api/v1/widget/messages_controller.rb @@ -39,44 +39,7 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController end def set_conversation - @conversation = ::Conversation.create!(conversation_params) if conversation.nil? - end - - def message_params - { - account_id: conversation.account_id, - sender: @contact, - content: permitted_params[:message][:content], - inbox_id: conversation.inbox_id, - echo_id: permitted_params[:message][:echo_id], - message_type: :incoming - } - end - - def conversation_params - # FIXME: typo referrer in additional attributes - # will probably require a migration. - { - account_id: inbox.account_id, - inbox_id: inbox.id, - contact_id: @contact.id, - contact_inbox_id: @contact_inbox.id, - additional_attributes: { - browser: browser_params, - referer: permitted_params[:message][:referer_url], - initiated_at: timestamp_params - } - } - end - - def timestamp_params - { - timestamp: permitted_params[:message][:timestamp] - } - end - - def inbox - @inbox ||= ::Inbox.find_by(id: auth_token_params[:inbox_id]) + @conversation = create_conversation if conversation.nil? end def message_finder_params @@ -90,36 +53,12 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController @message_finder ||= MessageFinder.new(conversation, message_finder_params) end - def update_contact(email) - contact_with_email = @current_account.contacts.find_by(email: email) - if contact_with_email - @contact = ::ContactMergeAction.new( - account: @current_account, - base_contact: contact_with_email, - mergee_contact: @contact - ).perform - else - @contact.update!( - email: email, - name: contact_name - ) - end - end - - def contact_email - permitted_params[:contact][:email].downcase - end - - def contact_name - contact_email.split('@')[0] - end - def message_update_params params.permit(message: [{ submitted_values: [:name, :title, :value] }]) end def permitted_params - params.permit(:id, :before, :website_token, contact: [:email], message: [:content, :referer_url, :timestamp, :echo_id]) + params.permit(:id, :before, :website_token, contact: [:name, :email], message: [:content, :referer_url, :timestamp, :echo_id]) end def set_message diff --git a/app/javascript/widget/App.vue b/app/javascript/widget/App.vue index 395f25662..1d860e76c 100755 --- a/app/javascript/widget/App.vue +++ b/app/javascript/widget/App.vue @@ -2,12 +2,7 @@ { + const urlData = endPoints.createConversation(content); + const result = await API.post(urlData.url, urlData.params); + return result; +}; + const sendMessageAPI = async content => { const urlData = endPoints.sendMessage(content); const result = await API.post(urlData.url, urlData.params); @@ -38,6 +44,7 @@ const setUserLastSeenAt = async ({ lastSeen }) => { }; export { + createConversationAPI, sendMessageAPI, getConversationAPI, getMessagesAPI, diff --git a/app/javascript/widget/api/endPoints.js b/app/javascript/widget/api/endPoints.js index 98c9206e4..6d856ee48 100755 --- a/app/javascript/widget/api/endPoints.js +++ b/app/javascript/widget/api/endPoints.js @@ -1,5 +1,24 @@ import { buildSearchParamsWithLocale } from '../helpers/urlParamsHelper'; +const createConversation = params => { + const referrerURL = window.referrerURL || ''; + const search = buildSearchParamsWithLocale(window.location.search); + return { + url: `/api/v1/widget/conversations${search}`, + params: { + contact: { + name: params.fullName, + email: params.emailAddress, + }, + message: { + content: params.message, + timestamp: new Date().toString(), + referer_url: referrerURL, + }, + }, + }; +}; + const sendMessage = content => { const referrerURL = window.referrerURL || ''; const search = buildSearchParamsWithLocale(window.location.search); @@ -47,6 +66,7 @@ const getAvailableAgents = token => ({ }); export default { + createConversation, sendMessage, sendAttachment, getConversation, diff --git a/app/javascript/widget/components/ChatHeader.vue b/app/javascript/widget/components/ChatHeader.vue index d7c4cf8d6..9bc830edc 100644 --- a/app/javascript/widget/components/ChatHeader.vue +++ b/app/javascript/widget/components/ChatHeader.vue @@ -75,8 +75,6 @@ export default { padding: $space-two $space-medium; width: 100%; box-sizing: border-box; - background: white; - @include shadow-large; .header-branding { display: flex; diff --git a/app/javascript/widget/components/ChatHeaderExpanded.vue b/app/javascript/widget/components/ChatHeaderExpanded.vue index 509805ff9..e528d336f 100755 --- a/app/javascript/widget/components/ChatHeaderExpanded.vue +++ b/app/javascript/widget/components/ChatHeaderExpanded.vue @@ -1,5 +1,5 @@