Merge branch 'develop' into chore-replace-inbox-mixin
This commit is contained in:
@@ -141,7 +141,7 @@ export default {
|
||||
allowOnFocusedInput: true,
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents, conversationListRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
|
||||
@@ -13,13 +13,12 @@ import wootConstants from 'dashboard/constants/globals';
|
||||
import {
|
||||
CMD_REOPEN_CONVERSATION,
|
||||
CMD_RESOLVE_CONVERSATION,
|
||||
} from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
} from 'dashboard/helper/commandbar/events';
|
||||
|
||||
const store = useStore();
|
||||
const getters = useStoreGetters();
|
||||
const { t } = useI18n();
|
||||
|
||||
const resolveActionsRef = ref(null);
|
||||
const arrowDownButtonRef = ref(null);
|
||||
const isLoading = ref(false);
|
||||
|
||||
@@ -131,17 +130,14 @@ const keyboardEvents = {
|
||||
},
|
||||
};
|
||||
|
||||
useKeyboardEvents(keyboardEvents, resolveActionsRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
useEmitter(CMD_REOPEN_CONVERSATION, onCmdOpenConversation);
|
||||
useEmitter(CMD_RESOLVE_CONVERSATION, onCmdResolveConversation);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="resolveActionsRef"
|
||||
class="relative flex items-center justify-end resolve-actions"
|
||||
>
|
||||
<div class="relative flex items-center justify-end resolve-actions">
|
||||
<div class="button-group">
|
||||
<woot-button
|
||||
v-if="isOpen"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { getSidebarItems } from './config/default-sidebar';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
@@ -8,7 +7,10 @@ import { useRoute, useRouter } from 'dashboard/composables/route';
|
||||
import PrimarySidebar from './sidebarComponents/Primary.vue';
|
||||
import SecondarySidebar from './sidebarComponents/Secondary.vue';
|
||||
import { routesWithPermissions } from '../../routes';
|
||||
import { hasPermissions } from '../../helper/permissionsHelper';
|
||||
import {
|
||||
getUserPermissions,
|
||||
hasPermissions,
|
||||
} from '../../helper/permissionsHelper';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -26,7 +28,6 @@ export default {
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const sidebarRef = ref(null);
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -64,11 +65,10 @@ export default {
|
||||
action: () => navigateToRoute('agent_list'),
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents, sidebarRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
return {
|
||||
toggleKeyShortcutModal,
|
||||
sidebarRef,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
@@ -113,7 +113,10 @@ export default {
|
||||
return getSidebarItems(this.accountId);
|
||||
},
|
||||
primaryMenuItems() {
|
||||
const userPermissions = this.currentUser.permissions;
|
||||
const userPermissions = getUserPermissions(
|
||||
this.currentUser,
|
||||
this.accountId
|
||||
);
|
||||
const menuItems = this.sideMenuConfig.primaryMenu;
|
||||
return menuItems.filter(menuItem => {
|
||||
const isAvailableForTheUser = hasPermissions(
|
||||
@@ -195,7 +198,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside ref="sidebarRef" class="flex h-full">
|
||||
<aside class="flex h-full">
|
||||
<PrimarySidebar
|
||||
:logo-source="globalConfig.logoThumbnail"
|
||||
:installation-name="globalConfig.installationName"
|
||||
|
||||
@@ -4,7 +4,10 @@ import SecondaryNavItem from './SecondaryNavItem.vue';
|
||||
import AccountContext from './AccountContext.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { FEATURE_FLAGS } from '../../../featureFlags';
|
||||
import { hasPermissions } from '../../../helper/permissionsHelper';
|
||||
import {
|
||||
getUserPermissions,
|
||||
hasPermissions,
|
||||
} from '../../../helper/permissionsHelper';
|
||||
import { routesWithPermissions } from '../../../routes';
|
||||
|
||||
export default {
|
||||
@@ -59,7 +62,10 @@ export default {
|
||||
accessibleMenuItems() {
|
||||
const menuItemsFilteredByPermissions = this.menuConfig.menuItems.filter(
|
||||
menuItem => {
|
||||
const { permissions: userPermissions = [] } = this.currentUser;
|
||||
const userPermissions = getUserPermissions(
|
||||
this.currentUser,
|
||||
this.accountId
|
||||
);
|
||||
return hasPermissions(
|
||||
routesWithPermissions[menuItem.toStateName],
|
||||
userPermissions
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<script setup>
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
import { computed } from 'vue';
|
||||
import { hasPermissions } from '../helper/permissionsHelper';
|
||||
import {
|
||||
getUserPermissions,
|
||||
hasPermissions,
|
||||
} from '../helper/permissionsHelper';
|
||||
|
||||
const props = defineProps({
|
||||
permissions: {
|
||||
type: Array,
|
||||
@@ -10,12 +14,17 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const getters = useStoreGetters();
|
||||
const user = getters.getCurrentUser.value;
|
||||
const hasPermission = computed(() =>
|
||||
hasPermissions(props.permissions, user.permissions)
|
||||
);
|
||||
const user = computed(() => getters.getCurrentUser.value);
|
||||
const accountId = computed(() => getters.getCurrentAccountId.value);
|
||||
const userPermissions = computed(() => {
|
||||
return getUserPermissions(user.value, accountId.value);
|
||||
});
|
||||
const hasPermission = computed(() => {
|
||||
return hasPermissions(props.permissions, userPermissions.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- eslint-disable vue/no-root-v-if -->
|
||||
<template>
|
||||
<div v-if="hasPermission">
|
||||
<slot />
|
||||
|
||||
@@ -4,10 +4,10 @@ import { mapGetters } from 'vuex';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
import { useAI } from 'dashboard/composables/useAI';
|
||||
import AICTAModal from './AICTAModal.vue';
|
||||
import AIAssistanceModal from './AIAssistanceModal.vue';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
import { CMD_AI_ASSIST } from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
import { CMD_AI_ASSIST } from 'dashboard/helper/commandbar/events';
|
||||
import AIAssistanceCTAButton from './AIAssistanceCTAButton.vue';
|
||||
|
||||
export default {
|
||||
@@ -16,17 +16,17 @@ export default {
|
||||
AICTAModal,
|
||||
AIAssistanceCTAButton,
|
||||
},
|
||||
mixins: [aiMixin],
|
||||
setup(props, { emit }) {
|
||||
const { uiSettings, updateUISettings } = useUISettings();
|
||||
|
||||
const { isAIIntegrationEnabled, draftMessage, recordAnalytics } = useAI();
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
|
||||
const aiAssistanceButtonRef = ref(null);
|
||||
const initialMessage = ref('');
|
||||
|
||||
const initializeMessage = draftMessage => {
|
||||
initialMessage.value = draftMessage;
|
||||
const initializeMessage = draftMsg => {
|
||||
initialMessage.value = draftMsg;
|
||||
};
|
||||
const keyboardEvents = {
|
||||
'$mod+KeyZ': {
|
||||
@@ -39,15 +39,17 @@ export default {
|
||||
allowOnFocusedInput: true,
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents, aiAssistanceButtonRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
updateUISettings,
|
||||
isAdmin,
|
||||
aiAssistanceButtonRef,
|
||||
initialMessage,
|
||||
initializeMessage,
|
||||
recordAnalytics,
|
||||
isAIIntegrationEnabled,
|
||||
draftMessage,
|
||||
};
|
||||
},
|
||||
data: () => ({
|
||||
@@ -118,7 +120,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="aiAssistanceButtonRef">
|
||||
<div>
|
||||
<div v-if="isAIIntegrationEnabled" class="relative">
|
||||
<AIAssistanceCTAButton
|
||||
v-if="shouldShowAIAssistCTAButton"
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
<script>
|
||||
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
|
||||
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
|
||||
import { useAI } from 'dashboard/composables/useAI';
|
||||
import AILoader from './AILoader.vue';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AILoader,
|
||||
},
|
||||
mixins: [aiMixin, messageFormatterMixin],
|
||||
props: {
|
||||
aiOption: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
setup() {
|
||||
const { formatMessage } = useMessageFormatter();
|
||||
const { draftMessage, processEvent, recordAnalytics } = useAI();
|
||||
return { draftMessage, processEvent, recordAnalytics, formatMessage };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
generatedContent: '',
|
||||
|
||||
@@ -3,16 +3,16 @@ import { useVuelidate } from '@vuelidate/core';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
import { useAI } from 'dashboard/composables/useAI';
|
||||
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
mixins: [aiMixin],
|
||||
setup() {
|
||||
const { updateUISettings } = useUISettings();
|
||||
const { recordAnalytics } = useAI();
|
||||
const v$ = useVuelidate();
|
||||
|
||||
return { updateUISettings, v$ };
|
||||
return { updateUISettings, v$, recordAnalytics };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
|
||||
@@ -16,8 +16,6 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['chatTabChange']);
|
||||
|
||||
const chatTypeTabsRef = ref(null);
|
||||
|
||||
const activeTabIndex = computed(() => {
|
||||
return props.items.findIndex(item => item.key === props.activeTab);
|
||||
});
|
||||
@@ -39,24 +37,23 @@ const keyboardEvents = {
|
||||
},
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents, chatTypeTabsRef);
|
||||
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="chatTypeTabsRef">
|
||||
<woot-tabs
|
||||
:index="activeTabIndex"
|
||||
class="tab--chat-type py-0 px-4 w-full"
|
||||
@change="onTabChange"
|
||||
>
|
||||
<woot-tabs-item
|
||||
v-for="item in items"
|
||||
:key="item.key"
|
||||
:name="item.name"
|
||||
:count="item.count"
|
||||
/>
|
||||
</woot-tabs>
|
||||
</div>
|
||||
<woot-tabs
|
||||
:index="activeTabIndex"
|
||||
class="w-full px-4 py-0 tab--chat-type"
|
||||
@change="onTabChange"
|
||||
>
|
||||
<woot-tabs-item
|
||||
v-for="item in items"
|
||||
:key="item.key"
|
||||
:name="item.name"
|
||||
:count="item.count"
|
||||
/>
|
||||
</woot-tabs>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -18,8 +18,6 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['add', 'remove']);
|
||||
|
||||
const labelSelectorWrapRef = ref(null);
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
|
||||
const showSearchDropdownLabel = ref(false);
|
||||
@@ -57,15 +55,11 @@ const keyboardEvents = {
|
||||
},
|
||||
};
|
||||
|
||||
useKeyboardEvents(keyboardEvents, labelSelectorWrapRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="labelSelectorWrapRef"
|
||||
v-on-clickaway="closeDropdownLabel"
|
||||
class="relative leading-6"
|
||||
>
|
||||
<div v-on-clickaway="closeDropdownLabel" class="relative leading-6">
|
||||
<AddLabel @add="toggleLabels" />
|
||||
<woot-label
|
||||
v-for="label in savedLabels"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script>
|
||||
import { ref, watchEffect, computed } from 'vue';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
import FileUpload from 'vue-upload-component';
|
||||
@@ -124,15 +123,13 @@ export default {
|
||||
const { setSignatureFlagForInbox, fetchSignatureFlagFromUISettings } =
|
||||
useUISettings();
|
||||
|
||||
const uploadRef = ref(null);
|
||||
// TODO: This is really hacky, we need to replace the file picker component with
|
||||
// a custom one, where the logic and the component markup is isolated.
|
||||
// Once we have the custom component, we can remove the hacky logic below.
|
||||
const uploadRefElem = computed(() => uploadRef.value?.$el);
|
||||
|
||||
const keyboardEvents = {
|
||||
'Alt+KeyA': {
|
||||
action: () => {
|
||||
// TODO: This is really hacky, we need to replace the file picker component with
|
||||
// a custom one, where the logic and the component markup is isolated.
|
||||
// Once we have the custom component, we can remove the hacky logic below.
|
||||
|
||||
const uploadTriggerButton = document.querySelector(
|
||||
'#conversationAttachment'
|
||||
);
|
||||
@@ -142,14 +139,11 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
useKeyboardEvents(keyboardEvents, uploadRefElem);
|
||||
});
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
return {
|
||||
setSignatureFlagForInbox,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
uploadRef,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -273,7 +267,6 @@ export default {
|
||||
@click="toggleEmojiPicker"
|
||||
/>
|
||||
<FileUpload
|
||||
ref="uploadRef"
|
||||
v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_ATTACH_ICON')"
|
||||
input-id="conversationAttachment"
|
||||
:size="4096 * 4096"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
import { REPLY_EDITOR_MODES, CHAR_LENGTH_WARNING } from './constants';
|
||||
export default {
|
||||
@@ -23,8 +22,6 @@ export default {
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const replyTopRef = ref(null);
|
||||
|
||||
const setReplyMode = mode => {
|
||||
emit('setReplyMode', mode);
|
||||
};
|
||||
@@ -44,12 +41,11 @@ export default {
|
||||
allowOnFocusedInput: true,
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents, replyTopRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
return {
|
||||
handleReplyClick,
|
||||
handleNoteClick,
|
||||
replyTopRef,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -76,10 +72,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="replyTopRef"
|
||||
class="flex justify-between bg-black-50 dark:bg-slate-800"
|
||||
>
|
||||
<div class="flex justify-between bg-black-50 dark:bg-slate-800">
|
||||
<div class="button-group">
|
||||
<woot-button
|
||||
variant="clear"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
|
||||
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
|
||||
import BubbleActions from './bubble/Actions.vue';
|
||||
import BubbleContact from './bubble/Contact.vue';
|
||||
import BubbleFile from './bubble/File.vue';
|
||||
@@ -39,7 +39,6 @@ export default {
|
||||
InstagramStoryReply,
|
||||
Spinner,
|
||||
},
|
||||
mixins: [messageFormatterMixin],
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
@@ -74,6 +73,12 @@ export default {
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { formatMessage } = useMessageFormatter();
|
||||
return {
|
||||
formatMessage,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContextMenu: false,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script>
|
||||
import { MESSAGE_TYPE } from 'widget/helpers/constants';
|
||||
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
|
||||
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
|
||||
import { ATTACHMENT_ICONS } from 'shared/constants/messages';
|
||||
|
||||
export default {
|
||||
name: 'MessagePreview',
|
||||
mixins: [messageFormatterMixin],
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
@@ -20,6 +19,12 @@ export default {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { getPlainText } = useMessageFormatter();
|
||||
return {
|
||||
getPlainText,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
messageByAgent() {
|
||||
const { message_type: messageType } = this.message;
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
CMD_MUTE_CONVERSATION,
|
||||
CMD_SEND_TRANSCRIPT,
|
||||
CMD_UNMUTE_CONVERSATION,
|
||||
} from '../../../routes/dashboard/commands/commandBarBusEvents';
|
||||
} from 'dashboard/helper/commandbar/events';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
@@ -40,7 +40,6 @@ const onSelect = () => {
|
||||
};
|
||||
|
||||
useKeyboardNavigableList({
|
||||
elementRef: tagAgentsRef,
|
||||
items,
|
||||
onSelect,
|
||||
adjustScroll,
|
||||
|
||||
@@ -35,7 +35,6 @@ const ALLOWED_FILE_TYPES = {
|
||||
const MAX_ZOOM_LEVEL = 2;
|
||||
const MIN_ZOOM_LEVEL = 1;
|
||||
|
||||
const galleryViewRef = ref(null);
|
||||
const zoomScale = ref(1);
|
||||
const activeAttachment = ref({});
|
||||
const activeFileType = ref('');
|
||||
@@ -202,7 +201,7 @@ const keyboardEvents = {
|
||||
},
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents, galleryViewRef);
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
|
||||
onMounted(() => {
|
||||
setImageAndVideoSrc(props.attachment);
|
||||
@@ -218,7 +217,6 @@ onMounted(() => {
|
||||
:on-close="onClose"
|
||||
>
|
||||
<div
|
||||
ref="galleryViewRef"
|
||||
v-on-clickaway="onClose"
|
||||
class="bg-white dark:bg-slate-900 flex flex-col h-[inherit] w-[inherit] overflow-hidden"
|
||||
@click="onClose"
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import {
|
||||
getSortedAgentsByAvailability,
|
||||
getAgentsByUpdatedPresence,
|
||||
} from 'dashboard/helper/agentHelper.js';
|
||||
import MenuItem from './menuItem.vue';
|
||||
import MenuItemWithSubmenu from './menuItemWithSubmenu.vue';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import agentMixin from 'dashboard/mixins/agentMixin';
|
||||
import { mapGetters } from 'vuex';
|
||||
import AgentLoadingPlaceholder from './agentLoadingPlaceholder.vue';
|
||||
export default {
|
||||
components: {
|
||||
@@ -11,7 +14,6 @@ export default {
|
||||
MenuItemWithSubmenu,
|
||||
AgentLoadingPlaceholder,
|
||||
},
|
||||
mixins: [agentMixin],
|
||||
props: {
|
||||
chatId: {
|
||||
type: Number,
|
||||
@@ -112,13 +114,19 @@ export default {
|
||||
labels: 'labels/getLabels',
|
||||
teams: 'teams/getTeams',
|
||||
assignableAgentsUiFlags: 'inboxAssignableAgents/getUIFlags',
|
||||
currentUser: 'getCurrentUser',
|
||||
currentAccountId: 'getCurrentAccountId',
|
||||
}),
|
||||
filteredAgentOnAvailability() {
|
||||
const agents = this.$store.getters[
|
||||
'inboxAssignableAgents/getAssignableAgents'
|
||||
](this.inboxId);
|
||||
const agentsByUpdatedPresence = this.getAgentsByUpdatedPresence(agents);
|
||||
const filteredAgents = this.sortedAgentsByAvailability(
|
||||
const agentsByUpdatedPresence = getAgentsByUpdatedPresence(
|
||||
agents,
|
||||
this.currentUser,
|
||||
this.currentAccountId
|
||||
);
|
||||
const filteredAgents = getSortedAgentsByAvailability(
|
||||
agentsByUpdatedPresence
|
||||
);
|
||||
return filteredAgents;
|
||||
|
||||
+13
-3
@@ -2,7 +2,9 @@
|
||||
// components
|
||||
import WootButton from '../../../ui/WootButton.vue';
|
||||
import Avatar from '../../Avatar.vue';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
|
||||
// composables
|
||||
import { useAI } from 'dashboard/composables/useAI';
|
||||
|
||||
// store & api
|
||||
import { mapGetters } from 'vuex';
|
||||
@@ -18,7 +20,6 @@ export default {
|
||||
Avatar,
|
||||
WootButton,
|
||||
},
|
||||
mixins: [aiMixin],
|
||||
props: {
|
||||
suggestedLabels: {
|
||||
type: Array,
|
||||
@@ -30,6 +31,11 @@ export default {
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { isAIIntegrationEnabled } = useAI();
|
||||
|
||||
return { isAIIntegrationEnabled };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isDismissed: false,
|
||||
@@ -41,7 +47,11 @@ export default {
|
||||
...mapGetters({
|
||||
allLabels: 'labels/getLabels',
|
||||
currentAccountId: 'getCurrentAccountId',
|
||||
currentChat: 'getSelectedChat',
|
||||
}),
|
||||
conversationId() {
|
||||
return this.currentChat?.id;
|
||||
},
|
||||
labelTooltip() {
|
||||
if (this.preparedLabels.length > 1) {
|
||||
return this.$t('LABEL_MGMT.SUGGESTIONS.TOOLTIP.MULTIPLE_SUGGESTION');
|
||||
@@ -162,7 +172,7 @@ export default {
|
||||
delay: { show: 600, hide: 0 },
|
||||
hideOnClick: true,
|
||||
}"
|
||||
class="label-suggestion--option"
|
||||
class="label-suggestion--option !px-0"
|
||||
@click="pushOrAddLabel(label.title)"
|
||||
>
|
||||
<woot-label
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import {
|
||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
||||
CMD_BULK_ACTION_REOPEN_CONVERSATION,
|
||||
CMD_BULK_ACTION_RESOLVE_CONVERSATION,
|
||||
} from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
} from 'dashboard/helper/commandbar/events';
|
||||
|
||||
import AgentSelector from './AgentSelector.vue';
|
||||
import UpdateActions from './UpdateActions.vue';
|
||||
|
||||
@@ -48,11 +48,7 @@ const loadLinkedIssue = async () => {
|
||||
const issues = response.data;
|
||||
linkedIssue.value = issues && issues.length ? issues[0] : null;
|
||||
} catch (error) {
|
||||
const errorMessage = parseLinearAPIErrorResponse(
|
||||
error,
|
||||
t('INTEGRATION_SETTINGS.LINEAR.LOADING_ERROR')
|
||||
);
|
||||
useAlert(errorMessage);
|
||||
// We don't want to show an error message here, as it's not critical. When someone clicks on the Linear icon, we can inform them that the integration is disabled.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ const onSelect = () => {
|
||||
};
|
||||
|
||||
useKeyboardNavigableList({
|
||||
elementRef: mentionsListContainerRef,
|
||||
items: computed(() => props.items),
|
||||
onSelect,
|
||||
adjustScroll,
|
||||
|
||||
Reference in New Issue
Block a user