Skip to content

Commit

Permalink
feat: Custom fields in pre-chat form (#4135)
Browse files Browse the repository at this point in the history
Fixes: #2744
  • Loading branch information
muhsin-k committed Mar 14, 2022
1 parent 578414d commit e730804
Show file tree
Hide file tree
Showing 16 changed files with 328 additions and 137 deletions.
1 change: 0 additions & 1 deletion app/controllers/api/v1/accounts/inboxes_controller.rb
Expand Up @@ -49,7 +49,6 @@ def update
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
Expand Down
6 changes: 5 additions & 1 deletion app/controllers/api/v1/widget/base_controller.rb
Expand Up @@ -68,7 +68,7 @@ def update_contact(email)
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

Expand All @@ -80,6 +80,10 @@ def contact_name
params[:contact][:name] || contact_email.split('@')[0]
end

def contact_phone_number
params[:contact][:phone_number]
end

def browser_params
{
browser_name: browser.name,
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/api/v1/widget/conversations_controller.rb
Expand Up @@ -51,6 +51,7 @@ def trigger_typing_event(event)
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
65 changes: 65 additions & 0 deletions app/javascript/dashboard/components/buttons/ToggleButton.vue
@@ -0,0 +1,65 @@
<template>
<button
type="button"
class="toggle-button"
:class="{ active }"
role="switch"
:aria-checked="active.toString()"
@click="onClick"
>
<span aria-hidden="true" :class="{ active }"></span>
</button>
</template>

<script>
export default {
props: {
active: { type: Boolean, default: false },
},
methods: {
onClick(e) {
this.$emit('click', e);
},
},
};
</script>
<style lang="scss" scoped>
.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));
}
</style>
10 changes: 7 additions & 3 deletions app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
Expand Up @@ -187,7 +187,7 @@
}
}
},
"WHATSAPP": {
"WHATSAPP": {
"TITLE": "WhatsApp Channel",
"DESC": "Start supporting your customers via WhatsApp.",
"PROVIDERS": {
Expand All @@ -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": {
Expand Down Expand Up @@ -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": {
Expand Down Expand Up @@ -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",
Expand Down
Expand Up @@ -34,19 +34,10 @@
<td>{{ automation.name }}</td>
<td>{{ automation.description }}</td>
<td>
<button
type="button"
class="toggle-button"
:class="{ active: automation.active }"
role="switch"
:aria-checked="automation.active.toString()"
<toggle-button
:active="automation.active"
@click="toggleAutomation(automation, automation.active)"
>
<span
aria-hidden="true"
:class="{ active: automation.active }"
></span>
</button>
/>
</td>
<td>{{ readableTime(automation.created_on) }}</td>
<td class="button-wrapper">
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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));
}
</style>
Expand Up @@ -15,28 +15,57 @@
</option>
</select>
</label>

<label class="medium-9">
{{ $t('INBOX_MGMT.PRE_CHAT_FORM.PRE_CHAT_MESSAGE.LABEL') }}
<textarea
v-model.trim="preChatMessage"
type="text"
:placeholder="
$t('INBOX_MGMT.PRE_CHAT_FORM.PRE_CHAT_MESSAGE.PLACEHOLDER')
"
/>
</label>
<div>
<input
v-model="preChatFieldOptions"
type="checkbox"
value="requireEmail"
@input="handlePreChatFieldOptions"
/>
<label for="requireEmail">
{{ $t('INBOX_MGMT.PRE_CHAT_FORM.REQUIRE_EMAIL.LABEL') }}
<div v-if="preChatFormEnabled">
<label class="medium-9">
{{ $t('INBOX_MGMT.PRE_CHAT_FORM.PRE_CHAT_MESSAGE.LABEL') }}
<textarea
v-model.trim="preChatMessage"
type="text"
:placeholder="
$t('INBOX_MGMT.PRE_CHAT_FORM.PRE_CHAT_MESSAGE.PLACEHOLDER')
"
/>
</label>
<label> {{ $t('INBOX_MGMT.PRE_CHAT_FORM.SET_FIELDS') }} </label>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th scope="col"></th>
<th scope="col">
{{ $t('INBOX_MGMT.PRE_CHAT_FORM.SET_FIELDS_HEADER.FIELDS') }}
</th>
<th scope="col">
{{ $t('INBOX_MGMT.PRE_CHAT_FORM.SET_FIELDS_HEADER.REQUIRED') }}
</th>
</tr>
</thead>
<draggable v-model="preChatFields" tag="tbody">
<tr v-for="(item, index) in preChatFields" :key="index">
<th scope="col"><fluent-icon icon="drag" /></th>
<td scope="row">
<toggle-button
:active="item['enabled']"
@click="handlePreChatFieldOptions($event, 'enabled', item)"
/>
</td>
<td :class="{ 'disabled-text': !item['enabled'] }">
{{ item.label }}
</td>
<td>
<input
v-model="item['required']"
type="checkbox"
:value="`${item.name}-required`"
:disabled="!item['enabled']"
@click="handlePreChatFieldOptions($event, 'required', item)"
/>
</td>
</tr>
</draggable>
</table>
</div>

<woot-submit-button
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
:loading="uiFlags.isUpdatingInbox"
Expand All @@ -47,8 +76,13 @@
<script>
import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin';
import draggable from 'vuedraggable';
import ToggleButton from 'dashboard/components/buttons/ToggleButton';
export default {
components: {
draggable,
ToggleButton,
},
mixins: [alertMixin],
props: {
inbox: {
Expand All @@ -61,6 +95,7 @@ export default {
preChatFormEnabled: false,
preChatMessage: '',
preChatFieldOptions: [],
preChatFields: [],
};
},
computed: {
Expand All @@ -81,19 +116,19 @@ export default {
pre_chat_form_options: preChatFormOptions,
} = this.inbox;
this.preChatFormEnabled = preChatFormEnabled;
const { pre_chat_message: preChatMessage, require_email: requireEmail } =
preChatFormOptions || {};
const {
pre_chat_message: preChatMessage,
pre_chat_fields: preChatFields,
} = preChatFormOptions || {};
this.preChatMessage = preChatMessage;
if (requireEmail) {
this.preChatFieldOptions = ['requireEmail'];
}
this.preChatFields = preChatFields;
},
handlePreChatFieldOptions(event) {
if (this.preChatFieldOptions.includes(event.target.value)) {
this.preChatFieldOptions = [];
} else {
this.preChatFieldOptions = [event.target.value];
}
handlePreChatFieldOptions(event, type, item) {
this.preChatFields.forEach((field, index) => {
if (field.name === item.name) {
this.preChatFields[index][type] = !item[type];
}
});
},
async updateInbox() {
try {
Expand All @@ -104,7 +139,7 @@ export default {
pre_chat_form_enabled: this.preChatFormEnabled,
pre_chat_form_options: {
pre_chat_message: this.preChatMessage,
require_email: this.preChatFieldOptions.includes('requireEmail'),
pre_chat_fields: this.preChatFields,
},
},
};
Expand All @@ -125,4 +160,16 @@ export default {
.prechat--title {
margin: var(--space-medium) 0 var(--space-slab);
}
.disabled-text {
font-size: var(--font-size-small);
color: var(--s-500);
}
table thead th {
text-transform: none;
}
checkbox {
margin: 0;
}
</style>
Expand Up @@ -126,5 +126,6 @@
"brand-whatsapp-outline": "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z",
"brand-github-outline": "M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385c.6.105.825-.255.825-.57c0-.285-.015-1.23-.015-2.235c-3.015.555-3.795-.735-4.035-1.41c-.135-.345-.72-1.41-1.23-1.695c-.42-.225-1.02-.78-.015-.795c.945-.015 1.62.87 1.845 1.23c1.08 1.815 2.805 1.305 3.495.99c.105-.78.42-1.305.765-1.605c-2.67-.3-5.46-1.335-5.46-5.925c0-1.305.465-2.385 1.23-3.225c-.12-.3-.54-1.53.12-3.18c0 0 1.005-.315 3.3 1.23c.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23c.66 1.65.24 2.88.12 3.18c.765.84 1.23 1.905 1.23 3.225c0 4.605-2.805 5.625-5.475 5.925c.435.375.81 1.095.81 2.22c0 1.605-.015 2.895-.015 3.3c0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12Z",
"add-solid": "M11.883 3.007 12 3a1 1 0 0 1 .993.883L13 4v7h7a1 1 0 0 1 .993.883L21 12a1 1 0 0 1-.883.993L20 13h-7v7a1 1 0 0 1-.883.993L12 21a1 1 0 0 1-.993-.883L11 20v-7H4a1 1 0 0 1-.993-.883L3 12a1 1 0 0 1 .883-.993L4 11h7V4a1 1 0 0 1 .883-.993L12 3l-.117.007Z",
"subtract-solid": "M3.997 13H20a1 1 0 1 0 0-2H3.997a1 1 0 1 0 0 2Z"
"subtract-solid": "M3.997 13H20a1 1 0 1 0 0-2H3.997a1 1 0 1 0 0 2Z",
"drag-outline": "M15 3.707V8.5a.5.5 0 0 0 1 0V3.707l1.146 1.147a.5.5 0 0 0 .708-.708l-2-2a.499.499 0 0 0-.708 0l-2 2a.5.5 0 0 0 .708.708L15 3.707ZM2 4.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5Zm0 5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5Zm.5 4.5a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6ZM15 16.293V11.5a.5.5 0 0 1 1 0v4.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 .708-.708L15 16.293Z"
}
1 change: 1 addition & 0 deletions app/javascript/widget/api/endPoints.js
Expand Up @@ -10,6 +10,7 @@ const createConversation = params => {
contact: {
name: params.fullName,
email: params.emailAddress,
phone_number: params.phoneNumber,
},
message: {
content: params.message,
Expand Down

0 comments on commit e730804

Please sign in to comment.