Merge branch 'release/1.14.3'
This commit is contained in:
116
Gemfile.lock
116
Gemfile.lock
@@ -18,58 +18,58 @@ GEM
|
|||||||
specs:
|
specs:
|
||||||
action-cable-testing (0.6.1)
|
action-cable-testing (0.6.1)
|
||||||
actioncable (>= 5.0)
|
actioncable (>= 5.0)
|
||||||
actioncable (6.0.3.5)
|
actioncable (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (6.0.3.5)
|
actionmailbox (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
activestorage (= 6.0.3.5)
|
activestorage (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
actionmailer (6.0.3.5)
|
actionmailer (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
actionview (= 6.0.3.5)
|
actionview (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (6.0.3.5)
|
actionpack (6.0.3.6)
|
||||||
actionview (= 6.0.3.5)
|
actionview (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
rack (~> 2.0, >= 2.0.8)
|
rack (~> 2.0, >= 2.0.8)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (6.0.3.5)
|
actiontext (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
activestorage (= 6.0.3.5)
|
activestorage (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (6.0.3.5)
|
actionview (6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
activejob (6.0.3.5)
|
activejob (6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (6.0.3.5)
|
activemodel (6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
activerecord (6.0.3.5)
|
activerecord (6.0.3.6)
|
||||||
activemodel (= 6.0.3.5)
|
activemodel (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
activerecord-import (1.0.7)
|
activerecord-import (1.0.7)
|
||||||
activerecord (>= 3.2)
|
activerecord (>= 3.2)
|
||||||
activestorage (6.0.3.5)
|
activestorage (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
marcel (~> 0.3.1)
|
marcel (~> 1.0.0)
|
||||||
activesupport (6.0.3.5)
|
activesupport (6.0.3.6)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
@@ -261,7 +261,7 @@ GEM
|
|||||||
mime-types (~> 3.0)
|
mime-types (~> 3.0)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
i18n (1.8.8)
|
i18n (1.8.9)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
ice_nine (0.11.2)
|
ice_nine (0.11.2)
|
||||||
inflecto (0.0.2)
|
inflecto (0.0.2)
|
||||||
@@ -303,19 +303,17 @@ GEM
|
|||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.7.1)
|
mail (2.7.1)
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
marcel (0.3.3)
|
marcel (1.0.0)
|
||||||
mimemagic (~> 0.3.2)
|
|
||||||
maxminddb (0.1.22)
|
maxminddb (0.1.22)
|
||||||
memoist (0.16.2)
|
memoist (0.16.2)
|
||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
mime-types (3.3.1)
|
mime-types (3.3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2020.0512)
|
mime-types-data (3.2020.0512)
|
||||||
mimemagic (0.3.5)
|
|
||||||
mini_magick (4.10.1)
|
mini_magick (4.10.1)
|
||||||
mini_mime (1.0.2)
|
mini_mime (1.0.3)
|
||||||
mini_portile2 (2.5.0)
|
mini_portile2 (2.5.0)
|
||||||
minitest (5.14.3)
|
minitest (5.14.4)
|
||||||
momentjs-rails (2.20.1)
|
momentjs-rails (2.20.1)
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
msgpack (1.3.3)
|
msgpack (1.3.3)
|
||||||
@@ -325,8 +323,8 @@ GEM
|
|||||||
net-http-persistent (4.0.0)
|
net-http-persistent (4.0.0)
|
||||||
connection_pool (~> 2.2)
|
connection_pool (~> 2.2)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
nio4r (2.5.5)
|
nio4r (2.5.7)
|
||||||
nokogiri (1.11.1)
|
nokogiri (1.11.2)
|
||||||
mini_portile2 (~> 2.5.0)
|
mini_portile2 (~> 2.5.0)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oauth (0.5.4)
|
oauth (0.5.4)
|
||||||
@@ -357,29 +355,29 @@ GEM
|
|||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rails (6.0.3.5)
|
rails (6.0.3.6)
|
||||||
actioncable (= 6.0.3.5)
|
actioncable (= 6.0.3.6)
|
||||||
actionmailbox (= 6.0.3.5)
|
actionmailbox (= 6.0.3.6)
|
||||||
actionmailer (= 6.0.3.5)
|
actionmailer (= 6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
actiontext (= 6.0.3.5)
|
actiontext (= 6.0.3.6)
|
||||||
actionview (= 6.0.3.5)
|
actionview (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
activemodel (= 6.0.3.5)
|
activemodel (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
activestorage (= 6.0.3.5)
|
activestorage (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
bundler (>= 1.3.0)
|
bundler (>= 1.3.0)
|
||||||
railties (= 6.0.3.5)
|
railties (= 6.0.3.6)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.3.0)
|
rails-html-sanitizer (1.3.0)
|
||||||
loofah (~> 2.3)
|
loofah (~> 2.3)
|
||||||
railties (6.0.3.5)
|
railties (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.20.3, < 2.0)
|
thor (>= 0.20.3, < 2.0)
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ class ContactIdentifyAction
|
|||||||
|
|
||||||
def update_contact
|
def update_contact
|
||||||
custom_attributes = params[:custom_attributes] ? @contact.custom_attributes.merge(params[:custom_attributes]) : @contact.custom_attributes
|
custom_attributes = params[:custom_attributes] ? @contact.custom_attributes.merge(params[:custom_attributes]) : @contact.custom_attributes
|
||||||
@contact.update!(params.slice(:name, :email, :identifier).merge({ custom_attributes: custom_attributes }))
|
# blank identifier or email will throw unique index error
|
||||||
|
# TODO: replace reject { |_k, v| v.blank? } with compact_blank when rails is upgraded
|
||||||
|
@contact.update!(params.slice(:name, :email, :identifier).reject { |_k, v| v.blank? }.merge({ custom_attributes: custom_attributes }))
|
||||||
ContactAvatarJob.perform_later(@contact, params[:avatar_url]) if params[:avatar_url].present?
|
ContactAvatarJob.perform_later(@contact, params[:avatar_url]) if params[:avatar_url].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ class Api::V1::Widget::BaseController < ApplicationController
|
|||||||
@contact_inbox = @web_widget.inbox.contact_inboxes.find_by(
|
@contact_inbox = @web_widget.inbox.contact_inboxes.find_by(
|
||||||
source_id: auth_token_params[:source_id]
|
source_id: auth_token_params[:source_id]
|
||||||
)
|
)
|
||||||
@contact = @contact_inbox.contact
|
@contact = @contact_inbox&.contact
|
||||||
|
raise ActiveRecord::RecordNotFound unless @contact
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_conversation
|
def create_conversation
|
||||||
|
|||||||
61
app/javascript/dashboard/components/ui/WootButton.vue
Normal file
61
app/javascript/dashboard/components/ui/WootButton.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
:class="[
|
||||||
|
variant,
|
||||||
|
size,
|
||||||
|
colorScheme,
|
||||||
|
classNames,
|
||||||
|
isDisabled ? 'disabled' : '',
|
||||||
|
]"
|
||||||
|
:disabled="isDisabled || isLoading"
|
||||||
|
@click="handleClick"
|
||||||
|
>
|
||||||
|
<spinner v-if="isLoading" size="small" />
|
||||||
|
<i v-if="icon" :class="icon"></i>
|
||||||
|
<span v-if="$slots.default"><slot></slot></span>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Spinner from 'shared/components/Spinner.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WootButton',
|
||||||
|
components: { Spinner },
|
||||||
|
props: {
|
||||||
|
variant: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
colorScheme: {
|
||||||
|
type: String,
|
||||||
|
default: 'primary',
|
||||||
|
},
|
||||||
|
classNames: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
isDisabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isLoading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClick(evt) {
|
||||||
|
this.$emit('click', evt);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -143,7 +143,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
parsedLastMessage() {
|
parsedLastMessage() {
|
||||||
return this.getPlainText(this.lastMessageInChat.content);
|
const { content_attributes: contentAttributes } = this.lastMessageInChat;
|
||||||
|
const { email: { subject } = {} } = contentAttributes || {};
|
||||||
|
return this.getPlainText(subject || this.lastMessageInChat.content);
|
||||||
},
|
},
|
||||||
|
|
||||||
chatInbox() {
|
chatInbox() {
|
||||||
|
|||||||
@@ -107,11 +107,23 @@ export default {
|
|||||||
this.contentAttributes,
|
this.contentAttributes,
|
||||||
this.$t('CONVERSATION.NO_RESPONSE')
|
this.$t('CONVERSATION.NO_RESPONSE')
|
||||||
);
|
);
|
||||||
let messageContent =
|
|
||||||
this.formatMessage(this.data.content, this.isATweet) +
|
|
||||||
botMessageContent;
|
|
||||||
|
|
||||||
return messageContent;
|
const {
|
||||||
|
email: { html_content: { full: fullHTMLContent } = {} } = {},
|
||||||
|
} = this.contentAttributes;
|
||||||
|
|
||||||
|
if (fullHTMLContent && this.isIncoming) {
|
||||||
|
let parsedContent = new DOMParser().parseFromString(
|
||||||
|
fullHTMLContent || '',
|
||||||
|
'text/html'
|
||||||
|
);
|
||||||
|
if (!parsedContent.getElementsByTagName('parsererror').length) {
|
||||||
|
return parsedContent.body.innerHTML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this.formatMessage(this.data.content, this.isATweet) + botMessageContent
|
||||||
|
);
|
||||||
},
|
},
|
||||||
contentAttributes() {
|
contentAttributes() {
|
||||||
return this.data.content_attributes || {};
|
return this.data.content_attributes || {};
|
||||||
|
|||||||
@@ -87,14 +87,18 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
activeList() {
|
activeList() {
|
||||||
return this.accountLabels.filter(accountLabel =>
|
return this.accountLabels
|
||||||
this.savedLabels.includes(accountLabel.title)
|
.filter(accountLabel => this.savedLabels.includes(accountLabel.title))
|
||||||
);
|
.sort((a, b) => {
|
||||||
|
return a.title.localeCompare(b.title);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
inactiveList() {
|
inactiveList() {
|
||||||
return this.accountLabels.filter(
|
return this.accountLabels
|
||||||
accountLabel => !this.savedLabels.includes(accountLabel.title)
|
.filter(accountLabel => !this.savedLabels.includes(accountLabel.title))
|
||||||
);
|
.sort((a, b) => {
|
||||||
|
return a.title.localeCompare(b.title);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import hljs from 'highlight.js';
|
|||||||
import Multiselect from 'vue-multiselect';
|
import Multiselect from 'vue-multiselect';
|
||||||
import WootSwitch from 'components/ui/Switch';
|
import WootSwitch from 'components/ui/Switch';
|
||||||
import WootWizard from 'components/ui/Wizard';
|
import WootWizard from 'components/ui/Wizard';
|
||||||
|
import WootButton from 'components/ui/WootButton';
|
||||||
import { sync } from 'vuex-router-sync';
|
import { sync } from 'vuex-router-sync';
|
||||||
import Vuelidate from 'vuelidate';
|
import Vuelidate from 'vuelidate';
|
||||||
import VTooltip from 'v-tooltip';
|
import VTooltip from 'v-tooltip';
|
||||||
@@ -48,6 +49,7 @@ Vue.use(hljs.vuePlugin);
|
|||||||
Vue.component('multiselect', Multiselect);
|
Vue.component('multiselect', Multiselect);
|
||||||
Vue.component('woot-switch', WootSwitch);
|
Vue.component('woot-switch', WootSwitch);
|
||||||
Vue.component('woot-wizard', WootWizard);
|
Vue.component('woot-wizard', WootWizard);
|
||||||
|
Vue.component('woot-button', WootButton);
|
||||||
|
|
||||||
const i18nConfig = new VueI18n({
|
const i18nConfig = new VueI18n({
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
|
|||||||
@@ -49,10 +49,13 @@ export default {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '~widget/assets/scss/mixins.scss';
|
@import '~widget/assets/scss/mixins.scss';
|
||||||
|
|
||||||
|
$logo-size: 56px;
|
||||||
|
|
||||||
.header-expanded {
|
.header-expanded {
|
||||||
.logo {
|
.logo {
|
||||||
width: 56px;
|
width: $logo-size;
|
||||||
height: 56px;
|
height: $logo-size;
|
||||||
|
border-radius: $logo-size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export default {
|
|||||||
if (workingHoursEnabled) {
|
if (workingHoursEnabled) {
|
||||||
return this.outOfOfficeMessage;
|
return this.outOfOfficeMessage;
|
||||||
}
|
}
|
||||||
return this.$t('TEAM_AVAILABILITY.OFFLINE');
|
return '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
},
|
},
|
||||||
"TEAM_AVAILABILITY": {
|
"TEAM_AVAILABILITY": {
|
||||||
"ONLINE": "We are online",
|
"ONLINE": "We are online",
|
||||||
"OFFLINE": "We are offline"
|
"OFFLINE": "We are away at the moment"
|
||||||
},
|
},
|
||||||
"REPLY_TIME": {
|
"REPLY_TIME": {
|
||||||
"IN_A_FEW_MINUTES": "Typically replies in a few minutes",
|
"IN_A_FEW_MINUTES": "Typically replies in a few minutes",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class ApplicationMailbox < ActionMailbox::Base
|
|||||||
def self.reply_mail?
|
def self.reply_mail?
|
||||||
proc do |inbound_mail_obj|
|
proc do |inbound_mail_obj|
|
||||||
is_a_reply_email = false
|
is_a_reply_email = false
|
||||||
inbound_mail_obj.mail.to.each do |email|
|
inbound_mail_obj.mail.to&.each do |email|
|
||||||
username = email.split('@')[0]
|
username = email.split('@')[0]
|
||||||
match_result = username.match(REPLY_EMAIL_USERNAME_PATTERN)
|
match_result = username.match(REPLY_EMAIL_USERNAME_PATTERN)
|
||||||
if match_result
|
if match_result
|
||||||
@@ -21,7 +21,7 @@ class ApplicationMailbox < ActionMailbox::Base
|
|||||||
def self.support_mail?
|
def self.support_mail?
|
||||||
proc do |inbound_mail_obj|
|
proc do |inbound_mail_obj|
|
||||||
is_a_support_email = false
|
is_a_support_email = false
|
||||||
inbound_mail_obj.mail.to.each do |email|
|
inbound_mail_obj.mail.to&.each do |email|
|
||||||
channel = Channel::Email.find_by('email = ? OR forward_to_email = ?', email, email)
|
channel = Channel::Email.find_by('email = ? OR forward_to_email = ?', email, email)
|
||||||
if channel.present?
|
if channel.present?
|
||||||
is_a_support_email = true
|
is_a_support_email = true
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class Notification < ApplicationRecord
|
|||||||
I18n.t(
|
I18n.t(
|
||||||
'notifications.notification_title.assigned_conversation_new_message',
|
'notifications.notification_title.assigned_conversation_new_message',
|
||||||
display_id: conversation.display_id,
|
display_id: conversation.display_id,
|
||||||
content: primary_actor.content.truncate_words(10)
|
content: primary_actor.content&.truncate_words(10)
|
||||||
)
|
)
|
||||||
when 'conversation_mention'
|
when 'conversation_mention'
|
||||||
I18n.t('notifications.notification_title.conversation_mention', display_id: conversation.display_id, name: secondary_actor.name)
|
I18n.t('notifications.notification_title.conversation_mention', display_id: conversation.display_id, name: secondary_actor.name)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
shared: &shared
|
shared: &shared
|
||||||
version: '1.14.2'
|
version: '1.14.3'
|
||||||
|
|
||||||
development:
|
development:
|
||||||
<<: *shared
|
<<: *shared
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
module ExceptionList
|
module ExceptionList
|
||||||
URI_EXCEPTIONS = [Errno::ETIMEDOUT, Errno::ECONNREFUSED, URI::InvalidURIError, Net::OpenTimeout, SocketError].freeze
|
URI_EXCEPTIONS = [Errno::ETIMEDOUT, Errno::ECONNREFUSED, URI::InvalidURIError, Net::OpenTimeout, SocketError].freeze
|
||||||
REST_CLIENT_EXCEPTIONS = [RestClient::NotFound, RestClient::GatewayTimeout, RestClient::BadRequest, RestClient::MethodNotAllowed].freeze
|
REST_CLIENT_EXCEPTIONS = [RestClient::NotFound, RestClient::GatewayTimeout, RestClient::BadRequest,
|
||||||
|
RestClient::MethodNotAllowed, RestClient::Forbidden].freeze
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@chatwoot/chatwoot",
|
"name": "@chatwoot/chatwoot",
|
||||||
"version": "1.14.2",
|
"version": "1.14.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"eslint": "eslint app/javascript --fix",
|
"eslint": "eslint app/javascript --fix",
|
||||||
|
|||||||
@@ -44,5 +44,15 @@ describe ::ContactIdentifyAction do
|
|||||||
expect { contact.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
expect { contact.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when contacts with blank identifiers exist and identify action is called with blank identifier' do
|
||||||
|
it 'updates the attributes of contact passed in to identify action' do
|
||||||
|
create(:contact, account: account, identifier: '')
|
||||||
|
params = { identifier: '', name: 'new name' }
|
||||||
|
result = described_class.new(contact: contact, params: params).perform
|
||||||
|
expect(result.id).to eq contact.id
|
||||||
|
expect(result.name).to eq 'new name'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,6 +25,21 @@ RSpec.describe '/api/v1/widget/conversations/toggle_typing', type: :request do
|
|||||||
expect(json_response['status']).to eq(conversation.status)
|
expect(json_response['status']).to eq(conversation.status)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a conversation but invalid source id' do
|
||||||
|
it 'returns the correct conversation params' do
|
||||||
|
allow(Rails.configuration.dispatcher).to receive(:dispatch)
|
||||||
|
|
||||||
|
payload = { source_id: 'invalid source id', inbox_id: web_widget.inbox.id }
|
||||||
|
token = ::Widget::TokenService.new(payload: payload).generate_token
|
||||||
|
get '/api/v1/widget/conversations',
|
||||||
|
headers: { 'X-Auth-Token' => token },
|
||||||
|
params: { website_token: web_widget.website_token },
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST /api/v1/widget/conversations' do
|
describe 'POST /api/v1/widget/conversations' do
|
||||||
|
|||||||
@@ -41,6 +41,14 @@ RSpec.describe Notification do
|
|||||||
#{message.content.truncate_words(10)}"
|
#{message.content.truncate_words(10)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns appropriate title suited for the notification type assigned_conversation_new_message when attachment message' do
|
||||||
|
# checking content nil should be suffice for attachments
|
||||||
|
message = create(:message, sender: create(:user), content: nil)
|
||||||
|
notification = create(:notification, notification_type: 'assigned_conversation_new_message', primary_actor: message)
|
||||||
|
|
||||||
|
expect(notification.push_message_title).to eq "[New message] - ##{notification.conversation.display_id} "
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns appropriate title suited for the notification type conversation_mention' do
|
it 'returns appropriate title suited for the notification type conversation_mention' do
|
||||||
message = create(:message, sender: create(:user))
|
message = create(:message, sender: create(:user))
|
||||||
notification = create(:notification, notification_type: 'conversation_mention', primary_actor: message, secondary_actor: message.sender)
|
notification = create(:notification, notification_type: 'conversation_mention', primary_actor: message, secondary_actor: message.sender)
|
||||||
|
|||||||
Reference in New Issue
Block a user