diff --git a/app/javascript/dashboard/composables/useChatwootConfig.js b/app/javascript/dashboard/composables/useChatwootConfig.js new file mode 100644 index 000000000..98490e46d --- /dev/null +++ b/app/javascript/dashboard/composables/useChatwootConfig.js @@ -0,0 +1,31 @@ +import { computed } from 'vue'; + +/** + * Composable for accessing Chatwoot configuration values. + * @returns {Object} An object containing computed properties for various Chatwoot configuration values. + */ +export function useChatwootConfig() { + const hostURL = computed(() => window.chatwootConfig.hostURL); + + const vapidPublicKey = computed(() => window.chatwootConfig.vapidPublicKey); + + const enabledLanguages = computed( + () => window.chatwootConfig.enabledLanguages + ); + + const isEnterprise = computed( + () => window.chatwootConfig.isEnterprise === 'true' + ); + + const enterprisePlanName = computed( + () => window.chatwootConfig?.enterprisePlanName + ); + + return { + hostURL, + vapidPublicKey, + enabledLanguages, + isEnterprise, + enterprisePlanName, + }; +} diff --git a/app/javascript/dashboard/composables/useConfig.js b/app/javascript/dashboard/composables/useConfig.js new file mode 100644 index 000000000..46dc301fb --- /dev/null +++ b/app/javascript/dashboard/composables/useConfig.js @@ -0,0 +1,52 @@ +// export default { +// computed: { +// hostURL() { +// return window.chatwootConfig.hostURL; +// }, +// vapidPublicKey() { +// return window.chatwootConfig.vapidPublicKey; +// }, +// enabledLanguages() { +// return window.chatwootConfig.enabledLanguages; +// }, +// isEnterprise() { +// return window.chatwootConfig.isEnterprise === 'true'; +// }, +// enterprisePlanName() { +// // returns "community" or "enterprise" +// return window.chatwootConfig?.enterprisePlanName; +// }, +// }, +// }; + +import { computed } from 'vue'; + +/** + * Composable for accessing Chatwoot configuration values. + * @returns {Object} An object containing computed properties for various Chatwoot configuration values. + */ +export function useConfig() { + const hostURL = computed(() => window.chatwootConfig.hostURL); + + const vapidPublicKey = computed(() => window.chatwootConfig.vapidPublicKey); + + const enabledLanguages = computed( + () => window.chatwootConfig.enabledLanguages + ); + + const isEnterprise = computed( + () => window.chatwootConfig.isEnterprise === 'true' + ); + + const enterprisePlanName = computed( + () => window.chatwootConfig?.enterprisePlanName + ); + + return { + hostURL, + vapidPublicKey, + enabledLanguages, + isEnterprise, + enterprisePlanName, + }; +} diff --git a/app/javascript/dashboard/composables/useFilter.js b/app/javascript/dashboard/composables/useFilter.js new file mode 100644 index 000000000..b5614782f --- /dev/null +++ b/app/javascript/dashboard/composables/useFilter.js @@ -0,0 +1,155 @@ +// File: app/javascript/dashboard/composables/useFilter.js +import { ref, computed } from 'vue'; +import { useStore } from 'vuex'; +import wootConstants from 'dashboard/constants/globals'; + +/** + * Composable for handling filter-related functionalities. + * @returns {Object} An object containing methods for filter management. + */ +export function useFilter( + attributeModel, + filtersFori18n, + filterAttributeGroups, + customAttributeInputType, + getOperatorTypes +) { + const store = useStore(); + const filterTypes = ref([]); + const filterGroups = ref([]); + const appliedFilter = ref([]); + const activeStatus = ref(''); + const activeAssigneeTab = ref(''); + const conversationInbox = ref(''); + const teamId = ref(''); + const label = ref(''); + const currentUserDetails = ref([]); + const inbox = ref({}); + const activeTeam = ref({}); + + const setFilterAttributes = () => { + const allCustomAttributes = store.getters[ + 'attributes/getAttributesByModel' + ](attributeModel.value); + const customAttributesFormatted = { + name: store.$t(`${filtersFori18n.value}.GROUPS.CUSTOM_ATTRIBUTES`), + attributes: allCustomAttributes.map(attr => ({ + key: attr.attribute_key, + name: store.$t(`${filtersFori18n.value}.ATTRIBUTES.${attr.i18nKey}`), + })), + }; + const allFilterGroups = filterAttributeGroups.value.map(group => ({ + name: store.$t(`${filtersFori18n.value}.GROUPS.${group.i18nGroup}`), + attributes: group.attributes.map(attribute => ({ + key: attribute.key, + name: store.$t( + `${filtersFori18n.value}.ATTRIBUTES.${attribute.i18nKey}` + ), + })), + })); + const customAttributeTypes = allCustomAttributes.map(attr => ({ + attributeKey: attr.attribute_key, + attributeI18nKey: `CUSTOM_ATTRIBUTE_${attr.attribute_display_type.toUpperCase()}`, + inputType: customAttributeInputType(attr.attribute_display_type), + filterOperators: getOperatorTypes(attr.attribute_display_type), + attributeModel: 'custom_attributes', + })); + filterTypes.value = [...filterTypes.value, ...customAttributeTypes]; + filterGroups.value = [...allFilterGroups, customAttributesFormatted]; + }; + + const initializeExistingFilterToModal = () => { + initializeStatusAndAssigneeFilterToModal(); + initializeInboxTeamAndLabelFilterToModal(); + }; + + const initializeStatusAndAssigneeFilterToModal = () => { + if (activeStatus.value !== '') { + appliedFilter.value.push({ + attribute_key: 'status', + attribute_model: 'standard', + filter_operator: 'equal_to', + values: [ + { + id: activeStatus.value, + name: store.$t( + `CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.${activeStatus.value}.TEXT` + ), + }, + ], + query_operator: 'and', + custom_attribute_type: '', + }); + } + if (activeAssigneeTab.value === wootConstants.ASSIGNEE_TYPE.ME) { + appliedFilter.value.push({ + attribute_key: 'assignee_id', + filter_operator: 'equal_to', + values: currentUserDetails.value, + query_operator: 'and', + custom_attribute_type: '', + }); + } + }; + + const initializeInboxTeamAndLabelFilterToModal = () => { + if (conversationInbox.value) { + appliedFilter.value.push({ + attribute_key: 'inbox_id', + attribute_model: 'standard', + filter_operator: 'equal_to', + values: [ + { + id: conversationInbox.value, + name: inbox.value.name, + }, + ], + query_operator: 'and', + custom_attribute_type: '', + }); + } + if (teamId.value) { + appliedFilter.value.push({ + attribute_key: 'team_id', + attribute_model: 'standard', + filter_operator: 'equal_to', + values: activeTeam.value, + query_operator: 'and', + custom_attribute_type: '', + }); + } + if (label.value) { + appliedFilter.value.push({ + attribute_key: 'labels', + attribute_model: 'standard', + filter_operator: 'equal_to', + values: [ + { + id: label.value, + name: label.value, + }, + ], + query_operator: 'and', + custom_attribute_type: '', + }); + } + }; + + return { + setFilterAttributes, + initializeExistingFilterToModal, + initializeStatusAndAssigneeFilterToModal, + initializeInboxTeamAndLabelFilterToModal, + filterTypes, + filterGroups, + appliedFilter, + activeStatus, + activeAssigneeTab, + conversationInbox, + teamId, + label, + currentUserDetails, + inbox, + activeTeam, + }; +} diff --git a/app/javascript/dashboard/composables/useReports.js b/app/javascript/dashboard/composables/useReports.js new file mode 100644 index 000000000..e69de29bb diff --git a/app/javascript/shared/mixins/useGlobalConfig.js b/app/javascript/shared/mixins/useGlobalConfig.js new file mode 100644 index 000000000..3f1db270f --- /dev/null +++ b/app/javascript/shared/mixins/useGlobalConfig.js @@ -0,0 +1,13 @@ +/** + * Composable for replacing 'Chatwoot' with a custom installation name in a string. + * @param {string} installationName - The custom installation name to replace 'Chatwoot' with. + * @returns {Function} A function that replaces 'Chatwoot' with the custom installation name in a given string. + */ +export function useInstallationName(installationName) { + return str => { + if (str && installationName) { + return str.replace(/Chatwoot/g, installationName); + } + return str; + }; +} diff --git a/app/javascript/shared/mixins/useInbox.js b/app/javascript/shared/mixins/useInbox.js new file mode 100644 index 000000000..fefc7deb7 --- /dev/null +++ b/app/javascript/shared/mixins/useInbox.js @@ -0,0 +1,164 @@ +import { computed } from 'vue'; + +export const INBOX_TYPES = { + WEB: 'Channel::WebWidget', + FB: 'Channel::FacebookPage', + TWITTER: 'Channel::TwitterProfile', + TWILIO: 'Channel::TwilioSms', + WHATSAPP: 'Channel::Whatsapp', + API: 'Channel::Api', + EMAIL: 'Channel::Email', + TELEGRAM: 'Channel::Telegram', + LINE: 'Channel::Line', + SMS: 'Channel::Sms', +}; + +export const INBOX_FEATURES = { + REPLY_TO: 'replyTo', + REPLY_TO_OUTGOING: 'replyToOutgoing', +}; + +export const INBOX_FEATURE_MAP = { + [INBOX_FEATURES.REPLY_TO]: [ + INBOX_TYPES.FB, + INBOX_TYPES.WEB, + INBOX_TYPES.TWITTER, + INBOX_TYPES.WHATSAPP, + INBOX_TYPES.TELEGRAM, + INBOX_TYPES.API, + ], + [INBOX_FEATURES.REPLY_TO_OUTGOING]: [ + INBOX_TYPES.WEB, + INBOX_TYPES.TWITTER, + INBOX_TYPES.WHATSAPP, + INBOX_TYPES.TELEGRAM, + INBOX_TYPES.API, + ], +}; + +/** + * Composable for handling inbox-related computations and methods. + * @param {Object} inbox - The inbox object to be processed. + * @param {Object} chat - The chat object associated with the inbox. + * @returns {Object} An object containing computed properties and methods for inbox management. + */ +export function useInbox(inbox, chat) { + const channelType = computed(() => inbox.channel_type); + const whatsAppAPIProvider = computed(() => inbox.provider || ''); + + const isAMicrosoftInbox = computed( + () => isAnEmailChannel.value && inbox.provider === 'microsoft' + ); + const isAGoogleInbox = computed( + () => isAnEmailChannel.value && inbox.provider === 'google' + ); + const isAPIInbox = computed(() => channelType.value === INBOX_TYPES.API); + const isATwitterInbox = computed( + () => channelType.value === INBOX_TYPES.TWITTER + ); + const isAFacebookInbox = computed(() => channelType.value === INBOX_TYPES.FB); + const isAWebWidgetInbox = computed( + () => channelType.value === INBOX_TYPES.WEB + ); + const isATwilioChannel = computed( + () => channelType.value === INBOX_TYPES.TWILIO + ); + const isALineChannel = computed(() => channelType.value === INBOX_TYPES.LINE); + const isAnEmailChannel = computed( + () => channelType.value === INBOX_TYPES.EMAIL + ); + const isATelegramChannel = computed( + () => channelType.value === INBOX_TYPES.TELEGRAM + ); + + const isATwilioSMSChannel = computed(() => { + const { medium = '' } = inbox; + return isATwilioChannel.value && medium === 'sms'; + }); + + const isASmsInbox = computed( + () => channelType.value === INBOX_TYPES.SMS || isATwilioSMSChannel.value + ); + + const isATwilioWhatsAppChannel = computed(() => { + const { medium = '' } = inbox; + return isATwilioChannel.value && medium === 'whatsapp'; + }); + + const isAWhatsAppCloudChannel = computed( + () => + channelType.value === INBOX_TYPES.WHATSAPP && + whatsAppAPIProvider.value === 'whatsapp_cloud' + ); + + const is360DialogWhatsAppChannel = computed( + () => + channelType.value === INBOX_TYPES.WHATSAPP && + whatsAppAPIProvider.value === 'default' + ); + + const chatAdditionalAttributes = computed(() => { + const { additional_attributes: additionalAttributes } = chat || {}; + return additionalAttributes || {}; + }); + + const isTwitterInboxTweet = computed( + () => chatAdditionalAttributes.value.type === 'tweet' + ); + + const twilioBadge = computed( + () => `${isATwilioSMSChannel.value ? 'sms' : 'whatsapp'}` + ); + const twitterBadge = computed( + () => `${isTwitterInboxTweet.value ? 'twitter-tweet' : 'twitter-dm'}` + ); + const facebookBadge = computed( + () => chatAdditionalAttributes.value.type || 'facebook' + ); + + const inboxBadge = computed(() => { + if (isATwitterInbox.value) return twitterBadge.value; + if (isAFacebookInbox.value) return facebookBadge.value; + if (isATwilioChannel.value) return twilioBadge.value; + if (isAWhatsAppChannel.value) return 'whatsapp'; + return channelType.value; + }); + + const isAWhatsAppChannel = computed( + () => + channelType.value === INBOX_TYPES.WHATSAPP || + isATwilioWhatsAppChannel.value + ); + + const inboxHasFeature = feature => { + return INBOX_FEATURE_MAP[feature]?.includes(channelType.value) ?? false; + }; + + return { + channelType, + whatsAppAPIProvider, + isAMicrosoftInbox, + isAGoogleInbox, + isAPIInbox, + isATwitterInbox, + isAFacebookInbox, + isAWebWidgetInbox, + isATwilioChannel, + isALineChannel, + isAnEmailChannel, + isATelegramChannel, + isATwilioSMSChannel, + isASmsInbox, + isATwilioWhatsAppChannel, + isAWhatsAppCloudChannel, + is360DialogWhatsAppChannel, + chatAdditionalAttributes, + isTwitterInboxTweet, + twilioBadge, + twitterBadge, + facebookBadge, + inboxBadge, + isAWhatsAppChannel, + inboxHasFeature, + }; +}