feat: Update UI for Copilot (#11561)

- Updated UI for copilot
This commit is contained in:
Pranav
2025-06-02 22:02:03 -05:00
committed by GitHub
parent a5fda8e118
commit bae958334d
28 changed files with 455 additions and 243 deletions

View File

@@ -1,16 +1,11 @@
<script setup>
import { ref, computed, onMounted, watchEffect } from 'vue';
import { ref, computed, onMounted } from 'vue';
import { useStore } from 'dashboard/composables/store';
import Copilot from 'dashboard/components-next/copilot/Copilot.vue';
import ConversationAPI from 'dashboard/api/inbox/conversation';
import { useMapGetter } from 'dashboard/composables/store';
import { useUISettings } from 'dashboard/composables/useUISettings';
const props = defineProps({
conversationId: {
type: [Number, String],
required: true,
},
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
defineProps({
conversationInboxType: {
type: String,
required: true,
@@ -20,12 +15,24 @@ const props = defineProps({
const store = useStore();
const currentUser = useMapGetter('getCurrentUser');
const assistants = useMapGetter('captainAssistants/getRecords');
const uiFlags = useMapGetter('captainAssistants/getUIFlags');
const inboxAssistant = useMapGetter('getCopilotAssistant');
const { uiSettings, updateUISettings } = useUISettings();
const currentChat = useMapGetter('getSelectedChat');
const selectedCopilotThreadId = ref(null);
const messages = computed(() =>
store.getters['copilotMessages/getMessagesByThreadId'](
selectedCopilotThreadId.value
)
);
const currentAccountId = useMapGetter('getCurrentAccountId');
const isFeatureEnabledonAccount = useMapGetter(
'accounts/isFeatureEnabledonAccount'
);
const messages = ref([]);
const isCaptainTyping = ref(false);
const selectedAssistantId = ref(null);
const { uiSettings, updateUISettings } = useUISettings();
const activeAssistant = computed(() => {
const preferredId = uiSettings.value.preferred_captain_assistant_id;
@@ -55,68 +62,57 @@ const setAssistant = async assistant => {
});
};
const shouldShowCopilotPanel = computed(() => {
const isCaptainEnabled = isFeatureEnabledonAccount.value(
currentAccountId.value,
FEATURE_FLAGS.CAPTAIN
);
const { is_copilot_panel_open: isCopilotPanelOpen } = uiSettings.value;
return isCaptainEnabled && isCopilotPanelOpen && !uiFlags.value.fetchingList;
});
const handleReset = () => {
messages.value = [];
selectedCopilotThreadId.value = null;
};
const sendMessage = async message => {
// Add user message
messages.value.push({
id: messages.value.length + 1,
role: 'user',
content: message,
});
isCaptainTyping.value = true;
try {
const { data } = await ConversationAPI.requestCopilot(
props.conversationId,
{
previous_history: messages.value
.map(m => ({
role: m.role,
content: m.content,
}))
.slice(0, -1),
message,
assistant_id: selectedAssistantId.value,
}
);
messages.value.push({
id: new Date().getTime(),
role: 'assistant',
content: data.message,
if (selectedCopilotThreadId.value) {
await store.dispatch('copilotMessages/create', {
assistant_id: activeAssistant.value.id,
conversation_id: currentChat.value?.id,
threadId: selectedCopilotThreadId.value,
message,
});
} catch (error) {
// eslint-disable-next-line
console.log(error);
} finally {
isCaptainTyping.value = false;
} else {
const response = await store.dispatch('copilotThreads/create', {
assistant_id: activeAssistant.value.id,
conversation_id: currentChat.value?.id,
message,
});
selectedCopilotThreadId.value = response.id;
}
};
onMounted(() => {
store.dispatch('captainAssistants/get');
});
watchEffect(() => {
if (props.conversationId) {
store.dispatch('getInboxCaptainAssistantById', props.conversationId);
selectedAssistantId.value = activeAssistant.value?.id;
}
});
</script>
<template>
<Copilot
:messages="messages"
:support-agent="currentUser"
:is-captain-typing="isCaptainTyping"
:conversation-inbox-type="conversationInboxType"
:assistants="assistants"
:active-assistant="activeAssistant"
@set-assistant="setAssistant"
@send-message="sendMessage"
@reset="handleReset"
/>
<div
v-if="shouldShowCopilotPanel"
class="ltr:border-l rtl:border-r border-n-weak h-full overflow-hidden z-10 w-[320px] min-w-[320px] 2xl:min-w-[360px] 2xl:w-[360px] flex flex-col bg-n-background"
>
<Copilot
:messages="messages"
:support-agent="currentUser"
:conversation-inbox-type="conversationInboxType"
:assistants="assistants"
:active-assistant="activeAssistant"
@set-assistant="setAssistant"
@send-message="sendMessage"
@reset="handleReset"
/>
</div>
<template v-else />
</template>

View File

@@ -1,43 +1,23 @@
<script setup>
import { computed } from 'vue';
import CopilotContainer from '../../copilot/CopilotContainer.vue';
import ContactPanel from 'dashboard/routes/dashboard/conversation/ContactPanel.vue';
import { useMapGetter } from 'dashboard/composables/store';
import { FEATURE_FLAGS } from '../../../featureFlags';
import { useUISettings } from 'dashboard/composables/useUISettings';
const props = defineProps({
defineProps({
currentChat: {
required: true,
type: Object,
},
});
const channelType = computed(() => props.currentChat?.meta?.channel || '');
const currentAccountId = useMapGetter('getCurrentAccountId');
const isFeatureEnabledonAccount = useMapGetter(
'accounts/isFeatureEnabledonAccount'
);
const showCopilotTab = computed(() =>
isFeatureEnabledonAccount.value(currentAccountId.value, FEATURE_FLAGS.CAPTAIN)
);
const { uiSettings } = useUISettings();
const activeTab = computed(() => {
const {
is_contact_sidebar_open: isContactSidebarOpen,
is_copilot_panel_open: isCopilotPanelOpen,
} = uiSettings.value;
const { is_contact_sidebar_open: isContactSidebarOpen } = uiSettings.value;
if (isContactSidebarOpen) {
return 0;
}
if (isCopilotPanelOpen) {
return 1;
}
return null;
});
</script>
@@ -52,13 +32,6 @@ const activeTab = computed(() => {
:conversation-id="currentChat.id"
:inbox-id="currentChat.inbox_id"
/>
<CopilotContainer
v-show="activeTab === 1 && showCopilotTab"
:key="currentChat.id"
:conversation-inbox-type="channelType"
:conversation-id="currentChat.id"
class="flex-1"
/>
</div>
</div>
</template>