Merge branch 'develop' into feat/new-auth-screens
This commit is contained in:
commit
2e50ba137b
44 changed files with 482 additions and 78 deletions
|
@ -161,13 +161,15 @@ USE_INBOX_AVATAR_FOR_BOT=true
|
|||
## NewRelic
|
||||
# https://docs.newrelic.com/docs/agents/ruby-agent/configuration/ruby-agent-configuration/
|
||||
# NEW_RELIC_LICENSE_KEY=
|
||||
# Set this to true to allow newrelic apm to send logs.
|
||||
# This is turned off by default.
|
||||
# NEW_RELIC_APPLICATION_LOGGING_ENABLED=
|
||||
|
||||
## Datadog
|
||||
## https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md#environment-variables
|
||||
# DD_TRACE_AGENT_URL=
|
||||
|
||||
|
||||
|
||||
## IP look up configuration
|
||||
## ref https://github.com/alexreisner/geocoder/blob/master/README_API_GUIDE.md
|
||||
## works only on accounts with ip look up feature enabled
|
||||
|
|
|
@ -376,7 +376,7 @@ GEM
|
|||
net-http-persistent (4.0.1)
|
||||
connection_pool (~> 2.2)
|
||||
netrc (0.11.0)
|
||||
newrelic_rpm (8.4.0)
|
||||
newrelic_rpm (8.7.0)
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.4)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
|
|
|
@ -15,11 +15,10 @@ class ContactBuilder
|
|||
end
|
||||
|
||||
def create_contact_inbox(contact)
|
||||
::ContactInbox.create!(
|
||||
::ContactInbox.create_with(hmac_verified: hmac_verified || false).find_or_create_by!(
|
||||
contact_id: contact.id,
|
||||
inbox_id: inbox.id,
|
||||
source_id: source_id,
|
||||
hmac_verified: hmac_verified || false
|
||||
source_id: source_id
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class Messages::Facebook::MessageBuilder < Messages::Messenger::MessageBuilder
|
|||
return if contact.present?
|
||||
|
||||
@contact = Contact.create!(contact_params.except(:remote_avatar_url))
|
||||
@contact_inbox = ContactInbox.create(contact: contact, inbox: @inbox, source_id: @sender_id)
|
||||
@contact_inbox = ContactInbox.find_or_create_by!(contact: contact, inbox: @inbox, source_id: @sender_id)
|
||||
end
|
||||
|
||||
def build_message
|
||||
|
|
|
@ -45,6 +45,8 @@ class RoomChannel < ApplicationCable::Channel
|
|||
end
|
||||
|
||||
def current_account
|
||||
return if current_user.blank?
|
||||
|
||||
@current_account ||= if @current_user.is_a? Contact
|
||||
@current_user.account
|
||||
else
|
||||
|
|
|
@ -7,7 +7,6 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts:
|
|||
build_inbox
|
||||
setup_webhooks if @twilio_channel.sms?
|
||||
rescue StandardError => e
|
||||
Sentry.capture_exception(e)
|
||||
render_could_not_create_error(e.message)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ class Api::V1::Accounts::Conversations::BaseController < Api::V1::Accounts::Base
|
|||
private
|
||||
|
||||
def conversation
|
||||
@conversation ||= Current.account.conversations.find_by(display_id: params[:conversation_id])
|
||||
@conversation ||= Current.account.conversations.find_by!(display_id: params[:conversation_id])
|
||||
authorize @conversation.inbox, :show?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ class MessageFinder
|
|||
|
||||
def current_messages
|
||||
if @params[:before].present?
|
||||
messages.reorder('created_at desc').where('id < ?', @params[:before]).limit(20).reverse
|
||||
messages.reorder('created_at desc').where('id < ?', @params[:before].to_i).limit(20).reverse
|
||||
else
|
||||
messages.reorder('created_at desc').limit(20).reverse
|
||||
end
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
:menu-config="activeSecondaryMenu"
|
||||
:current-role="currentRole"
|
||||
@add-label="showAddLabelPopup"
|
||||
@toggle-accounts="toggleAccountModal"
|
||||
/>
|
||||
</aside>
|
||||
</template>
|
||||
|
|
|
@ -1,14 +1,34 @@
|
|||
<template>
|
||||
<div v-if="showShowCurrentAccountContext" class="account-context--group">
|
||||
<div
|
||||
v-if="showShowCurrentAccountContext"
|
||||
class="account-context--group"
|
||||
@mouseover="setShowSwitch"
|
||||
@mouseleave="resetShowSwitch"
|
||||
>
|
||||
{{ $t('SIDEBAR.CURRENTLY_VIEWING_ACCOUNT') }}
|
||||
<p class="account-context--name text-ellipsis">
|
||||
{{ account.name }}
|
||||
</p>
|
||||
<transition name="fade">
|
||||
<div v-if="showSwitchButton" class="account-context--switch-group">
|
||||
<woot-button
|
||||
variant="clear"
|
||||
icon="arrow-swap"
|
||||
class="cursor-pointer"
|
||||
@click="$emit('toggle-accounts')"
|
||||
>
|
||||
{{ $t('SIDEBAR.SWITCH') }}
|
||||
</woot-button>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
export default {
|
||||
data() {
|
||||
return { showSwitchButton: false };
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
account: 'getCurrentAccount',
|
||||
|
@ -18,6 +38,14 @@ export default {
|
|||
return this.userAccounts.length > 1 && this.account.name;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setShowSwitch() {
|
||||
this.showSwitchButton = true;
|
||||
},
|
||||
resetShowSwitch() {
|
||||
this.showSwitchButton = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
@ -27,10 +55,49 @@ export default {
|
|||
font-size: var(--font-size-mini);
|
||||
padding: var(--space-small);
|
||||
margin-bottom: var(--space-small);
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: var(--b-100);
|
||||
}
|
||||
|
||||
.account-context--name {
|
||||
font-weight: var(--font-weight-medium);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.account-context--switch-group {
|
||||
--overlay-shadow: linear-gradient(
|
||||
to right,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 50%
|
||||
);
|
||||
|
||||
align-items: center;
|
||||
background-image: var(--overlay-shadow);
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: var(--border-radius-normal);
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: var(--border-radius-normal);
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: end;
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 300ms ease;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div v-if="hasSecondaryMenu" class="main-nav secondary-menu">
|
||||
<account-context />
|
||||
<account-context @toggle-accounts="toggleAccountModal" />
|
||||
<transition-group name="menu-list" tag="ul" class="menu vertical">
|
||||
<secondary-nav-item
|
||||
v-for="menuItem in accessibleMenuItems"
|
||||
|
@ -224,6 +224,9 @@ export default {
|
|||
showAddLabelPopup() {
|
||||
this.$emit('add-label');
|
||||
},
|
||||
toggleAccountModal() {
|
||||
this.$emit('toggle-accounts');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -17,12 +17,8 @@ export default {
|
|||
value: { type: Boolean, default: false },
|
||||
},
|
||||
methods: {
|
||||
onClick(event) {
|
||||
if (event.pointerId === -1) {
|
||||
event.preventDefault();
|
||||
} else {
|
||||
this.$emit('input', !this.value);
|
||||
}
|
||||
onClick() {
|
||||
this.$emit('input', !this.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
},
|
||||
"SIDEBAR": {
|
||||
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
||||
"SWITCH": "Switch",
|
||||
"CONVERSATIONS": "Conversations",
|
||||
"ALL_CONVERSATIONS": "All Conversations",
|
||||
"MENTIONED_CONVERSATIONS": "Mentions",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<draggable v-model="preChatFields" tag="tbody">
|
||||
<tr v-for="(item, index) in preChatFields" :key="index">
|
||||
<draggable v-model="preChatFieldOptions" tag="tbody" @end="onDragEnd">
|
||||
<tr v-for="(item, index) in preChatFieldOptions" :key="index">
|
||||
<td class="pre-chat-field"><fluent-icon icon="drag" /></td>
|
||||
<td class="pre-chat-field">
|
||||
<woot-switch
|
||||
|
@ -51,15 +51,27 @@ export default {
|
|||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
handlePreChatFieldOptions: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
preChatFieldOptions: this.preChatFields,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
preChatFields() {
|
||||
this.preChatFieldOptions = this.preChatFields;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isFieldEditable(item) {
|
||||
return !!standardFieldKeys[item.name] || !item.enabled;
|
||||
},
|
||||
handlePreChatFieldOptions(event, type, item) {
|
||||
this.$emit('update', event, type, item);
|
||||
},
|
||||
onDragEnd() {
|
||||
this.$emit('drag-end', this.preChatFieldOptions);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
"
|
||||
/>
|
||||
</label>
|
||||
<label class="medium-8 columns">
|
||||
{{ $t('INBOX_MGMT.PRE_CHAT_FORM.SET_FIELDS') }}
|
||||
<div class="medium-8 columns">
|
||||
<label>{{ $t('INBOX_MGMT.PRE_CHAT_FORM.SET_FIELDS') }}</label>
|
||||
<table class="table table-striped w-full">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
|
@ -58,10 +58,11 @@
|
|||
</thead>
|
||||
<pre-chat-fields
|
||||
:pre-chat-fields="preChatFields"
|
||||
:handle-pre-chat-field-options="handlePreChatFieldOptions"
|
||||
@update="handlePreChatFieldOptions"
|
||||
@drag-end="changePreChatFieldFieldsOrder"
|
||||
/>
|
||||
</table>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<woot-submit-button
|
||||
|
@ -138,6 +139,10 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
changePreChatFieldFieldsOrder(updatedPreChatFieldOptions) {
|
||||
this.preChatFields = updatedPreChatFieldOptions;
|
||||
},
|
||||
|
||||
async updateInbox() {
|
||||
try {
|
||||
const payload = {
|
||||
|
|
|
@ -10,7 +10,8 @@ import {
|
|||
getUserCookieName,
|
||||
hasUserKeys,
|
||||
} from '../sdk/cookieHelpers';
|
||||
|
||||
import { addClass, removeClass } from '../sdk/DOMHelpers';
|
||||
import { SDK_SET_BUBBLE_VISIBILITY } from 'shared/constants/sharedFrameEvents';
|
||||
const runSDK = ({ baseUrl, websiteToken }) => {
|
||||
if (window.$chatwoot) {
|
||||
return;
|
||||
|
@ -36,6 +37,23 @@ const runSDK = ({ baseUrl, websiteToken }) => {
|
|||
IFrameHelper.events.toggleBubble(state);
|
||||
},
|
||||
|
||||
toggleBubbleVisibility(visibility) {
|
||||
let widgetElm = document.querySelector('.woot--bubble-holder');
|
||||
let widgetHolder = document.querySelector('.woot-widget-holder');
|
||||
if (visibility === 'hide') {
|
||||
addClass(widgetHolder, 'woot-widget--without-bubble');
|
||||
addClass(widgetElm, 'woot-hidden');
|
||||
window.$chatwoot.hideMessageBubble = true;
|
||||
} else if (visibility === 'show') {
|
||||
removeClass(widgetElm, 'woot-hidden');
|
||||
removeClass(widgetHolder, 'woot-widget--without-bubble');
|
||||
window.$chatwoot.hideMessageBubble = false;
|
||||
}
|
||||
IFrameHelper.sendMessage(SDK_SET_BUBBLE_VISIBILITY, {
|
||||
hideMessageBubble: window.$chatwoot.hideMessageBubble,
|
||||
});
|
||||
},
|
||||
|
||||
popoutChatWindow() {
|
||||
IFrameHelper.events.popoutChatWindow({
|
||||
baseUrl: window.$chatwoot.baseUrl,
|
||||
|
|
|
@ -121,7 +121,7 @@ export const IFrameHelper = {
|
|||
|
||||
setupAudioListeners: () => {
|
||||
const { baseUrl = '' } = window.$chatwoot;
|
||||
getAlertAudio(baseUrl).then(() =>
|
||||
getAlertAudio(baseUrl, 'widget').then(() =>
|
||||
initOnEvents.forEach(event => {
|
||||
document.removeEventListener(
|
||||
event,
|
||||
|
@ -175,9 +175,6 @@ export const IFrameHelper = {
|
|||
},
|
||||
|
||||
setBubbleLabel(message) {
|
||||
if (window.$chatwoot.hideMessageBubble) {
|
||||
return;
|
||||
}
|
||||
setBubbleText(window.$chatwoot.launcherTitle || message.label);
|
||||
},
|
||||
|
||||
|
@ -263,33 +260,32 @@ export const IFrameHelper = {
|
|||
if (IFrameHelper.getBubbleHolder().length) {
|
||||
return;
|
||||
}
|
||||
createBubbleHolder();
|
||||
createBubbleHolder(window.$chatwoot.hideMessageBubble);
|
||||
onLocationChangeListener();
|
||||
if (!window.$chatwoot.hideMessageBubble) {
|
||||
let className = 'woot-widget-bubble';
|
||||
let closeBtnClassName = `woot-elements--${window.$chatwoot.position} woot-widget-bubble woot--close woot--hide`;
|
||||
|
||||
if (isFlatWidgetStyle(window.$chatwoot.widgetStyle)) {
|
||||
className += ' woot-widget-bubble--flat';
|
||||
closeBtnClassName += ' woot-widget-bubble--flat';
|
||||
}
|
||||
let className = 'woot-widget-bubble';
|
||||
let closeBtnClassName = `woot-elements--${window.$chatwoot.position} woot-widget-bubble woot--close woot--hide`;
|
||||
|
||||
const chatIcon = createBubbleIcon({
|
||||
className,
|
||||
src: bubbleImg,
|
||||
target: chatBubble,
|
||||
});
|
||||
|
||||
addClass(closeBubble, closeBtnClassName);
|
||||
|
||||
chatIcon.style.background = widgetColor;
|
||||
closeBubble.style.background = widgetColor;
|
||||
|
||||
bubbleHolder.appendChild(chatIcon);
|
||||
bubbleHolder.appendChild(closeBubble);
|
||||
bubbleHolder.appendChild(createNotificationBubble());
|
||||
onClickChatBubble();
|
||||
if (isFlatWidgetStyle(window.$chatwoot.widgetStyle)) {
|
||||
className += ' woot-widget-bubble--flat';
|
||||
closeBtnClassName += ' woot-widget-bubble--flat';
|
||||
}
|
||||
|
||||
const chatIcon = createBubbleIcon({
|
||||
className,
|
||||
src: bubbleImg,
|
||||
target: chatBubble,
|
||||
});
|
||||
|
||||
addClass(closeBubble, closeBtnClassName);
|
||||
|
||||
chatIcon.style.background = widgetColor;
|
||||
closeBubble.style.background = widgetColor;
|
||||
|
||||
bubbleHolder.appendChild(chatIcon);
|
||||
bubbleHolder.appendChild(closeBubble);
|
||||
bubbleHolder.appendChild(createNotificationBubble());
|
||||
onClickChatBubble();
|
||||
},
|
||||
toggleCloseButton: () => {
|
||||
let isMobile = false;
|
||||
|
|
|
@ -39,7 +39,10 @@ export const createBubbleIcon = ({ className, src, target }) => {
|
|||
return target;
|
||||
};
|
||||
|
||||
export const createBubbleHolder = () => {
|
||||
export const createBubbleHolder = hideMessageBubble => {
|
||||
if (hideMessageBubble) {
|
||||
addClass(bubbleHolder, 'woot-hidden');
|
||||
}
|
||||
addClass(bubbleHolder, 'woot--bubble-holder');
|
||||
body.appendChild(bubbleHolder);
|
||||
};
|
||||
|
|
|
@ -227,4 +227,8 @@ export const SDK_CSS = `
|
|||
width: 400px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.woot-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
`;
|
||||
|
|
1
app/javascript/shared/constants/sharedFrameEvents.js
Normal file
1
app/javascript/shared/constants/sharedFrameEvents.js
Normal file
|
@ -0,0 +1 @@
|
|||
export const SDK_SET_BUBBLE_VISIBILITY = 'sdk-set-bubble-visibility';
|
|
@ -4,7 +4,7 @@ import { IFrameHelper } from 'widget/helpers/utils';
|
|||
import { showBadgeOnFavicon } from './faviconHelper';
|
||||
|
||||
export const initOnEvents = ['click', 'touchstart', 'keypress', 'keydown'];
|
||||
export const getAlertAudio = async (baseUrl = '') => {
|
||||
export const getAlertAudio = async (baseUrl = '', type = 'dashboard') => {
|
||||
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
const playsound = audioBuffer => {
|
||||
window.playAudioAlert = () => {
|
||||
|
@ -17,7 +17,7 @@ export const getAlertAudio = async (baseUrl = '') => {
|
|||
};
|
||||
|
||||
try {
|
||||
const resourceUrl = `${baseUrl}/dashboard/audios/ding.mp3`;
|
||||
const resourceUrl = `${baseUrl}/audio/${type}/ding.mp3`;
|
||||
const audioRequest = new Request(resourceUrl);
|
||||
|
||||
fetch(audioRequest)
|
||||
|
|
|
@ -38,6 +38,9 @@ import {
|
|||
ON_CAMPAIGN_MESSAGE_CLICK,
|
||||
ON_UNREAD_MESSAGE_CLICK,
|
||||
} from './constants/widgetBusEvents';
|
||||
|
||||
import { SDK_SET_BUBBLE_VISIBILITY } from '../shared/constants/sharedFrameEvents';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
|
@ -103,6 +106,7 @@ export default {
|
|||
'setAppConfig',
|
||||
'setReferrerHost',
|
||||
'setWidgetColor',
|
||||
'setBubbleVisibility',
|
||||
]),
|
||||
...mapActions('conversation', ['fetchOldConversations', 'setUserLastSeen']),
|
||||
...mapActions('campaign', [
|
||||
|
@ -285,6 +289,8 @@ export default {
|
|||
if (!message.isOpen) {
|
||||
this.resetCampaign();
|
||||
}
|
||||
} else if (message.event === SDK_SET_BUBBLE_VISIBILITY) {
|
||||
this.setBubbleVisibility(message.hideMessageBubble);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
SET_BUBBLE_VISIBILITY,
|
||||
SET_REFERRER_HOST,
|
||||
SET_WIDGET_APP_CONFIG,
|
||||
SET_WIDGET_COLOR,
|
||||
|
@ -57,6 +58,9 @@ export const actions = {
|
|||
setReferrerHost({ commit }, referrerHost) {
|
||||
commit(SET_REFERRER_HOST, referrerHost);
|
||||
},
|
||||
setBubbleVisibility({ commit }, hideMessageBubble) {
|
||||
commit(SET_BUBBLE_VISIBILITY, hideMessageBubble);
|
||||
},
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
|
@ -76,6 +80,9 @@ export const mutations = {
|
|||
[SET_REFERRER_HOST]($state, referrerHost) {
|
||||
$state.referrerHost = referrerHost;
|
||||
},
|
||||
[SET_BUBBLE_VISIBILITY]($state, hideMessageBubble) {
|
||||
$state.hideMessageBubble = hideMessageBubble;
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
|
|
|
@ -11,6 +11,13 @@ describe('#actions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('#setBubbleVisibility', () => {
|
||||
it('creates actions properly', () => {
|
||||
actions.setBubbleVisibility({ commit }, false);
|
||||
expect(commit.mock.calls).toEqual([['SET_BUBBLE_VISIBILITY', false]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setWidgetColor', () => {
|
||||
it('creates actions properly', () => {
|
||||
actions.setWidgetColor({ commit }, '#eaeaea');
|
||||
|
|
|
@ -9,6 +9,14 @@ describe('#mutations', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('#SET_BUBBLE_VISIBILITY', () => {
|
||||
it('sets bubble visibility properly', () => {
|
||||
const state = { hideMessageBubble: false };
|
||||
mutations.SET_BUBBLE_VISIBILITY(state, true);
|
||||
expect(state.hideMessageBubble).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_WIDGET_COLOR', () => {
|
||||
it('sets widget color properly', () => {
|
||||
const state = { widgetColor: '' };
|
||||
|
|
|
@ -5,3 +5,4 @@ export const SET_WIDGET_COLOR = 'SET_WIDGET_COLOR';
|
|||
export const UPDATE_CONVERSATION_ATTRIBUTES = 'UPDATE_CONVERSATION_ATTRIBUTES';
|
||||
export const TOGGLE_WIDGET_OPEN = 'TOGGLE_WIDGET_OPEN';
|
||||
export const SET_REFERRER_HOST = 'SET_REFERRER_HOST';
|
||||
export const SET_BUBBLE_VISIBILITY = 'SET_BUBBLE_VISIBILITY';
|
||||
|
|
|
@ -9,7 +9,7 @@ class HookJob < ApplicationJob
|
|||
process_dialogflow_integration(hook, event_name, event_data)
|
||||
end
|
||||
rescue StandardError => e
|
||||
Sentry.capture_exception(e)
|
||||
Rails.logger.error e
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_channel_twilio_sms_on_account_id_and_phone_number (account_id,phone_number) UNIQUE
|
||||
# index_channel_twilio_sms_on_account_sid_and_phone_number (account_sid,phone_number) UNIQUE
|
||||
# index_channel_twilio_sms_on_phone_number (phone_number) UNIQUE
|
||||
#
|
||||
|
||||
class Channel::TwilioSms < ApplicationRecord
|
||||
|
@ -23,7 +24,9 @@ class Channel::TwilioSms < ApplicationRecord
|
|||
|
||||
validates :account_sid, presence: true
|
||||
validates :auth_token, presence: true
|
||||
validates :phone_number, uniqueness: { scope: :account_id }, presence: true
|
||||
# NOTE: allowing nil for future when we suppor twilio messaging services
|
||||
# https://github.com/chatwoot/chatwoot/pull/4242
|
||||
validates :phone_number, uniqueness: true, allow_nil: true
|
||||
|
||||
enum medium: { sms: 0, whatsapp: 1 }
|
||||
|
||||
|
|
|
@ -32,6 +32,6 @@ class InboxMember < ApplicationRecord
|
|||
end
|
||||
|
||||
def remove_agent_from_round_robin
|
||||
::RoundRobin::ManageService.new(inbox: inbox).remove_agent_from_queue(user_id)
|
||||
::RoundRobin::ManageService.new(inbox: inbox).remove_agent_from_queue(user_id) if inbox.present?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -82,7 +82,7 @@ Rails.application.configure do
|
|||
allow do
|
||||
origins '*'
|
||||
resource '/packs/*', headers: :any, methods: [:get, :options]
|
||||
resource '/dashboard/audios/ding.mp3', headers: :any, methods: [:get, :options]
|
||||
resource '/audio/*', headers: :any, methods: [:get, :options]
|
||||
resource '*', headers: :any, methods: :any, expose: ['access-token', 'client', 'uid', 'expiry']
|
||||
end
|
||||
end
|
||||
|
|
|
@ -121,7 +121,7 @@ Rails.application.configure do
|
|||
allow do
|
||||
origins '*'
|
||||
resource '/packs/*', headers: :any, methods: [:get, :options]
|
||||
resource '/dashboard/audios/ding.mp3', headers: :any, methods: [:get, :options]
|
||||
resource '/audio/*', headers: :any, methods: [:get, :options]
|
||||
if ActiveModel::Type::Boolean.new.cast(ENV.fetch('CW_API_ONLY_SERVER', false))
|
||||
resource '*', headers: :any, methods: :any, expose: ['access-token', 'client', 'uid', 'expiry']
|
||||
end
|
||||
|
|
|
@ -87,7 +87,7 @@ Rails.application.configure do
|
|||
allow do
|
||||
origins '*'
|
||||
resource '/packs/*', headers: :any, methods: [:get, :options]
|
||||
resource '/dashboard/audios/ding.mp3', headers: :any, methods: [:get, :options]
|
||||
resource '/audio/*', headers: :any, methods: [:get, :options]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,7 +58,7 @@ Rails.application.configure do
|
|||
allow do
|
||||
origins '*'
|
||||
resource '/packs/*', headers: :any, methods: [:get, :options]
|
||||
resource '/dashboard/audios/ding.mp3', headers: :any, methods: [:get, :options]
|
||||
resource '/audio/*', headers: :any, methods: [:get, :options]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,6 +24,24 @@ common: &default_settings
|
|||
# Logging level for log/newrelic_agent.log
|
||||
log_level: <%= ENV.fetch('NEW_RELIC_LOG_LEVEL', 'info') %>
|
||||
|
||||
application_logging:
|
||||
# If `true`, all logging-related features for the agent can be enabled or disabled
|
||||
# independently. If `false`, all logging-related features are disabled.
|
||||
enabled: <%= ENV.fetch('NEW_RELIC_APPLICATION_LOGGING_ENABLED', false) %>
|
||||
forwarding:
|
||||
# If `true`, the agent captures log records emitted by this application.
|
||||
enabled: true
|
||||
# Defines the maximum number of log records to buffer in memory at a time.
|
||||
max_samples_stored: 30000
|
||||
metrics:
|
||||
# If `true`, the agent captures metrics related to logging for this application.
|
||||
enabled: true
|
||||
local_decorating:
|
||||
# If `true`, the agent decorates logs with metadata to link to entities, hosts, traces, and spans.
|
||||
# This requires a log forwarder to send your log files to New Relic.
|
||||
# This should not be used when forwarding is enabled.
|
||||
enabled: false
|
||||
|
||||
|
||||
# Environment-specific settings are in this section.
|
||||
# RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
|
||||
|
|
|
@ -25,14 +25,14 @@ pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }
|
|||
# Workers do not work on JRuby or Windows (both of which do not support
|
||||
# processes).
|
||||
#
|
||||
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
|
||||
workers ENV.fetch('WEB_CONCURRENCY', 1)
|
||||
|
||||
# Use the `preload_app!` method when specifying a `workers` number.
|
||||
# This directive tells Puma to first boot the application and load code
|
||||
# before forking the application. This takes advantage of Copy On Write
|
||||
# process behavior so workers use less memory.
|
||||
#
|
||||
# preload_app!
|
||||
preload_app!
|
||||
|
||||
# Allow puma to be restarted by `rails restart` command.
|
||||
plugin :tmp_restart
|
||||
|
|
|
@ -16,6 +16,6 @@ trigger_scheduled_items_job:
|
|||
|
||||
# executed At every 5th minute..
|
||||
trigger_imap_email_inboxes_job:
|
||||
cron: '*/1 * * * *'
|
||||
cron: '*/5 * * * *'
|
||||
class: 'Inboxes::FetchImapEmailInboxesJob'
|
||||
queue: scheduled_jobs
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
class AddAccountSidUniqueIndexToChannelTwilioSms < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
clear_possible_duplicates
|
||||
|
||||
has_duplicates = Channel::TwilioSms.select(:phone_number).group(:phone_number).having('count(*) > 1').exists?
|
||||
|
||||
if has_duplicates
|
||||
raise <<~ERR.squish
|
||||
ERROR: You have duplicate values for phone_number in "channel_twilio_sms".
|
||||
This causes Twilio account lookup to behave unpredictably. Please eliminate the duplicates
|
||||
and then re-run this migration.
|
||||
ERR
|
||||
end
|
||||
|
||||
remove_index :channel_twilio_sms, [:account_id, :phone_number], unique: true
|
||||
add_index :channel_twilio_sms, :phone_number, unique: true
|
||||
# since look ups are done via account_sid + phone_number, we need to add a unique index
|
||||
add_index :channel_twilio_sms, [:account_sid, :phone_number], unique: true
|
||||
end
|
||||
|
||||
def clear_possible_duplicates
|
||||
# based on the look up in saas it seems like only the first inbox is used in case of duplicates,
|
||||
# so lets try to clear our inboxes with out conversations
|
||||
duplicate_phone_numbers = Channel::TwilioSms.select(:phone_number).group(:phone_number).having('count(*) > 1').collect(&:phone_number)
|
||||
duplicate_phone_numbers.each do |phone_number|
|
||||
# we are skipping the first inbox that was created
|
||||
Channel::TwilioSms.where(phone_number: phone_number).drop(1).each do |channel|
|
||||
inbox = channel.inbox
|
||||
# skip inboxes with conversations
|
||||
next if inbox.conversations.count.positive?
|
||||
|
||||
inbox.destroy
|
||||
end
|
||||
end
|
||||
|
||||
# clear the accounts created with twilio sandbox whatsapp number
|
||||
# Channel::TwilioSms.where(phone_number: 'whatsapp:+14155238886').each { |channel| channel.inbox.destroy }
|
||||
end
|
||||
end
|
|
@ -257,7 +257,8 @@ ActiveRecord::Schema.define(version: 2022_04_28_101325) do
|
|||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.integer "medium", default: 0
|
||||
t.index ["account_id", "phone_number"], name: "index_channel_twilio_sms_on_account_id_and_phone_number", unique: true
|
||||
t.index ["account_sid", "phone_number"], name: "index_channel_twilio_sms_on_account_sid_and_phone_number", unique: true
|
||||
t.index ["phone_number"], name: "index_channel_twilio_sms_on_phone_number", unique: true
|
||||
end
|
||||
|
||||
create_table "channel_twitter_profiles", force: :cascade do |t|
|
||||
|
|
|
@ -37,7 +37,7 @@ class Integrations::Slack::IncomingMessageBuilder
|
|||
if message.present?
|
||||
SUPPORTED_MESSAGE_TYPES.include?(message[:type])
|
||||
else
|
||||
params[:event][:files].any?
|
||||
params.dig(:event, :files).any?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class Webhooks::Trigger
|
|||
timeout: 5
|
||||
)
|
||||
Rails.logger.info "Performed Request: Code - #{response.code}"
|
||||
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
|
||||
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS, URI::InvalidURIError => e
|
||||
Rails.logger.error "Exception: invalid webhook url #{url} : #{e.message}"
|
||||
rescue StandardError => e
|
||||
Rails.logger.error "Exception: invalid webhook url #{url} : #{e.message}"
|
||||
|
|
BIN
public/audio/widget/ding.mp3
Normal file
BIN
public/audio/widget/ding.mp3
Normal file
Binary file not shown.
20
spec/models/inbox_member_spec.rb
Normal file
20
spec/models/inbox_member_spec.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe InboxMember do
|
||||
include ActiveJob::TestHelper
|
||||
|
||||
describe '#DestroyAssociationAsyncJob' do
|
||||
let(:inbox_member) { create(:inbox_member) }
|
||||
|
||||
# ref: https://github.com/chatwoot/chatwoot/issues/4616
|
||||
context 'when parent inbox is destroyed' do
|
||||
it 'enques and processes DestroyAssociationAsyncJob' do
|
||||
perform_enqueued_jobs do
|
||||
inbox_member.inbox.destroy!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
199
yarn.lock
199
yarn.lock
|
@ -2794,6 +2794,47 @@
|
|||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@videojs/http-streaming@2.13.1":
|
||||
version "2.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.13.1.tgz#b7688d91eec969181430e00868b514b16b3b21b7"
|
||||
integrity sha512-1x3fkGSPyL0+iaS3/lTvfnPTtfqzfgG+ELQtPPtTvDwqGol9Mx3TNyZwtSTdIufBrqYRn7XybB/3QNMsyjq13A==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@videojs/vhs-utils" "3.0.4"
|
||||
aes-decrypter "3.1.2"
|
||||
global "^4.4.0"
|
||||
m3u8-parser "4.7.0"
|
||||
mpd-parser "0.21.0"
|
||||
mux.js "6.0.1"
|
||||
video.js "^6 || ^7"
|
||||
|
||||
"@videojs/vhs-utils@3.0.4":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-3.0.4.tgz#e253eecd8e9318f767e752010d213587f94bb03a"
|
||||
integrity sha512-hui4zOj2I1kLzDgf8QDVxD3IzrwjS/43KiS8IHQO0OeeSsb4pB/lgNt1NG7Dv0wMQfCccUpMVLGcK618s890Yg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
global "^4.4.0"
|
||||
url-toolkit "^2.2.1"
|
||||
|
||||
"@videojs/vhs-utils@^3.0.0", "@videojs/vhs-utils@^3.0.2", "@videojs/vhs-utils@^3.0.4":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz#665ba70d78258ba1ab977364e2fe9f4d4799c46c"
|
||||
integrity sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
global "^4.4.0"
|
||||
url-toolkit "^2.2.1"
|
||||
|
||||
"@videojs/xhr@2.6.0":
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.6.0.tgz#cd897e0ad54faf497961bcce3fa16dc15a26bb80"
|
||||
integrity sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
global "~4.4.0"
|
||||
is-function "^1.0.1"
|
||||
|
||||
"@vue/compiler-core@3.0.11":
|
||||
version "3.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.11.tgz#5ef579e46d7b336b8735228758d1c2c505aae69a"
|
||||
|
@ -3018,6 +3059,11 @@
|
|||
"@webassemblyjs/wast-parser" "1.9.0"
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@xmldom/xmldom@^0.7.2":
|
||||
version "0.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d"
|
||||
integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==
|
||||
|
||||
"@xtuc/ieee754@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||
|
@ -3100,6 +3146,16 @@ address@1.1.2, address@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
|
||||
integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==
|
||||
|
||||
aes-decrypter@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/aes-decrypter/-/aes-decrypter-3.1.2.tgz#3545546f8e9f6b878640339a242efe221ba7a7cb"
|
||||
integrity sha512-42nRwfQuPRj9R1zqZBdoxnaAmnIFyDi0MNyTVhjdFOd8fifXKKRfwIHIZ6AMn1or4x5WONzjwRTbTWcsIQ0O4A==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@videojs/vhs-utils" "^3.0.0"
|
||||
global "^4.4.0"
|
||||
pkcs7 "^1.0.4"
|
||||
|
||||
aggregate-error@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
|
||||
|
@ -7333,7 +7389,7 @@ global-prefix@^3.0.0:
|
|||
kind-of "^6.0.2"
|
||||
which "^1.3.1"
|
||||
|
||||
global@^4.4.0:
|
||||
global@^4.3.1, global@^4.4.0, global@~4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
|
||||
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
|
||||
|
@ -7977,6 +8033,11 @@ indexes-of@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
|
||||
integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
|
||||
|
||||
individual@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/individual/-/individual-2.0.0.tgz#833b097dad23294e76117a98fb38e0d9ad61bb97"
|
||||
integrity sha1-gzsJfa0jKU52EXqY+zjg2a1hu5c=
|
||||
|
||||
infer-owner@^1.0.3, infer-owner@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||
|
@ -8321,7 +8382,7 @@ is-fullwidth-code-point@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-function@^1.0.2:
|
||||
is-function@^1.0.1, is-function@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
|
||||
integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==
|
||||
|
@ -9347,6 +9408,11 @@ junk@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
|
||||
integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==
|
||||
|
||||
keycode@^2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.1.tgz#09c23b2be0611d26117ea2501c2c391a01f39eff"
|
||||
integrity sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==
|
||||
|
||||
killable@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
|
||||
|
@ -9775,6 +9841,15 @@ lru-cache@^6.0.0:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
m3u8-parser@4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-4.7.0.tgz#e01e8ce136098ade1b14ee691ea20fc4dc60abf6"
|
||||
integrity sha512-48l/OwRyjBm+QhNNigEEcRcgbRvnUjL7rxs597HmW9QSNbyNvt+RcZ9T/d9vxi9A9z7EZrB1POtZYhdRlwYQkQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@videojs/vhs-utils" "^3.0.0"
|
||||
global "^4.4.0"
|
||||
|
||||
magic-string@^0.25.7:
|
||||
version "0.25.7"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
|
||||
|
@ -10193,6 +10268,16 @@ move-concurrently@^1.0.1:
|
|||
rimraf "^2.5.4"
|
||||
run-queue "^1.0.3"
|
||||
|
||||
mpd-parser@0.21.0:
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/mpd-parser/-/mpd-parser-0.21.0.tgz#c2036cce19522383b93c973180fdd82cd646168e"
|
||||
integrity sha512-NbpMJ57qQzFmfCiP1pbL7cGMbVTD0X1hqNgL0VYP1wLlZXLf/HtmvQpNkOA1AHkPVeGQng+7/jEtSvNUzV7Gdg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@videojs/vhs-utils" "^3.0.2"
|
||||
"@xmldom/xmldom" "^0.7.2"
|
||||
global "^4.4.0"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
@ -10231,6 +10316,14 @@ mute-stream@0.0.8:
|
|||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
||||
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
|
||||
|
||||
mux.js@6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-6.0.1.tgz#65ce0f7a961d56c006829d024d772902d28c7755"
|
||||
integrity sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.11.2"
|
||||
global "^4.4.0"
|
||||
|
||||
nan@^2.12.1:
|
||||
version "2.14.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||
|
@ -10683,6 +10776,11 @@ optionator@^0.8.1, optionator@^0.8.3:
|
|||
type-check "~0.3.2"
|
||||
word-wrap "~1.2.3"
|
||||
|
||||
opus-recorder@^8.0.5:
|
||||
version "8.0.5"
|
||||
resolved "https://registry.yarnpkg.com/opus-recorder/-/opus-recorder-8.0.5.tgz#06d3e32e15da57ebc3f57e41b93033475fcb4e3e"
|
||||
integrity sha512-tBRXc9Btds7i3bVfA7d5rekAlyOcfsivt5vSIXHxRV1Oa+s6iXFW8omZ0Lm3ABWotVcEyKt96iIIUcgbV07YOw==
|
||||
|
||||
orderedmap@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.1.1.tgz#c618e77611b3b21d0fe3edc92586265e0059c789"
|
||||
|
@ -11077,6 +11175,13 @@ pirates@^4.0.0, pirates@^4.0.1:
|
|||
dependencies:
|
||||
node-modules-regexp "^1.0.0"
|
||||
|
||||
pkcs7@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/pkcs7/-/pkcs7-1.0.4.tgz#6090b9e71160dabf69209d719cbafa538b00a1cb"
|
||||
integrity sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
|
||||
pkg-dir@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
|
||||
|
@ -12757,7 +12862,7 @@ recast@^0.18.1:
|
|||
private "^0.1.8"
|
||||
source-map "~0.6.1"
|
||||
|
||||
recordrtc@^5.6.2:
|
||||
recordrtc@>=5.6.2:
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/recordrtc/-/recordrtc-5.6.2.tgz#48fc214b35084973ccce82c6251198b5742bc327"
|
||||
integrity sha512-1QNKKNtl7+KcwD1lyOgP3ZlbiJ1d0HtXnypUy7yq49xEERxk31PHvE9RCciDrulPCY7WJ+oz0R9hpNxgsIurGQ==
|
||||
|
@ -13192,6 +13297,13 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
|||
dependencies:
|
||||
aproba "^1.1.1"
|
||||
|
||||
rust-result@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/rust-result/-/rust-result-1.0.0.tgz#34c75b2e6dc39fe5875e5bdec85b5e0f91536f72"
|
||||
integrity sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=
|
||||
dependencies:
|
||||
individual "^2.0.0"
|
||||
|
||||
rxjs@^6.3.3, rxjs@^6.5.3, rxjs@^6.6.7:
|
||||
version "6.6.7"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
|
||||
|
@ -13214,6 +13326,13 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1,
|
|||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
safe-json-parse@4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-4.0.0.tgz#7c0f578cfccd12d33a71c0e05413e2eca171eaac"
|
||||
integrity sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=
|
||||
dependencies:
|
||||
rust-result "^1.0.0"
|
||||
|
||||
safe-regex@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
|
||||
|
@ -13315,6 +13434,11 @@ schema-utils@^3.0.0:
|
|||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
sdp@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sdp/-/sdp-3.0.3.tgz#669958d54663ea9f4a46cc66518c9d980c52c61e"
|
||||
integrity sha512-8EkfckS+XZQaPLyChu4ey7PghrdcraCVNpJe2Gfdi2ON1ylQ7OasuKX+b37R9slnRChwIAiQgt+oj8xXGD8x+A==
|
||||
|
||||
select-hose@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||
|
@ -14872,6 +14996,11 @@ url-parse@^1.4.3, url-parse@^1.5.1:
|
|||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
url-toolkit@^2.2.1:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/url-toolkit/-/url-toolkit-2.2.5.tgz#58406b18e12c58803e14624df5e374f638b0f607"
|
||||
integrity sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==
|
||||
|
||||
url@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
|
||||
|
@ -15040,6 +15169,55 @@ vfile@^4.0.0:
|
|||
unist-util-stringify-position "^2.0.0"
|
||||
vfile-message "^2.0.0"
|
||||
|
||||
video.js@>=7.0.5, "video.js@^6 || ^7":
|
||||
version "7.18.1"
|
||||
resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.18.1.tgz#d93cd4992710d4d95574a00e7d29a2518f9b30f7"
|
||||
integrity sha512-mnXdmkVcD5qQdKMZafDjqdhrnKGettZaGSVkExjACiylSB4r2Yt5W1bchsKmjFpfuNfszsMjTUnnoIWSSqoe/Q==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@videojs/http-streaming" "2.13.1"
|
||||
"@videojs/vhs-utils" "^3.0.4"
|
||||
"@videojs/xhr" "2.6.0"
|
||||
aes-decrypter "3.1.2"
|
||||
global "^4.4.0"
|
||||
keycode "^2.2.0"
|
||||
m3u8-parser "4.7.0"
|
||||
mpd-parser "0.21.0"
|
||||
mux.js "6.0.1"
|
||||
safe-json-parse "4.0.0"
|
||||
videojs-font "3.2.0"
|
||||
videojs-vtt.js "^0.15.3"
|
||||
|
||||
videojs-font@3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232"
|
||||
integrity sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==
|
||||
|
||||
videojs-record@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/videojs-record/-/videojs-record-4.5.0.tgz#6156a52e879fecd7b5e371e2ace0c1853133407f"
|
||||
integrity sha512-p/L6UaEZxCXVqzvH0TYCyUujHbymhqrEiF63KIjOatBxOhG7OVu4RiKEbkOlniBKr2sLoVOmC3vBuk+YBD3CXw==
|
||||
dependencies:
|
||||
recordrtc ">=5.6.2"
|
||||
video.js ">=7.0.5"
|
||||
videojs-wavesurfer ">=3.7.0"
|
||||
webrtc-adapter ">=8.0.0"
|
||||
|
||||
videojs-vtt.js@^0.15.3:
|
||||
version "0.15.3"
|
||||
resolved "https://registry.yarnpkg.com/videojs-vtt.js/-/videojs-vtt.js-0.15.3.tgz#84260393b79487fcf195d9372f812d7fab83a993"
|
||||
integrity sha512-5FvVsICuMRx6Hd7H/Y9s9GDeEtYcXQWzGMS+sl4UX3t/zoHp3y+isSfIPRochnTH7h+Bh1ILyC639xy9Z6kPag==
|
||||
dependencies:
|
||||
global "^4.3.1"
|
||||
|
||||
videojs-wavesurfer@>=3.7.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/videojs-wavesurfer/-/videojs-wavesurfer-3.8.0.tgz#7c32ba65dc35df79681b0c4edd8b3f4ce47e0a63"
|
||||
integrity sha512-qHucCBiEW+4dZ0Zp1k4R1elprUOV+QDw87UDA9QRXtO7GK/MrSdoe/TMFxP9SLnJCiX9xnYdf4OQgrmvJ9UVVw==
|
||||
dependencies:
|
||||
video.js ">=7.0.5"
|
||||
wavesurfer.js ">=5.0.1"
|
||||
|
||||
vm-browserify@^1.0.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
|
@ -15308,10 +15486,10 @@ watchpack@^1.7.4:
|
|||
chokidar "^3.4.1"
|
||||
watchpack-chokidar2 "^2.0.1"
|
||||
|
||||
wavesurfer.js@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/wavesurfer.js/-/wavesurfer.js-5.2.0.tgz#efae107b5b561e9bfe3fffc50e6158136a17643e"
|
||||
integrity sha512-SkPlTXfvKy+ZnEA7f7g7jn6iQg5/8mAvWpVV5vRbIS/FF9TB2ak9J7VayQfzfshOLW/CqccTiN6DDR/fZA902g==
|
||||
wavesurfer.js@>=5.0.1, wavesurfer.js@^6.0.4:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wavesurfer.js/-/wavesurfer.js-6.1.0.tgz#c6d4a192cbe2cb60717c88ea3f0a95bedc3dd571"
|
||||
integrity sha512-Ss8d4PC8r1vSE8Qtf3UhC6o4BWXL1J/tr9DFwshFW2pSZBdkzau6FzWGJUul3aoOZSFb+azC5F/m0I9F+vU72w==
|
||||
|
||||
wbuf@^1.1.0, wbuf@^1.7.3:
|
||||
version "1.7.3"
|
||||
|
@ -15487,6 +15665,13 @@ webpack@4, webpack@^4.46.0:
|
|||
watchpack "^1.7.4"
|
||||
webpack-sources "^1.4.1"
|
||||
|
||||
webrtc-adapter@>=8.0.0:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-8.1.1.tgz#e4a4dfd1b5085d119da40c4efc0147f7d0961cba"
|
||||
integrity sha512-1yXevP7TeZGmklEXkvQVrZp3fOSJlLeXNGCA7NovQokxgP3/e2T3EVGL0eKU87S9vKppWjvRWqnJeSANEspOBg==
|
||||
dependencies:
|
||||
sdp "^3.0.2"
|
||||
|
||||
websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
|
||||
|
|
Loading…
Reference in a new issue