Merge branch 'feat/custom-attrs-automations' of github.com:chatwoot/chatwoot into feat/custom-attrs-automations
This commit is contained in:
commit
123b5a7e6a
17 changed files with 423 additions and 229 deletions
|
@ -38,9 +38,12 @@ class DashboardController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def app_config
|
def app_config
|
||||||
{ APP_VERSION: Chatwoot.config[:version],
|
{
|
||||||
|
APP_VERSION: Chatwoot.config[:version],
|
||||||
VAPID_PUBLIC_KEY: VapidService.public_key,
|
VAPID_PUBLIC_KEY: VapidService.public_key,
|
||||||
ENABLE_ACCOUNT_SIGNUP: GlobalConfigService.load('ENABLE_ACCOUNT_SIGNUP', 'false'),
|
ENABLE_ACCOUNT_SIGNUP: GlobalConfigService.load('ENABLE_ACCOUNT_SIGNUP', 'false'),
|
||||||
FB_APP_ID: GlobalConfigService.load('FB_APP_ID', '') }
|
FB_APP_ID: GlobalConfigService.load('FB_APP_ID', ''),
|
||||||
|
FACEBOOK_API_VERSION: 'v13.0'
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,10 @@ class Platform::Api::V1::UsersController < PlatformController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@resource.assign_attributes(user_update_params)
|
@resource.assign_attributes(user_update_params)
|
||||||
|
|
||||||
|
# We are using devise's reconfirmable flow for changing emails
|
||||||
|
# But in case of platform APIs we don't want user to go through this extra step
|
||||||
|
@resource.skip_reconfirmation! if user_update_params[:email].present?
|
||||||
@resource.save!
|
@resource.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,30 +17,30 @@ module ReportHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def conversations_count
|
def conversations_count
|
||||||
(get_grouped_values scope.conversations).count
|
(get_grouped_values scope.conversations.where(account_id: account.id)).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def incoming_messages_count
|
def incoming_messages_count
|
||||||
(get_grouped_values scope.messages.incoming.unscope(:order)).count
|
(get_grouped_values scope.messages.where(account_id: account.id).incoming.unscope(:order)).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def outgoing_messages_count
|
def outgoing_messages_count
|
||||||
(get_grouped_values scope.messages.outgoing.unscope(:order)).count
|
(get_grouped_values scope.messages.where(account_id: account.id).outgoing.unscope(:order)).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolutions_count
|
def resolutions_count
|
||||||
(get_grouped_values scope.conversations.resolved).count
|
(get_grouped_values scope.conversations.where(account_id: account.id).resolved).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def avg_first_response_time
|
def avg_first_response_time
|
||||||
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'first_response'))
|
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'first_response', account_id: account.id))
|
||||||
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
||||||
|
|
||||||
grouped_reporting_events.average(:value)
|
grouped_reporting_events.average(:value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def avg_resolution_time
|
def avg_resolution_time
|
||||||
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'conversation_resolved'))
|
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'conversation_resolved', account_id: account.id))
|
||||||
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
||||||
|
|
||||||
grouped_reporting_events.average(:value)
|
grouped_reporting_events.average(:value)
|
||||||
|
@ -48,7 +48,7 @@ module ReportHelper
|
||||||
|
|
||||||
def avg_resolution_time_summary
|
def avg_resolution_time_summary
|
||||||
reporting_events = scope.reporting_events
|
reporting_events = scope.reporting_events
|
||||||
.where(name: 'conversation_resolved', created_at: range)
|
.where(name: 'conversation_resolved', account_id: account.id, created_at: range)
|
||||||
avg_rt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
avg_rt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
||||||
|
|
||||||
return 0 if avg_rt.blank?
|
return 0 if avg_rt.blank?
|
||||||
|
@ -58,7 +58,7 @@ module ReportHelper
|
||||||
|
|
||||||
def avg_first_response_time_summary
|
def avg_first_response_time_summary
|
||||||
reporting_events = scope.reporting_events
|
reporting_events = scope.reporting_events
|
||||||
.where(name: 'first_response', created_at: range)
|
.where(name: 'first_response', account_id: account.id, created_at: range)
|
||||||
avg_frt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
avg_frt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
||||||
|
|
||||||
return 0 if avg_frt.blank?
|
return 0 if avg_frt.blank?
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
export const createMessengerScript = pageId => `
|
|
||||||
<script>
|
|
||||||
window.fbAsyncInit = function() {
|
|
||||||
FB.init({
|
|
||||||
appId: "${window.chatwootConfig.fbAppId}",
|
|
||||||
xfbml: true,
|
|
||||||
version: "v4.0"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
(function(d, s, id){
|
|
||||||
var js, fjs = d.getElementsByTagName(s)[0];
|
|
||||||
if (d.getElementById(id)) { return; }
|
|
||||||
js = d.createElement(s); js.id = id;
|
|
||||||
js.src = "//connect.facebook.net/en_US/sdk.js";
|
|
||||||
fjs.parentNode.insertBefore(js, fjs);
|
|
||||||
}(document, 'script', 'facebook-jssdk'));
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<div class="fb-messengermessageus"
|
|
||||||
messenger_app_id="${window.chatwootConfig.fbAppId}"
|
|
||||||
page_id="${pageId}"
|
|
||||||
color="blue"
|
|
||||||
size="standard" >
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -341,10 +341,6 @@
|
||||||
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
|
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
|
||||||
"ERROR_MESSAGE": "Could not update widget color. Please try again later."
|
"ERROR_MESSAGE": "Could not update widget color. Please try again later."
|
||||||
},
|
},
|
||||||
"AUTO_ASSIGNMENT": {
|
|
||||||
"ENABLED": "Enabled",
|
|
||||||
"DISABLED": "Disabled"
|
|
||||||
},
|
|
||||||
"EMAIL_COLLECT_BOX": {
|
"EMAIL_COLLECT_BOX": {
|
||||||
"ENABLED": "Enabled",
|
"ENABLED": "Enabled",
|
||||||
"DISABLED": "Disabled"
|
"DISABLED": "Disabled"
|
||||||
|
@ -402,6 +398,8 @@
|
||||||
"MESSENGER_SUB_HEAD": "Place this button inside your body tag",
|
"MESSENGER_SUB_HEAD": "Place this button inside your body tag",
|
||||||
"INBOX_AGENTS": "Agents",
|
"INBOX_AGENTS": "Agents",
|
||||||
"INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
|
"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",
|
"UPDATE": "Update",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
||||||
|
|
|
@ -189,21 +189,6 @@
|
||||||
</p>
|
</p>
|
||||||
</label>
|
</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">
|
<label class="medium-9 columns settings-item">
|
||||||
{{ $t('INBOX_MGMT.SETTINGS_POPUP.ENABLE_CSAT') }}
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.ENABLE_CSAT') }}
|
||||||
<select v-model="csatSurveyEnabled">
|
<select v-model="csatSurveyEnabled">
|
||||||
|
@ -316,114 +301,11 @@
|
||||||
<facebook-reauthorize v-if="isAFacebookInbox" :inbox-id="inbox.id" />
|
<facebook-reauthorize v-if="isAFacebookInbox" :inbox-id="inbox.id" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- update agents in inbox -->
|
|
||||||
|
|
||||||
<div v-if="selectedTabKey === 'collaborators'" class="settings--content">
|
<div v-if="selectedTabKey === 'collaborators'" class="settings--content">
|
||||||
<settings-section
|
<collaborators-page :inbox="inbox" />
|
||||||
: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>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedTabKey === 'configuration'">
|
<div v-if="selectedTabKey === 'configuration'">
|
||||||
<div v-if="isATwilioChannel" class="settings--content">
|
<configuration-page :inbox="inbox" />
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedTabKey === 'preChatForm'">
|
<div v-if="selectedTabKey === 'preChatForm'">
|
||||||
<pre-chat-form-settings :inbox="inbox" />
|
<pre-chat-form-settings :inbox="inbox" />
|
||||||
|
@ -436,7 +318,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { createMessengerScript } from 'dashboard/helper/scriptGenerator';
|
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from 'vuelidate/lib/validators';
|
||||||
import { shouldBeUrl } from 'shared/helpers/Validators';
|
import { shouldBeUrl } from 'shared/helpers/Validators';
|
||||||
import configMixin from 'shared/mixins/configMixin';
|
import configMixin from 'shared/mixins/configMixin';
|
||||||
|
@ -448,8 +329,8 @@ import FacebookReauthorize from './facebook/Reauthorize';
|
||||||
import PreChatFormSettings from './PreChatForm/Settings';
|
import PreChatFormSettings from './PreChatForm/Settings';
|
||||||
import WeeklyAvailability from './components/WeeklyAvailability';
|
import WeeklyAvailability from './components/WeeklyAvailability';
|
||||||
import GreetingsEditor from 'shared/components/GreetingsEditor';
|
import GreetingsEditor from 'shared/components/GreetingsEditor';
|
||||||
import ImapSettings from './ImapSettings';
|
import ConfigurationPage from './settingsPage/ConfigurationPage';
|
||||||
import SmtpSettings from './SmtpSettings';
|
import CollaboratorsPage from './settingsPage/CollaboratorsPage';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
@ -459,22 +340,18 @@ export default {
|
||||||
PreChatFormSettings,
|
PreChatFormSettings,
|
||||||
WeeklyAvailability,
|
WeeklyAvailability,
|
||||||
GreetingsEditor,
|
GreetingsEditor,
|
||||||
ImapSettings,
|
ConfigurationPage,
|
||||||
SmtpSettings,
|
CollaboratorsPage,
|
||||||
},
|
},
|
||||||
mixins: [alertMixin, configMixin, inboxMixin],
|
mixins: [alertMixin, configMixin, inboxMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
avatarFile: null,
|
avatarFile: null,
|
||||||
avatarUrl: '',
|
avatarUrl: '',
|
||||||
selectedAgents: [],
|
|
||||||
greetingEnabled: true,
|
greetingEnabled: true,
|
||||||
tweetsEnabled: true,
|
tweetsEnabled: true,
|
||||||
hmacMandatory: null,
|
|
||||||
greetingMessage: '',
|
greetingMessage: '',
|
||||||
autoAssignment: false,
|
|
||||||
emailCollectEnabled: false,
|
emailCollectEnabled: false,
|
||||||
isAgentListUpdating: false,
|
|
||||||
csatSurveyEnabled: false,
|
csatSurveyEnabled: false,
|
||||||
allowMessagesAfterResolved: true,
|
allowMessagesAfterResolved: true,
|
||||||
continuityViaEmail: true,
|
continuityViaEmail: true,
|
||||||
|
@ -485,22 +362,11 @@ export default {
|
||||||
channelWelcomeTagline: '',
|
channelWelcomeTagline: '',
|
||||||
selectedFeatureFlags: [],
|
selectedFeatureFlags: [],
|
||||||
replyTime: '',
|
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,
|
selectedTabIndex: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
agentList: 'agents/getAgents',
|
|
||||||
uiFlags: 'inboxes/getUIFlags',
|
uiFlags: 'inboxes/getUIFlags',
|
||||||
}),
|
}),
|
||||||
selectedTabKey() {
|
selectedTabKey() {
|
||||||
|
@ -568,9 +434,6 @@ export default {
|
||||||
}
|
}
|
||||||
return this.inbox.name;
|
return this.inbox.name;
|
||||||
},
|
},
|
||||||
messengerScript() {
|
|
||||||
return createMessengerScript(this.inbox.page_id);
|
|
||||||
},
|
|
||||||
inboxNameLabel() {
|
inboxNameLabel() {
|
||||||
if (this.isAWebWidgetInbox) {
|
if (this.isAWebWidgetInbox) {
|
||||||
return this.$t('INBOX_MGMT.ADD.WEBSITE_NAME.LABEL');
|
return this.$t('INBOX_MGMT.ADD.WEBSITE_NAME.LABEL');
|
||||||
|
@ -610,9 +473,6 @@ export default {
|
||||||
e.target.value
|
e.target.value
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
handleHmacFlag() {
|
|
||||||
this.updateInbox();
|
|
||||||
},
|
|
||||||
toggleInput(selected, current) {
|
toggleInput(selected, current) {
|
||||||
if (selected.includes(current)) {
|
if (selected.includes(current)) {
|
||||||
const newSelectedFlags = selected.filter(flag => flag !== current);
|
const newSelectedFlags = selected.filter(flag => flag !== current);
|
||||||
|
@ -630,15 +490,12 @@ export default {
|
||||||
this.$store.dispatch('teams/get');
|
this.$store.dispatch('teams/get');
|
||||||
this.$store.dispatch('labels/get');
|
this.$store.dispatch('labels/get');
|
||||||
this.$store.dispatch('inboxes/get').then(() => {
|
this.$store.dispatch('inboxes/get').then(() => {
|
||||||
this.fetchAttachedAgents();
|
|
||||||
this.avatarUrl = this.inbox.avatar_url;
|
this.avatarUrl = this.inbox.avatar_url;
|
||||||
this.selectedInboxName = this.inbox.name;
|
this.selectedInboxName = this.inbox.name;
|
||||||
this.webhookUrl = this.inbox.webhook_url;
|
this.webhookUrl = this.inbox.webhook_url;
|
||||||
this.greetingEnabled = this.inbox.greeting_enabled || false;
|
this.greetingEnabled = this.inbox.greeting_enabled || false;
|
||||||
this.tweetsEnabled = this.inbox.tweets_enabled || false;
|
this.tweetsEnabled = this.inbox.tweets_enabled || false;
|
||||||
this.hmacMandatory = this.inbox.hmac_mandatory || false;
|
|
||||||
this.greetingMessage = this.inbox.greeting_message || '';
|
this.greetingMessage = this.inbox.greeting_message || '';
|
||||||
this.autoAssignment = this.inbox.enable_auto_assignment;
|
|
||||||
this.emailCollectEnabled = this.inbox.enable_email_collect;
|
this.emailCollectEnabled = this.inbox.enable_email_collect;
|
||||||
this.csatSurveyEnabled = this.inbox.csat_survey_enabled;
|
this.csatSurveyEnabled = this.inbox.csat_survey_enabled;
|
||||||
this.allowMessagesAfterResolved = this.inbox.allow_messages_after_resolved;
|
this.allowMessagesAfterResolved = this.inbox.allow_messages_after_resolved;
|
||||||
|
@ -650,39 +507,11 @@ export default {
|
||||||
this.replyTime = this.inbox.reply_time;
|
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() {
|
async updateInbox() {
|
||||||
try {
|
try {
|
||||||
const payload = {
|
const payload = {
|
||||||
id: this.currentInboxId,
|
id: this.currentInboxId,
|
||||||
name: this.selectedInboxName,
|
name: this.selectedInboxName,
|
||||||
enable_auto_assignment: this.autoAssignment,
|
|
||||||
enable_email_collect: this.emailCollectEnabled,
|
enable_email_collect: this.emailCollectEnabled,
|
||||||
csat_survey_enabled: this.csatSurveyEnabled,
|
csat_survey_enabled: this.csatSurveyEnabled,
|
||||||
allow_messages_after_resolved: this.allowMessagesAfterResolved,
|
allow_messages_after_resolved: this.allowMessagesAfterResolved,
|
||||||
|
@ -696,7 +525,6 @@ export default {
|
||||||
welcome_tagline: this.channelWelcomeTagline || '',
|
welcome_tagline: this.channelWelcomeTagline || '',
|
||||||
selectedFeatureFlags: this.selectedFeatureFlags,
|
selectedFeatureFlags: this.selectedFeatureFlags,
|
||||||
reply_time: this.replyTime || 'in_a_few_minutes',
|
reply_time: this.replyTime || 'in_a_few_minutes',
|
||||||
hmac_mandatory: this.hmacMandatory,
|
|
||||||
tweets_enabled: this.tweetsEnabled,
|
tweets_enabled: this.tweetsEnabled,
|
||||||
continuity_via_email: this.continuityViaEmail,
|
continuity_via_email: this.continuityViaEmail,
|
||||||
},
|
},
|
||||||
|
@ -737,11 +565,6 @@ export default {
|
||||||
required,
|
required,
|
||||||
shouldBeUrl,
|
shouldBeUrl,
|
||||||
},
|
},
|
||||||
selectedAgents: {
|
|
||||||
isEmpty() {
|
|
||||||
return !!this.selectedAgents.length;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -163,7 +163,7 @@ export default {
|
||||||
FB.init({
|
FB.init({
|
||||||
appId: window.chatwootConfig.fbAppId,
|
appId: window.chatwootConfig.fbAppId,
|
||||||
xfbml: true,
|
xfbml: true,
|
||||||
version: 'v12.0',
|
version: window.chatwootConfig.fbApiVersion,
|
||||||
status: true,
|
status: true,
|
||||||
});
|
});
|
||||||
window.fbSDKLoaded = true;
|
window.fbSDKLoaded = true;
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default {
|
||||||
FB.init({
|
FB.init({
|
||||||
appId: window.chatwootConfig.fbAppId,
|
appId: window.chatwootConfig.fbAppId,
|
||||||
xfbml: true,
|
xfbml: true,
|
||||||
version: 'v12.0',
|
version: window.chatwootConfig.fbApiVersion,
|
||||||
status: true,
|
status: true,
|
||||||
});
|
});
|
||||||
window.fbSDKLoaded = true;
|
window.fbSDKLoaded = true;
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -22,7 +22,7 @@ class Instagram::MessageText < Instagram::WebhooksBaseService
|
||||||
|
|
||||||
return unsend_message if message_is_deleted?
|
return unsend_message if message_is_deleted?
|
||||||
|
|
||||||
ensure_contact(contact_id)
|
ensure_contact(contact_id) if contacts_first_message?(contact_id)
|
||||||
|
|
||||||
create_message
|
create_message
|
||||||
end
|
end
|
||||||
|
@ -36,7 +36,7 @@ class Instagram::MessageText < Instagram::WebhooksBaseService
|
||||||
rescue Koala::Facebook::AuthenticationError
|
rescue Koala::Facebook::AuthenticationError
|
||||||
@inbox.channel.authorization_error!
|
@inbox.channel.authorization_error!
|
||||||
raise
|
raise
|
||||||
rescue StandardError => e
|
rescue StandardError, Koala::Facebook::ClientError => e
|
||||||
result = {}
|
result = {}
|
||||||
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception
|
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception
|
||||||
end
|
end
|
||||||
|
@ -52,6 +52,10 @@ class Instagram::MessageText < Instagram::WebhooksBaseService
|
||||||
@messaging[:message][:is_deleted].present?
|
@messaging[:message][:is_deleted].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def contacts_first_message?(ig_scope_id)
|
||||||
|
@inbox.contact_inboxes.where(source_id: ig_scope_id).empty? && @inbox.channel.instagram_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
def unsend_message
|
def unsend_message
|
||||||
message_to_delete = @inbox.messages.find_by(
|
message_to_delete = @inbox.messages.find_by(
|
||||||
source_id: @messaging[:message][:mid]
|
source_id: @messaging[:message][:mid]
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
window.chatwootConfig = {
|
window.chatwootConfig = {
|
||||||
hostURL: '<%= ENV.fetch('FRONTEND_URL', '') %>',
|
hostURL: '<%= ENV.fetch('FRONTEND_URL', '') %>',
|
||||||
fbAppId: '<%= ENV.fetch('FB_APP_ID', nil) %>',
|
fbAppId: '<%= ENV.fetch('FB_APP_ID', nil) %>',
|
||||||
|
fbApiVersion: '<%= @global_config['FACEBOOK_API_VERSION'] %>',
|
||||||
signupEnabled: '<%= @global_config['ENABLE_ACCOUNT_SIGNUP'] %>',
|
signupEnabled: '<%= @global_config['ENABLE_ACCOUNT_SIGNUP'] %>',
|
||||||
<% if @global_config['VAPID_PUBLIC_KEY'] %>
|
<% if @global_config['VAPID_PUBLIC_KEY'] %>
|
||||||
vapidPublicKey: new Uint8Array(<%= Base64.urlsafe_decode64(@global_config['VAPID_PUBLIC_KEY']).bytes %>),
|
vapidPublicKey: new Uint8Array(<%= Base64.urlsafe_decode64(@global_config['VAPID_PUBLIC_KEY']).bytes %>),
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Integrations::Slack::IncomingMessageBuilder
|
||||||
if message.present?
|
if message.present?
|
||||||
SUPPORTED_MESSAGE_TYPES.include?(message[:type]) && !attached_file_message?
|
SUPPORTED_MESSAGE_TYPES.include?(message[:type]) && !attached_file_message?
|
||||||
else
|
else
|
||||||
params[:event][:files].any? && !attached_file_message?
|
params[:event][:files].present? && !attached_file_message?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ class Seeders::AccountSeeder
|
||||||
|
|
||||||
def seed!
|
def seed!
|
||||||
seed_canned_responses
|
seed_canned_responses
|
||||||
|
seed_inboxes
|
||||||
end
|
end
|
||||||
|
|
||||||
def seed_canned_responses(count: 50)
|
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))
|
account.canned_responses.create(content: Faker::Quote.fortune_cookie, short_code: Faker::Alphanumeric.alpha(number: 10))
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -223,6 +223,40 @@ RSpec.describe 'Reports API', type: :request do
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when an agent has access to multiple accounts' do
|
||||||
|
let(:account1) { create(:account) }
|
||||||
|
let(:account2) { create(:account) }
|
||||||
|
|
||||||
|
let(:params) do
|
||||||
|
super().merge(
|
||||||
|
type: :agent,
|
||||||
|
since: 30.days.ago.to_i.to_s,
|
||||||
|
until: date_timestamp.to_s
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns agent metrics from the current account' do
|
||||||
|
admin1 = create(:user, account: account1, role: :administrator)
|
||||||
|
inbox1 = create(:inbox, account: account1)
|
||||||
|
inbox2 = create(:inbox, account: account2)
|
||||||
|
|
||||||
|
create(:account_user, user: admin1, account: account2)
|
||||||
|
create(:conversation, account: account1, inbox: inbox1,
|
||||||
|
assignee: admin1, created_at: Time.zone.today - 2.days)
|
||||||
|
create(:conversation, account: account2, inbox: inbox2,
|
||||||
|
assignee: admin1, created_at: Time.zone.today - 2.days)
|
||||||
|
|
||||||
|
get "/api/v2/accounts/#{account1.id}/reports/summary",
|
||||||
|
params: params.merge({ id: admin1.id }),
|
||||||
|
headers: admin1.create_new_auth_token
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response['conversations_count']).to eq(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET /api/v2/accounts/:account_id/reports/inboxes' do
|
describe 'GET /api/v2/accounts/:account_id/reports/inboxes' do
|
||||||
|
|
|
@ -145,14 +145,17 @@ RSpec.describe 'Platform Users API', type: :request do
|
||||||
expect(response).to have_http_status(:unauthorized)
|
expect(response).to have_http_status(:unauthorized)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the user' do
|
it 'updates the user attributes' do
|
||||||
create(:platform_app_permissible, platform_app: platform_app, permissible: user)
|
create(:platform_app_permissible, platform_app: platform_app, permissible: user)
|
||||||
patch "/platform/api/v1/users/#{user.id}", params: { name: 'test123', custom_attributes: { test: 'test_update' } },
|
patch "/platform/api/v1/users/#{user.id}", params: {
|
||||||
|
name: 'test123', email: 'newtestemail@test.com', custom_attributes: { test: 'test_update' }
|
||||||
|
},
|
||||||
headers: { api_access_token: platform_app.access_token.token }, as: :json
|
headers: { api_access_token: platform_app.access_token.token }, as: :json
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
data = JSON.parse(response.body)
|
data = JSON.parse(response.body)
|
||||||
expect(data['name']).to eq('test123')
|
expect(data['name']).to eq('test123')
|
||||||
|
expect(data['email']).to eq('newtestemail@test.com')
|
||||||
expect(data['custom_attributes']['test']).to eq('test_update')
|
expect(data['custom_attributes']['test']).to eq('test_update')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -61,6 +61,15 @@ describe Integrations::Slack::IncomingMessageBuilder do
|
||||||
expect(conversation.messages.count).to eql(messages_count)
|
expect(conversation.messages.count).to eql(messages_count)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not create message for invalid event type and event files is not present' do
|
||||||
|
messages_count = conversation.messages.count
|
||||||
|
message_with_attachments[:event][:files] = nil
|
||||||
|
builder = described_class.new(message_with_attachments)
|
||||||
|
allow(builder).to receive(:sender).and_return(nil)
|
||||||
|
builder.perform
|
||||||
|
expect(conversation.messages.count).to eql(messages_count)
|
||||||
|
end
|
||||||
|
|
||||||
it 'saves attachment if params files present' do
|
it 'saves attachment if params files present' do
|
||||||
expect(hook).not_to eq nil
|
expect(hook).not_to eq nil
|
||||||
messages_count = conversation.messages.count
|
messages_count = conversation.messages.count
|
||||||
|
|
Loading…
Reference in a new issue