Merge branch 'develop' into chore/conversation-participants

This commit is contained in:
Sojan Jose 2022-12-05 12:29:36 +03:00 committed by GitHub
commit e62bb86a40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 139 additions and 23 deletions

View file

@ -21,6 +21,7 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
def create
@portal = Current.account.portals.build(portal_params)
@portal.custom_domain = parsed_custom_domain
@portal.save!
process_attached_logo
end
@ -28,6 +29,7 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
def update
ActiveRecord::Base.transaction do
@portal.update!(portal_params) if params[:portal].present?
# @portal.custom_domain = parsed_custom_domain
process_attached_logo
rescue StandardError => e
Rails.logger.error e
@ -73,4 +75,9 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
def set_current_page
@current_page = params[:page] || 1
end
def parsed_custom_domain
domain = URI.parse(@portal.custom_domain)
domain.is_a?(URI::HTTP) ? domain.host : @portal.custom_domain
end
end

View file

@ -187,6 +187,10 @@ import {
hasPressedAltAndKKey,
} from 'shared/helpers/KeyboardHelpers';
import { conversationListPageURL } from '../helper/URLHelper';
import {
isOnMentionsView,
isOnUnattendedView,
} from '../store/modules/conversations/helpers/actionHelpers';
export default {
components: {
@ -652,10 +656,16 @@ export default {
params: { accountId, inbox_id: inboxId, label, teamId },
name,
} = this.$route;
let conversationType = '';
if (isOnMentionsView({ route: { name } })) {
conversationType = 'mention';
} else if (isOnUnattendedView({ route: { name } })) {
conversationType = 'unattended';
}
this.$router.push(
conversationListPageURL({
accountId,
conversationType: name === 'conversation_mentions' ? 'mention' : '',
conversationType: conversationType,
customViewId: this.foldersId,
inboxId,
label,

View file

@ -87,6 +87,10 @@ import {
} from 'dashboard/helper/inbox';
import SecondaryChildNavItem from './SecondaryChildNavItem';
import {
isOnMentionsView,
isOnUnattendedView,
} from '../../../store/modules/conversations/helpers/actionHelpers';
export default {
components: { SecondaryChildNavItem },
@ -115,19 +119,31 @@ export default {
this.menuItem.featureFlag
);
},
isInboxConversation() {
isAllConversations() {
return (
this.$store.state.route.name === 'inbox_conversation' &&
this.menuItem.toStateName === 'home'
);
},
isMentions() {
return (
isOnMentionsView({ route: this.$route }) &&
this.menuItem.toStateName === 'conversation_mentions'
);
},
isUnattended() {
return (
isOnUnattendedView({ route: this.$route }) &&
this.menuItem.toStateName === 'conversation_unattended'
);
},
isTeamsSettings() {
return (
this.$store.state.route.name === 'settings_teams_edit' &&
this.menuItem.toStateName === 'settings_teams_list'
);
},
isInboxsSettings() {
isInboxSettings() {
return (
this.$store.state.route.name === 'settings_inbox_show' &&
this.menuItem.toStateName === 'settings_inbox_list'
@ -150,14 +166,20 @@ export default {
},
computedClass() {
// If active Inbox is present
// donot highlight conversations
// If active inbox is present, do not highlight conversations
if (this.activeInbox) return ' ';
if (
this.isAllConversations ||
this.isMentions ||
this.isUnattended ||
this.isCurrentRoute
) {
return 'is-active';
}
if (this.hasSubMenu) {
if (
this.isInboxConversation ||
this.isTeamsSettings ||
this.isInboxsSettings ||
this.isInboxSettings ||
this.isIntegrationsSettings ||
this.isApplicationsSettings
) {
@ -166,10 +188,6 @@ export default {
return ' ';
}
if (this.isCurrentRoute) {
return 'is-active';
}
return '';
},
},

View file

@ -23,6 +23,7 @@ import 'videojs-wavesurfer/dist/videojs.wavesurfer.js';
import 'videojs-record/dist/videojs.record.js';
import 'videojs-record/dist/plugins/videojs.record.opus-recorder.js';
import { format, addSeconds } from 'date-fns';
import { AUDIO_FORMATS } from 'shared/constants/messages';
WaveSurfer.microphone = MicrophonePlugin;
@ -70,13 +71,26 @@ export default {
record: {
audio: true,
video: false,
displayMilliseconds: false,
maxLength: 300,
audioEngine: 'opus-recorder',
audioWorkerURL: encoderWorker,
audioChannels: 1,
audioSampleRate: 48000,
audioBitRate: 128,
...(this.audioRecordFormat === AUDIO_FORMATS.WEBM && {
monitorGain: 0,
recordingGain: 1,
numberOfChannels: 1,
encoderSampleRate: 16000,
originalSampleRateOverride: 16000,
streamPages: true,
maxFramesPerPage: 1,
encoderFrameSize: 1,
encoderPath: 'opus-recorder/dist/waveWorker.min.js',
}),
...(this.audioRecordFormat === AUDIO_FORMATS.OGG && {
displayMilliseconds: false,
maxLength: 300,
audioEngine: 'opus-recorder',
audioWorkerURL: encoderWorker,
audioChannels: 1,
audioSampleRate: 48000,
audioBitRate: 128,
}),
},
},
},
@ -86,6 +100,12 @@ export default {
isRecording() {
return this.player && this.player.record().isRecording();
},
audioRecordFormat() {
if (this.isAWebWidgetInbox) {
return AUDIO_FORMATS.WEBM;
}
return AUDIO_FORMATS.OGG;
},
},
mounted() {
window.Recorder = Recorder;

View file

@ -65,6 +65,7 @@ export default {
placeholder: { type: String, default: '' },
isPrivate: { type: Boolean, default: false },
enableSuggestions: { type: Boolean, default: true },
updateSelectionWith: { type: String, default: '' },
},
data() {
return {
@ -162,6 +163,25 @@ export default {
isPrivate() {
this.reloadState();
},
updateSelectionWith(newValue, oldValue) {
if (!this.editorView) {
return null;
}
if (newValue !== oldValue) {
if (this.updateSelectionWith !== '') {
const node = this.editorView.state.schema.text(
this.updateSelectionWith
);
const tr = this.editorView.state.tr.replaceSelectionWith(node);
this.editorView.focus();
this.state = this.editorView.state.apply(tr);
this.emitOnChange();
this.$emit('clear-selection');
}
}
return null;
},
},
created() {
this.state = createState(this.value, this.placeholder, this.plugins);

View file

@ -232,11 +232,18 @@ export default {
return this.showFileUpload || this.isNote;
},
showAudioRecorderButton() {
// Disable audio recorder for safari browser as recording is not supported
const isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(
navigator.userAgent
);
return (
this.isFeatureEnabledonAccount(
this.accountId,
FEATURE_FLAGS.VOICE_RECORDER
) && this.showAudioRecorder
) &&
this.showAudioRecorder &&
!isSafari
);
},
showAudioPlayStopButton() {

View file

@ -60,6 +60,7 @@
class="input"
:is-private="isOnPrivateNote"
:placeholder="messagePlaceHolder"
:update-selection-with="updateEditorSelectionWith"
:min-height="4"
@typing-off="onTypingOff"
@typing-on="onTypingOn"
@ -67,6 +68,7 @@
@blur="onBlur"
@toggle-user-mention="toggleUserMention"
@toggle-canned-menu="toggleCannedMenu"
@clear-selection="clearEditorSelection"
/>
</div>
<div v-if="hasAttachments" class="attachment-preview-box" @paste="onPaste">
@ -215,6 +217,7 @@ export default {
ccEmails: '',
doAutoSaveDraft: () => {},
showWhatsAppTemplatesModal: false,
updateEditorSelectionWith: '',
};
},
computed: {
@ -707,8 +710,26 @@ export default {
}
this.$nextTick(() => this.$refs.messageInput.focus());
},
clearEditorSelection() {
this.updateEditorSelectionWith = '';
},
insertEmoji(emoji, selectionStart, selectionEnd) {
const { message } = this;
const newMessage =
message.slice(0, selectionStart) +
emoji +
message.slice(selectionEnd, message.length);
this.message = newMessage;
},
emojiOnClick(emoji) {
this.message = `${this.message}${emoji} `;
if (this.showRichContentEditor) {
this.updateEditorSelectionWith = emoji;
this.onFocus();
}
if (!this.showRichContentEditor) {
const { selectionStart, selectionEnd } = this.$refs.messageInput.$el;
this.insertEmoji(emoji, selectionStart, selectionEnd);
}
},
clearMessage() {
this.message = '';

View file

@ -77,12 +77,16 @@ export const conversationListPageURL = ({
url = `accounts/${accountId}/label/${label}`;
} else if (teamId) {
url = `accounts/${accountId}/team/${teamId}`;
} else if (conversationType === 'mention') {
url = `accounts/${accountId}/mentions/conversations`;
} else if (inboxId) {
url = `accounts/${accountId}/inbox/${inboxId}`;
} else if (customViewId) {
url = `accounts/${accountId}/custom_view/${customViewId}`;
} else if (conversationType) {
const urlMap = {
mention: 'mentions/conversations',
unattended: 'unattended/conversations',
};
url = `accounts/${accountId}/${urlMap[conversationType]}`;
}
return frontendURL(url);
};

View file

@ -99,6 +99,8 @@ const MUTE_ACTION = {
export const isAConversationRoute = routeName =>
[
'inbox_conversation',
'conversation_through_mentions',
'conversation_through_unattended',
'conversation_through_inbox',
'conversations_through_label',
'conversations_through_team',

View file

@ -72,3 +72,8 @@ export const CSAT_RATINGS = [
color: '#44CE4B',
},
];
export const AUDIO_FORMATS = {
WEBM: 'audio/webm',
OGG: 'audio/ogg',
};

View file

@ -91,7 +91,8 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do
portal_params = {
portal: {
name: 'test_portal',
slug: 'test_kbase'
slug: 'test_kbase',
custom_domain: 'https://support.chatwoot.dev'
},
logo: file
}
@ -103,6 +104,7 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do
json_response = JSON.parse(response.body)
expect(json_response['name']).to eql('test_portal')
expect(json_response['logo']['filename']).to eql('avatar.png')
expect(json_response['custom_domain']).to eql('support.chatwoot.dev')
end
end
end