chore: Split Inbox Settings Page Component (#4664)

Clean up the Inbox settings page component as the logic was growing complex.

- Moved subpages like collaborators and configuration to new components
- Moved Assignment settings to the collaborators tab
- Introduced a new inbox seeder to quickly preview setting pages of all inbox types when in development
This commit is contained in:
Sojan Jose 2022-05-11 13:33:24 +05:30 committed by GitHub
parent 9cec091716
commit 5c161e0fef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 348 additions and 183 deletions

View file

@ -341,10 +341,6 @@
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
"ERROR_MESSAGE": "Could not update widget color. Please try again later."
},
"AUTO_ASSIGNMENT": {
"ENABLED": "Enabled",
"DISABLED": "Disabled"
},
"EMAIL_COLLECT_BOX": {
"ENABLED": "Enabled",
"DISABLED": "Disabled"
@ -402,6 +398,8 @@
"MESSENGER_SUB_HEAD": "Place this button inside your body tag",
"INBOX_AGENTS": "Agents",
"INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
"AGENT_ASSIGNMENT": "Conversation Assignment",
"AGENT_ASSIGNMENT_SUB_TEXT": "Update conversation assignment settings",
"UPDATE": "Update",
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",

View file

@ -189,21 +189,6 @@
</p>
</label>
<label class="medium-9 columns settings-item">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT') }}
<select v-model="autoAssignment">
<option :value="true">
{{ $t('INBOX_MGMT.EDIT.AUTO_ASSIGNMENT.ENABLED') }}
</option>
<option :value="false">
{{ $t('INBOX_MGMT.EDIT.AUTO_ASSIGNMENT.DISABLED') }}
</option>
</select>
<p class="help-text">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT_SUB_TEXT') }}
</p>
</label>
<label class="medium-9 columns settings-item">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.ENABLE_CSAT') }}
<select v-model="csatSurveyEnabled">
@ -316,114 +301,11 @@
<facebook-reauthorize v-if="isAFacebookInbox" :inbox-id="inbox.id" />
</div>
<!-- update agents in inbox -->
<div v-if="selectedTabKey === 'collaborators'" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_AGENTS')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_AGENTS_SUB_TEXT')"
>
<multiselect
v-model="selectedAgents"
:options="agentList"
track-by="id"
label="name"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:hide-selected="true"
placeholder="Pick some"
selected-label
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
@select="$v.selectedAgents.$touch"
/>
<woot-submit-button
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
:loading="isAgentListUpdating"
@click="updateAgents"
/>
</settings-section>
<collaborators-page :inbox="inbox" />
</div>
<div v-if="selectedTabKey === 'configuration'">
<div v-if="isATwilioChannel" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.ADD.TWILIO.API_CALLBACK.TITLE')"
:sub-title="$t('INBOX_MGMT.ADD.TWILIO.API_CALLBACK.SUBTITLE')"
>
<woot-code
:script="inbox.callback_webhook_url"
lang="html"
></woot-code>
</settings-section>
</div>
<div v-else-if="isALineChannel" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.API_CALLBACK.TITLE')"
:sub-title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.API_CALLBACK.SUBTITLE')"
>
<woot-code
:script="inbox.callback_webhook_url"
lang="html"
></woot-code>
</settings-section>
</div>
<div v-else-if="isAWebWidgetInbox">
<div class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_HEADING')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD')"
>
<woot-code :script="inbox.web_widget_script"></woot-code>
</settings-section>
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_VERIFICATION')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_DESCRIPTION')"
>
<woot-code :script="inbox.hmac_token"></woot-code>
</settings-section>
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_VERIFICATION')"
:sub-title="
$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_DESCRIPTION')
"
>
<div class="enter-to-send--checkbox">
<input
id="hmacMandatory"
v-model="hmacMandatory"
type="checkbox"
@change="handleHmacFlag"
/>
<label for="hmacMandatory">
{{ $t('INBOX_MGMT.EDIT.ENABLE_HMAC.LABEL') }}
</label>
</div>
</settings-section>
</div>
</div>
<div v-else-if="isAPIInbox" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_IDENTIFIER')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_IDENTIFIER_SUB_TEXT')"
>
<woot-code :script="inbox.inbox_identifier"></woot-code>
</settings-section>
</div>
<div v-else-if="isAnEmailChannel">
<div class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.FORWARD_EMAIL_TITLE')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.FORWARD_EMAIL_SUB_TEXT')"
>
<woot-code :script="inbox.forward_to_email"></woot-code>
</settings-section>
</div>
<imap-settings :inbox="inbox" />
<smtp-settings v-if="inbox.imap_enabled" :inbox="inbox" />
</div>
<configuration-page :inbox="inbox" />
</div>
<div v-if="selectedTabKey === 'preChatForm'">
<pre-chat-form-settings :inbox="inbox" />
@ -447,8 +329,8 @@ import FacebookReauthorize from './facebook/Reauthorize';
import PreChatFormSettings from './PreChatForm/Settings';
import WeeklyAvailability from './components/WeeklyAvailability';
import GreetingsEditor from 'shared/components/GreetingsEditor';
import ImapSettings from './ImapSettings';
import SmtpSettings from './SmtpSettings';
import ConfigurationPage from './settingsPage/ConfigurationPage';
import CollaboratorsPage from './settingsPage/CollaboratorsPage';
export default {
components: {
@ -458,22 +340,18 @@ export default {
PreChatFormSettings,
WeeklyAvailability,
GreetingsEditor,
ImapSettings,
SmtpSettings,
ConfigurationPage,
CollaboratorsPage,
},
mixins: [alertMixin, configMixin, inboxMixin],
data() {
return {
avatarFile: null,
avatarUrl: '',
selectedAgents: [],
greetingEnabled: true,
tweetsEnabled: true,
hmacMandatory: null,
greetingMessage: '',
autoAssignment: false,
emailCollectEnabled: false,
isAgentListUpdating: false,
csatSurveyEnabled: false,
allowMessagesAfterResolved: true,
continuityViaEmail: true,
@ -484,22 +362,11 @@ export default {
channelWelcomeTagline: '',
selectedFeatureFlags: [],
replyTime: '',
autoAssignmentOptions: [
{
value: true,
label: this.$t('INBOX_MGMT.EDIT.AUTO_ASSIGNMENT.ENABLED'),
},
{
value: false,
label: this.$t('INBOX_MGMT.EDIT.AUTO_ASSIGNMENT.DISABLED'),
},
],
selectedTabIndex: 0,
};
},
computed: {
...mapGetters({
agentList: 'agents/getAgents',
uiFlags: 'inboxes/getUIFlags',
}),
selectedTabKey() {
@ -606,9 +473,6 @@ export default {
e.target.value
);
},
handleHmacFlag() {
this.updateInbox();
},
toggleInput(selected, current) {
if (selected.includes(current)) {
const newSelectedFlags = selected.filter(flag => flag !== current);
@ -626,15 +490,12 @@ export default {
this.$store.dispatch('teams/get');
this.$store.dispatch('labels/get');
this.$store.dispatch('inboxes/get').then(() => {
this.fetchAttachedAgents();
this.avatarUrl = this.inbox.avatar_url;
this.selectedInboxName = this.inbox.name;
this.webhookUrl = this.inbox.webhook_url;
this.greetingEnabled = this.inbox.greeting_enabled || false;
this.tweetsEnabled = this.inbox.tweets_enabled || false;
this.hmacMandatory = this.inbox.hmac_mandatory || false;
this.greetingMessage = this.inbox.greeting_message || '';
this.autoAssignment = this.inbox.enable_auto_assignment;
this.emailCollectEnabled = this.inbox.enable_email_collect;
this.csatSurveyEnabled = this.inbox.csat_survey_enabled;
this.allowMessagesAfterResolved = this.inbox.allow_messages_after_resolved;
@ -646,39 +507,11 @@ export default {
this.replyTime = this.inbox.reply_time;
});
},
async fetchAttachedAgents() {
try {
const response = await this.$store.dispatch('inboxMembers/get', {
inboxId: this.currentInboxId,
});
const {
data: { payload: inboxMembers },
} = response;
this.selectedAgents = inboxMembers;
} catch (error) {
// Handle error
}
},
async updateAgents() {
const agentList = this.selectedAgents.map(el => el.id);
this.isAgentListUpdating = true;
try {
await this.$store.dispatch('inboxMembers/create', {
inboxId: this.currentInboxId,
agentList,
});
this.showAlert(this.$t('AGENT_MGMT.EDIT.API.SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(this.$t('AGENT_MGMT.EDIT.API.ERROR_MESSAGE'));
}
this.isAgentListUpdating = false;
},
async updateInbox() {
try {
const payload = {
id: this.currentInboxId,
name: this.selectedInboxName,
enable_auto_assignment: this.autoAssignment,
enable_email_collect: this.emailCollectEnabled,
csat_survey_enabled: this.csatSurveyEnabled,
allow_messages_after_resolved: this.allowMessagesAfterResolved,
@ -692,7 +525,6 @@ export default {
welcome_tagline: this.channelWelcomeTagline || '',
selectedFeatureFlags: this.selectedFeatureFlags,
reply_time: this.replyTime || 'in_a_few_minutes',
hmac_mandatory: this.hmacMandatory,
tweets_enabled: this.tweetsEnabled,
continuity_via_email: this.continuityViaEmail,
},
@ -733,11 +565,6 @@ export default {
required,
shouldBeUrl,
},
selectedAgents: {
isEmpty() {
return !!this.selectedAgents.length;
},
},
},
};
</script>

View file

@ -0,0 +1,148 @@
<template>
<div>
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_AGENTS')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_AGENTS_SUB_TEXT')"
>
<multiselect
v-model="selectedAgents"
:options="agentList"
track-by="id"
label="name"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:hide-selected="true"
placeholder="Pick some"
selected-label
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
@select="$v.selectedAgents.$touch"
/>
<woot-submit-button
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
:loading="isAgentListUpdating"
@click="updateAgents"
/>
</settings-section>
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.AGENT_ASSIGNMENT')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.AGENT_ASSIGNMENT_SUB_TEXT')"
>
<label class="medium-9 columns settings-item">
<div class="enter-to-send--checkbox">
<input
id="enableAutoAssignment"
v-model="enableAutoAssignment"
type="checkbox"
@change="handleEnableAutoAssignment"
/>
<label for="enableAutoAssignment">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT') }}
</label>
</div>
<p class="help-text">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT_SUB_TEXT') }}
</p>
</label>
</settings-section>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin';
import SettingsSection from '../../../../../components/SettingsSection';
export default {
components: {
SettingsSection,
},
mixins: [alertMixin],
props: {
inbox: {
type: Object,
default: () => ({}),
},
},
data() {
return {
selectedAgents: [],
isAgentListUpdating: false,
enableAutoAssignment: false,
};
},
computed: {
...mapGetters({
agentList: 'agents/getAgents',
}),
},
watch: {
inbox() {
this.setDefaults();
},
},
mounted() {
this.setDefaults();
},
methods: {
setDefaults() {
this.enableAutoAssignment = this.inbox.enable_auto_assignment;
this.fetchAttachedAgents();
},
async fetchAttachedAgents() {
try {
const response = await this.$store.dispatch('inboxMembers/get', {
inboxId: this.inbox.id,
});
const {
data: { payload: inboxMembers },
} = response;
this.selectedAgents = inboxMembers;
} catch (error) {
// Handle error
}
},
handleEnableAutoAssignment() {
this.updateInbox();
},
async updateAgents() {
const agentList = this.selectedAgents.map(el => el.id);
this.isAgentListUpdating = true;
try {
await this.$store.dispatch('inboxMembers/create', {
inboxId: this.inbox.id,
agentList,
});
this.showAlert(this.$t('AGENT_MGMT.EDIT.API.SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(this.$t('AGENT_MGMT.EDIT.API.ERROR_MESSAGE'));
}
this.isAgentListUpdating = false;
},
async updateInbox() {
try {
const payload = {
id: this.inbox.id,
formData: false,
enable_auto_assignment: this.enableAutoAssignment,
};
await this.$store.dispatch('inboxes/updateInbox', payload);
this.showAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
}
},
},
validations: {
selectedAgents: {
isEmpty() {
return !!this.selectedAgents.length;
},
},
},
};
</script>

View file

@ -0,0 +1,130 @@
<template>
<div v-if="isATwilioChannel" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.ADD.TWILIO.API_CALLBACK.TITLE')"
:sub-title="$t('INBOX_MGMT.ADD.TWILIO.API_CALLBACK.SUBTITLE')"
>
<woot-code :script="inbox.callback_webhook_url" lang="html"></woot-code>
</settings-section>
</div>
<div v-else-if="isALineChannel" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.API_CALLBACK.TITLE')"
:sub-title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.API_CALLBACK.SUBTITLE')"
>
<woot-code :script="inbox.callback_webhook_url" lang="html"></woot-code>
</settings-section>
</div>
<div v-else-if="isAWebWidgetInbox">
<div class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_HEADING')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD')"
>
<woot-code :script="inbox.web_widget_script"></woot-code>
</settings-section>
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_VERIFICATION')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_DESCRIPTION')"
>
<woot-code :script="inbox.hmac_token"></woot-code>
</settings-section>
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_VERIFICATION')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_DESCRIPTION')"
>
<div class="enter-to-send--checkbox">
<input
id="hmacMandatory"
v-model="hmacMandatory"
type="checkbox"
@change="handleHmacFlag"
/>
<label for="hmacMandatory">
{{ $t('INBOX_MGMT.EDIT.ENABLE_HMAC.LABEL') }}
</label>
</div>
</settings-section>
</div>
</div>
<div v-else-if="isAPIInbox" class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_IDENTIFIER')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_IDENTIFIER_SUB_TEXT')"
>
<woot-code :script="inbox.inbox_identifier"></woot-code>
</settings-section>
</div>
<div v-else-if="isAnEmailChannel">
<div class="settings--content">
<settings-section
:title="$t('INBOX_MGMT.SETTINGS_POPUP.FORWARD_EMAIL_TITLE')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.FORWARD_EMAIL_SUB_TEXT')"
>
<woot-code :script="inbox.forward_to_email"></woot-code>
</settings-section>
</div>
<imap-settings :inbox="inbox" />
<smtp-settings v-if="inbox.imap_enabled" :inbox="inbox" />
</div>
</template>
<script>
import alertMixin from 'shared/mixins/alertMixin';
import inboxMixin from 'shared/mixins/inboxMixin';
import SettingsSection from '../../../../../components/SettingsSection';
import ImapSettings from '../ImapSettings';
import SmtpSettings from '../SmtpSettings';
export default {
components: {
SettingsSection,
ImapSettings,
SmtpSettings,
},
mixins: [inboxMixin, alertMixin],
props: {
inbox: {
type: Object,
default: () => ({}),
},
},
data() {
return {
hmacMandatory: false,
};
},
watch: {
inbox() {
this.setDefaults();
},
},
mounted() {
this.setDefaults();
},
methods: {
setDefaults() {
this.hmacMandatory = this.inbox.hmac_mandatory || false;
},
handleHmacFlag() {
this.updateInbox();
},
async updateInbox() {
try {
const payload = {
id: this.inbox.id,
formData: false,
channel: {
hmac_mandatory: this.hmacMandatory,
},
};
await this.$store.dispatch('inboxes/updateInbox', payload);
this.showAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
}
},
},
};
</script>

View file

@ -17,6 +17,7 @@ class Seeders::AccountSeeder
def seed!
seed_canned_responses
seed_inboxes
end
def seed_canned_responses(count: 50)
@ -24,4 +25,65 @@ class Seeders::AccountSeeder
account.canned_responses.create(content: Faker::Quote.fortune_cookie, short_code: Faker::Alphanumeric.alpha(number: 10))
end
end
def seed_inboxes
seed_website_inbox
seed_facebook_inbox
seed_twitter_inbox
seed_whatsapp_inbox
seed_sms_inbox
seed_email_inbox
seed_api_inbox
seed_telegram_inbox
seed_line_inbox
end
def seed_website_inbox
channel = Channel::WebWidget.create!(account: account, website_url: 'https://acme.inc')
Inbox.create!(channel: channel, account: account, name: 'Acme Website')
end
def seed_facebook_inbox
channel = Channel::FacebookPage.create!(account: account, user_access_token: 'test', page_access_token: 'test', page_id: 'test')
Inbox.create!(channel: channel, account: account, name: 'Acme Facebook')
end
def seed_twitter_inbox
channel = Channel::TwitterProfile.create!(account: account, twitter_access_token: 'test', twitter_access_token_secret: 'test', profile_id: '123')
Inbox.create!(channel: channel, account: account, name: 'Acme Twitter')
end
def seed_whatsapp_inbox
channel = Channel::Whatsapp.create!(account: account, phone_number: '+123456789')
Inbox.create!(channel: channel, account: account, name: 'Acme Whatsapp')
end
def seed_sms_inbox
channel = Channel::Sms.create!(account: account, phone_number: '+123456789')
Inbox.create!(channel: channel, account: account, name: 'Acme SMS')
end
def seed_email_inbox
channel = Channel::Email.create!(account: account, email: 'test@acme.inc', forward_to_email: 'test_fwd@acme.inc')
Inbox.create!(channel: channel, account: account, name: 'Acme Email')
end
def seed_api_inbox
channel = Channel::Api.create!(account: account)
Inbox.create!(channel: channel, account: account, name: 'Acme API')
end
def seed_telegram_inbox
# rubocop:disable Rails/SkipsModelValidations
Channel::Telegram.insert({ account_id: account.id, bot_name: 'Acme', bot_token: 'test', created_at: Time.now.utc, updated_at: Time.now.utc },
returning: %w[id])
channel = Channel::Telegram.find_by(bot_token: 'test')
Inbox.create!(channel: channel, account: account, name: 'Acme Telegram')
# rubocop:enable Rails/SkipsModelValidations
end
def seed_line_inbox
channel = Channel::Line.create!(account: account, line_channel_id: 'test', line_channel_secret: 'test', line_channel_token: 'test')
Inbox.create!(channel: channel, account: account, name: 'Acme Line')
end
end