Merge branch 'develop' into feat/add_last_snoozed_option
This commit is contained in:
@@ -4,7 +4,7 @@ import { useAlert } from 'dashboard/composables';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { DirectUpload } from 'activestorage';
|
||||
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
|
||||
import { MAXIMUM_FILE_UPLOAD_SIZE_TWILIO_SMS_CHANNEL } from 'shared/constants/messages';
|
||||
import { getMaxUploadSizeByChannel } from '@chatwoot/utils';
|
||||
|
||||
vi.mock('dashboard/composables/store');
|
||||
vi.mock('dashboard/composables', () => ({
|
||||
@@ -13,6 +13,7 @@ vi.mock('dashboard/composables', () => ({
|
||||
vi.mock('vue-i18n');
|
||||
vi.mock('activestorage');
|
||||
vi.mock('shared/helpers/FileHelper');
|
||||
vi.mock('@chatwoot/utils');
|
||||
|
||||
describe('useFileUpload', () => {
|
||||
const mockAttachFile = vi.fn();
|
||||
@@ -22,6 +23,11 @@ describe('useFileUpload', () => {
|
||||
file: new File(['test'], 'test.jpg', { type: 'image/jpeg' }),
|
||||
};
|
||||
|
||||
const inbox = {
|
||||
channel_type: 'Channel::WhatsApp',
|
||||
medium: 'whatsapp',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -37,11 +43,12 @@ describe('useFileUpload', () => {
|
||||
|
||||
useI18n.mockReturnValue({ t: mockTranslate });
|
||||
checkFileSizeLimit.mockReturnValue(true);
|
||||
getMaxUploadSizeByChannel.mockReturnValue(25); // default max size MB for tests
|
||||
});
|
||||
|
||||
it('should handle direct file upload when enabled', () => {
|
||||
it('handles direct file upload when direct uploads enabled', () => {
|
||||
const { onFileUpload } = useFileUpload({
|
||||
isATwilioSMSChannel: false,
|
||||
inbox,
|
||||
attachFile: mockAttachFile,
|
||||
});
|
||||
|
||||
@@ -52,6 +59,16 @@ describe('useFileUpload', () => {
|
||||
|
||||
onFileUpload(mockFile);
|
||||
|
||||
// size rules called with inbox + mime
|
||||
expect(getMaxUploadSizeByChannel).toHaveBeenCalledWith({
|
||||
channelType: inbox.channel_type,
|
||||
medium: inbox.medium,
|
||||
mime: 'image/jpeg',
|
||||
});
|
||||
|
||||
// size check called with max from helper
|
||||
expect(checkFileSizeLimit).toHaveBeenCalledWith(mockFile, 25);
|
||||
|
||||
expect(DirectUpload).toHaveBeenCalledWith(
|
||||
mockFile.file,
|
||||
'/api/v1/accounts/123/conversations/456/direct_uploads',
|
||||
@@ -63,7 +80,7 @@ describe('useFileUpload', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle indirect file upload when direct upload is disabled', () => {
|
||||
it('handles indirect file upload when direct upload disabled', () => {
|
||||
useMapGetter.mockImplementation(getter => {
|
||||
const getterMap = {
|
||||
getCurrentAccountId: { value: '123' },
|
||||
@@ -75,22 +92,24 @@ describe('useFileUpload', () => {
|
||||
});
|
||||
|
||||
const { onFileUpload } = useFileUpload({
|
||||
isATwilioSMSChannel: false,
|
||||
inbox,
|
||||
attachFile: mockAttachFile,
|
||||
});
|
||||
|
||||
onFileUpload(mockFile);
|
||||
|
||||
expect(DirectUpload).not.toHaveBeenCalled();
|
||||
expect(getMaxUploadSizeByChannel).toHaveBeenCalled();
|
||||
expect(checkFileSizeLimit).toHaveBeenCalledWith(mockFile, 25);
|
||||
expect(mockAttachFile).toHaveBeenCalledWith({ file: mockFile });
|
||||
});
|
||||
|
||||
it('should show alert when file size exceeds limit', () => {
|
||||
it('shows alert when file size exceeds limit', () => {
|
||||
checkFileSizeLimit.mockReturnValue(false);
|
||||
mockTranslate.mockReturnValue('File size exceeds limit');
|
||||
|
||||
const { onFileUpload } = useFileUpload({
|
||||
isATwilioSMSChannel: false,
|
||||
inbox,
|
||||
attachFile: mockAttachFile,
|
||||
});
|
||||
|
||||
@@ -100,28 +119,37 @@ describe('useFileUpload', () => {
|
||||
expect(mockAttachFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use different max file size for Twilio SMS channel', () => {
|
||||
it('uses per-mime limits from helper', () => {
|
||||
getMaxUploadSizeByChannel.mockImplementation(({ mime }) =>
|
||||
mime.startsWith('image/') ? 10 : 50
|
||||
);
|
||||
const { onFileUpload } = useFileUpload({
|
||||
isATwilioSMSChannel: true,
|
||||
inbox,
|
||||
attachFile: mockAttachFile,
|
||||
});
|
||||
|
||||
DirectUpload.mockImplementation(() => ({
|
||||
create: cb => cb(null, { signed_id: 'blob' }),
|
||||
}));
|
||||
|
||||
onFileUpload(mockFile);
|
||||
|
||||
expect(checkFileSizeLimit).toHaveBeenCalledWith(
|
||||
mockFile,
|
||||
MAXIMUM_FILE_UPLOAD_SIZE_TWILIO_SMS_CHANNEL
|
||||
);
|
||||
expect(getMaxUploadSizeByChannel).toHaveBeenCalledWith({
|
||||
channelType: inbox.channel_type,
|
||||
medium: inbox.medium,
|
||||
mime: 'image/jpeg',
|
||||
});
|
||||
expect(checkFileSizeLimit).toHaveBeenCalledWith(mockFile, 10);
|
||||
});
|
||||
|
||||
it('should handle direct upload errors', () => {
|
||||
it('handles direct upload errors', () => {
|
||||
const mockError = 'Upload failed';
|
||||
DirectUpload.mockImplementation(() => ({
|
||||
create: callback => callback(mockError, null),
|
||||
}));
|
||||
|
||||
const { onFileUpload } = useFileUpload({
|
||||
isATwilioSMSChannel: false,
|
||||
inbox,
|
||||
attachFile: mockAttachFile,
|
||||
});
|
||||
|
||||
@@ -131,15 +159,16 @@ describe('useFileUpload', () => {
|
||||
expect(mockAttachFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing when file is null', () => {
|
||||
it('does nothing when file is null', () => {
|
||||
const { onFileUpload } = useFileUpload({
|
||||
isATwilioSMSChannel: false,
|
||||
inbox,
|
||||
attachFile: mockAttachFile,
|
||||
});
|
||||
|
||||
onFileUpload(null);
|
||||
|
||||
expect(checkFileSizeLimit).not.toHaveBeenCalled();
|
||||
expect(getMaxUploadSizeByChannel).not.toHaveBeenCalled();
|
||||
expect(mockAttachFile).not.toHaveBeenCalled();
|
||||
expect(useAlert).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { defineComponent, h } from 'vue';
|
||||
import { createStore } from 'vuex';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { useInbox } from '../useInbox';
|
||||
import { INBOX_TYPES } from 'dashboard/helper/inbox';
|
||||
|
||||
vi.mock('dashboard/composables/store');
|
||||
vi.mock('dashboard/composables/useTransformKeys');
|
||||
|
||||
// Mock the dependencies
|
||||
const mockStore = createStore({
|
||||
modules: {
|
||||
conversations: {
|
||||
namespaced: false,
|
||||
getters: {
|
||||
getSelectedChat: () => ({ inbox_id: 1 }),
|
||||
},
|
||||
},
|
||||
inboxes: {
|
||||
namespaced: true,
|
||||
getters: {
|
||||
getInboxById: () => id => {
|
||||
const inboxes = {
|
||||
1: {
|
||||
id: 1,
|
||||
channel_type: INBOX_TYPES.WHATSAPP,
|
||||
provider: 'whatsapp_cloud',
|
||||
},
|
||||
2: { id: 2, channel_type: INBOX_TYPES.FB },
|
||||
3: { id: 3, channel_type: INBOX_TYPES.TWILIO, medium: 'sms' },
|
||||
4: { id: 4, channel_type: INBOX_TYPES.TWILIO, medium: 'whatsapp' },
|
||||
5: {
|
||||
id: 5,
|
||||
channel_type: INBOX_TYPES.EMAIL,
|
||||
provider: 'microsoft',
|
||||
},
|
||||
6: { id: 6, channel_type: INBOX_TYPES.EMAIL, provider: 'google' },
|
||||
7: {
|
||||
id: 7,
|
||||
channel_type: INBOX_TYPES.WHATSAPP,
|
||||
provider: 'default',
|
||||
},
|
||||
8: { id: 8, channel_type: INBOX_TYPES.TELEGRAM },
|
||||
9: { id: 9, channel_type: INBOX_TYPES.LINE },
|
||||
10: { id: 10, channel_type: INBOX_TYPES.WEB },
|
||||
11: { id: 11, channel_type: INBOX_TYPES.API },
|
||||
12: { id: 12, channel_type: INBOX_TYPES.SMS },
|
||||
13: { id: 13, channel_type: INBOX_TYPES.INSTAGRAM },
|
||||
14: { id: 14, channel_type: INBOX_TYPES.VOICE },
|
||||
};
|
||||
return inboxes[id] || null;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Mock useMapGetter to return mock store getters
|
||||
vi.mock('dashboard/composables/store', () => ({
|
||||
useMapGetter: vi.fn(getter => {
|
||||
if (getter === 'getSelectedChat') {
|
||||
return { value: { inbox_id: 1 } };
|
||||
}
|
||||
if (getter === 'inboxes/getInboxById') {
|
||||
return { value: mockStore.getters['inboxes/getInboxById'] };
|
||||
}
|
||||
return { value: null };
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock useCamelCase to return the data as-is for testing
|
||||
vi.mock('dashboard/composables/useTransformKeys', () => ({
|
||||
useCamelCase: vi.fn(data => ({
|
||||
...data,
|
||||
channelType: data?.channel_type,
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('useInbox', () => {
|
||||
const createTestComponent = inboxId =>
|
||||
defineComponent({
|
||||
setup() {
|
||||
return useInbox(inboxId);
|
||||
},
|
||||
render() {
|
||||
return h('div');
|
||||
},
|
||||
});
|
||||
|
||||
describe('with current chat context (no inboxId provided)', () => {
|
||||
it('identifies WhatsApp Cloud channel correctly', () => {
|
||||
const wrapper = mount(createTestComponent(), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.isAWhatsAppCloudChannel).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(true);
|
||||
});
|
||||
|
||||
it('returns correct inbox object', () => {
|
||||
const wrapper = mount(createTestComponent(), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.inbox).toEqual({
|
||||
id: 1,
|
||||
channel_type: INBOX_TYPES.WHATSAPP,
|
||||
provider: 'whatsapp_cloud',
|
||||
channelType: INBOX_TYPES.WHATSAPP,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with explicit inboxId provided', () => {
|
||||
it('identifies Facebook inbox correctly', () => {
|
||||
const wrapper = mount(createTestComponent(2), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.isAFacebookInbox).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
|
||||
});
|
||||
|
||||
it('identifies Twilio SMS channel correctly', () => {
|
||||
const wrapper = mount(createTestComponent(3), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.isATwilioChannel).toBe(true);
|
||||
expect(wrapper.vm.isASmsInbox).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
|
||||
});
|
||||
|
||||
it('identifies Twilio WhatsApp channel correctly', () => {
|
||||
const wrapper = mount(createTestComponent(4), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.isATwilioChannel).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(true);
|
||||
expect(wrapper.vm.isATwilioWhatsAppChannel).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppCloudChannel).toBe(false);
|
||||
});
|
||||
|
||||
it('identifies Microsoft email inbox correctly', () => {
|
||||
const wrapper = mount(createTestComponent(5), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.isAnEmailChannel).toBe(true);
|
||||
expect(wrapper.vm.isAMicrosoftInbox).toBe(true);
|
||||
expect(wrapper.vm.isAGoogleInbox).toBe(false);
|
||||
});
|
||||
|
||||
it('identifies Google email inbox correctly', () => {
|
||||
const wrapper = mount(createTestComponent(6), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.isAnEmailChannel).toBe(true);
|
||||
expect(wrapper.vm.isAGoogleInbox).toBe(true);
|
||||
expect(wrapper.vm.isAMicrosoftInbox).toBe(false);
|
||||
});
|
||||
|
||||
it('identifies 360Dialog WhatsApp channel correctly', () => {
|
||||
const wrapper = mount(createTestComponent(7), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.is360DialogWhatsAppChannel).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(true);
|
||||
expect(wrapper.vm.isAWhatsAppCloudChannel).toBe(false);
|
||||
});
|
||||
|
||||
it('identifies all other channel types correctly', () => {
|
||||
// Test Telegram
|
||||
let wrapper = mount(createTestComponent(8), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isATelegramChannel).toBe(true);
|
||||
|
||||
// Test Line
|
||||
wrapper = mount(createTestComponent(9), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isALineChannel).toBe(true);
|
||||
|
||||
// Test Web Widget
|
||||
wrapper = mount(createTestComponent(10), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isAWebWidgetInbox).toBe(true);
|
||||
|
||||
// Test API
|
||||
wrapper = mount(createTestComponent(11), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isAPIInbox).toBe(true);
|
||||
|
||||
// Test SMS
|
||||
wrapper = mount(createTestComponent(12), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isASmsInbox).toBe(true);
|
||||
|
||||
// Test Instagram
|
||||
wrapper = mount(createTestComponent(13), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isAnInstagramChannel).toBe(true);
|
||||
|
||||
// Test Voice
|
||||
wrapper = mount(createTestComponent(14), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
expect(wrapper.vm.isAVoiceChannel).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('handles non-existent inbox ID gracefully', () => {
|
||||
const wrapper = mount(createTestComponent(999), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
// useCamelCase still processes null data, so we get an object with channelType: undefined
|
||||
expect(wrapper.vm.inbox).toEqual({ channelType: undefined });
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
|
||||
expect(wrapper.vm.isAFacebookInbox).toBe(false);
|
||||
});
|
||||
|
||||
it('handles inbox with no data correctly', () => {
|
||||
// The mock will return null for non-existent IDs, but useCamelCase processes it
|
||||
const wrapper = mount(createTestComponent(999), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.inbox.channelType).toBeUndefined();
|
||||
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
|
||||
expect(wrapper.vm.isAFacebookInbox).toBe(false);
|
||||
expect(wrapper.vm.isATelegramChannel).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('return object completeness', () => {
|
||||
it('returns all expected properties', () => {
|
||||
const wrapper = mount(createTestComponent(1), {
|
||||
global: { plugins: [mockStore] },
|
||||
});
|
||||
|
||||
const expectedProperties = [
|
||||
'inbox',
|
||||
'isAFacebookInbox',
|
||||
'isALineChannel',
|
||||
'isAPIInbox',
|
||||
'isASmsInbox',
|
||||
'isATelegramChannel',
|
||||
'isATwilioChannel',
|
||||
'isAWebWidgetInbox',
|
||||
'isAWhatsAppChannel',
|
||||
'isAMicrosoftInbox',
|
||||
'isAGoogleInbox',
|
||||
'isATwilioWhatsAppChannel',
|
||||
'isAWhatsAppCloudChannel',
|
||||
'is360DialogWhatsAppChannel',
|
||||
'isAnEmailChannel',
|
||||
'isAnInstagramChannel',
|
||||
'isAVoiceChannel',
|
||||
];
|
||||
|
||||
expectedProperties.forEach(prop => {
|
||||
expect(wrapper.vm).toHaveProperty(prop);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,22 +1,19 @@
|
||||
import { computed } from 'vue';
|
||||
import { useMapGetter } from 'dashboard/composables/store';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { DirectUpload } from 'activestorage';
|
||||
import {
|
||||
MAXIMUM_FILE_UPLOAD_SIZE,
|
||||
MAXIMUM_FILE_UPLOAD_SIZE_TWILIO_SMS_CHANNEL,
|
||||
} from 'shared/constants/messages';
|
||||
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
|
||||
import { getMaxUploadSizeByChannel } from '@chatwoot/utils';
|
||||
import { MAXIMUM_FILE_UPLOAD_SIZE } from 'shared/constants/messages';
|
||||
|
||||
/**
|
||||
* Composable for handling file uploads in conversations
|
||||
* @param {Object} options - Configuration options
|
||||
* @param {boolean} options.isATwilioSMSChannel - Whether the current channel is Twilio SMS
|
||||
* @param {Function} options.attachFile - Callback function to handle file attachment
|
||||
* @returns {Object} File upload methods and utilities
|
||||
* @param {Object} options
|
||||
* @param {Object} options.inbox - Current inbox object (has channel_type, medium, etc.)
|
||||
* @param {Function} options.attachFile - Callback to handle file attachment
|
||||
* @param {boolean} options.isPrivateNote - Whether the upload is for a private note
|
||||
*/
|
||||
export const useFileUpload = ({ isATwilioSMSChannel, attachFile }) => {
|
||||
export const useFileUpload = ({ inbox, attachFile, isPrivateNote = false }) => {
|
||||
const { t } = useI18n();
|
||||
|
||||
const accountId = useMapGetter('getCurrentAccountId');
|
||||
@@ -24,57 +21,72 @@ export const useFileUpload = ({ isATwilioSMSChannel, attachFile }) => {
|
||||
const currentChat = useMapGetter('getSelectedChat');
|
||||
const globalConfig = useMapGetter('globalConfig/get');
|
||||
|
||||
const maxFileSize = computed(() =>
|
||||
isATwilioSMSChannel
|
||||
? MAXIMUM_FILE_UPLOAD_SIZE_TWILIO_SMS_CHANNEL
|
||||
: MAXIMUM_FILE_UPLOAD_SIZE
|
||||
);
|
||||
// helper: compute max upload size for a given file's mime
|
||||
const maxSizeFor = mime => {
|
||||
// Use default file size limit for private notes
|
||||
if (isPrivateNote) {
|
||||
return MAXIMUM_FILE_UPLOAD_SIZE;
|
||||
}
|
||||
|
||||
return getMaxUploadSizeByChannel({
|
||||
channelType: inbox?.channel_type,
|
||||
medium: inbox?.medium, // e.g. 'sms' | 'whatsapp' | etc.
|
||||
mime, // e.g. 'image/png'
|
||||
});
|
||||
};
|
||||
|
||||
const alertOverLimit = maxSizeMB =>
|
||||
useAlert(
|
||||
t('CONVERSATION.FILE_SIZE_LIMIT', {
|
||||
MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE: maxSizeMB,
|
||||
})
|
||||
);
|
||||
|
||||
const handleDirectFileUpload = file => {
|
||||
if (!file) return;
|
||||
|
||||
if (checkFileSizeLimit(file, maxFileSize.value)) {
|
||||
const upload = new DirectUpload(
|
||||
file.file,
|
||||
`/api/v1/accounts/${accountId.value}/conversations/${currentChat.value.id}/direct_uploads`,
|
||||
{
|
||||
directUploadWillCreateBlobWithXHR: xhr => {
|
||||
xhr.setRequestHeader(
|
||||
'api_access_token',
|
||||
currentUser.value.access_token
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
const mime = file.file?.type || file.type;
|
||||
const maxSizeMB = maxSizeFor(mime);
|
||||
|
||||
upload.create((error, blob) => {
|
||||
if (error) {
|
||||
useAlert(error);
|
||||
} else {
|
||||
attachFile({ file, blob });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
useAlert(
|
||||
t('CONVERSATION.FILE_SIZE_LIMIT', {
|
||||
MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE: maxFileSize.value,
|
||||
})
|
||||
);
|
||||
if (!checkFileSizeLimit(file, maxSizeMB)) {
|
||||
alertOverLimit(maxSizeMB);
|
||||
return;
|
||||
}
|
||||
|
||||
const upload = new DirectUpload(
|
||||
file.file,
|
||||
`/api/v1/accounts/${accountId.value}/conversations/${currentChat.value.id}/direct_uploads`,
|
||||
{
|
||||
directUploadWillCreateBlobWithXHR: xhr => {
|
||||
xhr.setRequestHeader(
|
||||
'api_access_token',
|
||||
currentUser.value.access_token
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
upload.create((error, blob) => {
|
||||
if (error) {
|
||||
useAlert(error);
|
||||
} else {
|
||||
attachFile({ file, blob });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleIndirectFileUpload = file => {
|
||||
if (!file) return;
|
||||
|
||||
if (checkFileSizeLimit(file, maxFileSize.value)) {
|
||||
attachFile({ file });
|
||||
} else {
|
||||
useAlert(
|
||||
t('CONVERSATION.FILE_SIZE_LIMIT', {
|
||||
MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE: maxFileSize.value,
|
||||
})
|
||||
);
|
||||
const mime = file.file?.type || file.type;
|
||||
const maxSizeMB = maxSizeFor(mime);
|
||||
|
||||
if (!checkFileSizeLimit(file, maxSizeMB)) {
|
||||
alertOverLimit(maxSizeMB);
|
||||
return;
|
||||
}
|
||||
|
||||
attachFile({ file });
|
||||
};
|
||||
|
||||
const onFileUpload = file => {
|
||||
@@ -85,7 +97,5 @@ export const useFileUpload = ({ isATwilioSMSChannel, attachFile }) => {
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
onFileUpload,
|
||||
};
|
||||
return { onFileUpload };
|
||||
};
|
||||
|
||||
@@ -29,21 +29,24 @@ export const INBOX_FEATURE_MAP = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Composable for handling macro-related functionality
|
||||
* @returns {Object} An object containing the getMacroDropdownValues function
|
||||
* Composable for handling inbox-related functionality
|
||||
* @param {string|null} inboxId - Optional inbox ID. If not provided, uses current chat's inbox
|
||||
* @returns {Object} An object containing inbox type checking functions
|
||||
*/
|
||||
export const useInbox = () => {
|
||||
export const useInbox = (inboxId = null) => {
|
||||
const currentChat = useMapGetter('getSelectedChat');
|
||||
const inboxGetter = useMapGetter('inboxes/getInboxById');
|
||||
|
||||
const inbox = computed(() => {
|
||||
const inboxId = currentChat.value.inbox_id;
|
||||
const targetInboxId = inboxId || currentChat.value?.inbox_id;
|
||||
|
||||
return useCamelCase(inboxGetter.value(inboxId), { deep: true });
|
||||
if (!targetInboxId) return null;
|
||||
|
||||
return useCamelCase(inboxGetter.value(targetInboxId), { deep: true });
|
||||
});
|
||||
|
||||
const channelType = computed(() => {
|
||||
return inbox.value.channelType;
|
||||
return inbox.value?.channelType;
|
||||
});
|
||||
|
||||
const isAPIInbox = computed(() => {
|
||||
@@ -75,19 +78,19 @@ export const useInbox = () => {
|
||||
});
|
||||
|
||||
const whatsAppAPIProvider = computed(() => {
|
||||
return inbox.value.provider || '';
|
||||
return inbox.value?.provider || '';
|
||||
});
|
||||
|
||||
const isAMicrosoftInbox = computed(() => {
|
||||
return isAnEmailChannel.value && inbox.value.provider === 'microsoft';
|
||||
return isAnEmailChannel.value && inbox.value?.provider === 'microsoft';
|
||||
});
|
||||
|
||||
const isAGoogleInbox = computed(() => {
|
||||
return isAnEmailChannel.value && inbox.value.provider === 'google';
|
||||
return isAnEmailChannel.value && inbox.value?.provider === 'google';
|
||||
});
|
||||
|
||||
const isATwilioSMSChannel = computed(() => {
|
||||
const { medium: medium = '' } = inbox.value;
|
||||
const { medium: medium = '' } = inbox.value || {};
|
||||
return isATwilioChannel.value && medium === 'sms';
|
||||
});
|
||||
|
||||
@@ -96,7 +99,7 @@ export const useInbox = () => {
|
||||
});
|
||||
|
||||
const isATwilioWhatsAppChannel = computed(() => {
|
||||
const { medium: medium = '' } = inbox.value;
|
||||
const { medium: medium = '' } = inbox.value || {};
|
||||
return isATwilioChannel.value && medium === 'whatsapp';
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user