chore: Improve captain layout (#12820)
This commit is contained in:
@@ -4,7 +4,6 @@ import { OnClickOutside } from '@vueuse/components';
|
|||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useMapGetter } from 'dashboard/composables/store.js';
|
import { useMapGetter } from 'dashboard/composables/store.js';
|
||||||
import { usePolicy } from 'dashboard/composables/usePolicy';
|
import { usePolicy } from 'dashboard/composables/usePolicy';
|
||||||
import Icon from 'dashboard/components-next/icon/Icon.vue';
|
|
||||||
import Button from 'dashboard/components-next/button/Button.vue';
|
import Button from 'dashboard/components-next/button/Button.vue';
|
||||||
import BackButton from 'dashboard/components/widgets/BackButton.vue';
|
import BackButton from 'dashboard/components/widgets/BackButton.vue';
|
||||||
import PaginationFooter from 'dashboard/components-next/pagination/PaginationFooter.vue';
|
import PaginationFooter from 'dashboard/components-next/pagination/PaginationFooter.vue';
|
||||||
@@ -117,58 +116,57 @@ const handleCreateAssistant = () => {
|
|||||||
<div
|
<div
|
||||||
class="flex items-start lg:items-center justify-between w-full py-6 lg:py-0 lg:h-20 gap-4 lg:gap-2 flex-col lg:flex-row"
|
class="flex items-start lg:items-center justify-between w-full py-6 lg:py-0 lg:h-20 gap-4 lg:gap-2 flex-col lg:flex-row"
|
||||||
>
|
>
|
||||||
<div class="flex gap-4 items-center">
|
<div class="flex gap-3 items-center">
|
||||||
<BackButton v-if="backUrl" :back-url="backUrl" />
|
<BackButton v-if="backUrl" :back-url="backUrl" />
|
||||||
<slot name="headerTitle">
|
<div v-if="showAssistantSwitcher" class="flex items-center gap-2">
|
||||||
<div v-if="showAssistantSwitcher" class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="flex items-center gap-1">
|
<span
|
||||||
<span
|
v-if="activeAssistantName"
|
||||||
v-if="activeAssistantName"
|
class="text-xl font-medium truncate text-n-slate-12"
|
||||||
class="text-xl font-medium truncate text-n-slate-12"
|
>
|
||||||
|
{{ activeAssistantName }}
|
||||||
|
</span>
|
||||||
|
<div v-if="activeAssistantName" class="relative group">
|
||||||
|
<OnClickOutside
|
||||||
|
@trigger="showAssistantSwitcherDropdown = false"
|
||||||
>
|
>
|
||||||
{{ activeAssistantName }}
|
<Button
|
||||||
</span>
|
icon="i-lucide-chevron-down"
|
||||||
<div v-if="activeAssistantName" class="relative group">
|
variant="ghost"
|
||||||
<OnClickOutside
|
color="slate"
|
||||||
@trigger="showAssistantSwitcherDropdown = false"
|
size="xs"
|
||||||
>
|
class="rounded-md group-hover:bg-n-slate-3 hover:bg-n-slate-3 [&>span]:size-4"
|
||||||
<Button
|
@click="toggleAssistantSwitcher"
|
||||||
icon="i-lucide-chevron-down"
|
/>
|
||||||
variant="ghost"
|
|
||||||
color="slate"
|
|
||||||
size="xs"
|
|
||||||
class="rounded-md group-hover:bg-n-slate-3 hover:bg-n-slate-3 [&>span]:size-4"
|
|
||||||
@click="toggleAssistantSwitcher"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AssistantSwitcher
|
<AssistantSwitcher
|
||||||
v-if="showAssistantSwitcherDropdown"
|
v-if="showAssistantSwitcherDropdown"
|
||||||
class="absolute ltr:left-0 rtl:right-0 top-9"
|
class="absolute ltr:left-0 rtl:right-0 top-9"
|
||||||
@close="showAssistantSwitcherDropdown = false"
|
@close="showAssistantSwitcherDropdown = false"
|
||||||
@create-assistant="handleCreateAssistant"
|
@create-assistant="handleCreateAssistant"
|
||||||
/>
|
/>
|
||||||
</OnClickOutside>
|
</OnClickOutside>
|
||||||
</div>
|
|
||||||
<Icon
|
|
||||||
v-if="activeAssistantName"
|
|
||||||
icon="i-lucide-chevron-right"
|
|
||||||
class="size-6 text-n-slate-11"
|
|
||||||
/>
|
|
||||||
<span class="text-xl font-medium text-n-slate-11">
|
|
||||||
{{ headerTitle }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span v-else class="text-xl font-medium text-n-slate-12">
|
</div>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div
|
||||||
|
v-if="showAssistantSwitcher && headerTitle"
|
||||||
|
class="w-0.5 h-4 rounded-2xl bg-n-weak"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="headerTitle"
|
||||||
|
class="text-xl font-medium text-n-slate-12"
|
||||||
|
>
|
||||||
{{ headerTitle }}
|
{{ headerTitle }}
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
<div
|
||||||
<div
|
v-if="!isEmpty && showKnowMore"
|
||||||
v-if="!isEmpty && showKnowMore"
|
class="flex items-center gap-2"
|
||||||
class="flex items-center gap-2"
|
>
|
||||||
>
|
<div class="w-0.5 h-4 rounded-2xl bg-n-weak" />
|
||||||
<div class="w-0.5 h-4 rounded-2xl bg-n-weak" />
|
<slot name="knowMore" />
|
||||||
<slot name="knowMore" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ const sendMessage = async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col h-full rounded-lg p-4 border border-n-slate-4 text-n-slate-11"
|
class="flex flex-col h-full rounded-xl border py-6 border-n-weak text-n-slate-11"
|
||||||
>
|
>
|
||||||
<div class="mb-4">
|
<div class="mb-8 px-6">
|
||||||
<div class="flex justify-between items-center mb-1">
|
<div class="flex justify-between items-center mb-1">
|
||||||
<h3 class="text-lg font-medium">
|
<h3 class="text-lg font-medium">
|
||||||
{{ t('CAPTAIN.PLAYGROUND.HEADER') }}
|
{{ t('CAPTAIN.PLAYGROUND.HEADER') }}
|
||||||
@@ -85,6 +85,7 @@ const sendMessage = async () => {
|
|||||||
<NextButton
|
<NextButton
|
||||||
ghost
|
ghost
|
||||||
sm
|
sm
|
||||||
|
slate
|
||||||
icon="i-lucide-rotate-ccw"
|
icon="i-lucide-rotate-ccw"
|
||||||
@click="resetConversation"
|
@click="resetConversation"
|
||||||
/>
|
/>
|
||||||
@@ -97,11 +98,11 @@ const sendMessage = async () => {
|
|||||||
<MessageList :messages="messages" :is-loading="isLoading" />
|
<MessageList :messages="messages" :is-loading="isLoading" />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="flex items-center bg-n-solid-1 outline outline-n-container rounded-lg p-3"
|
class="flex items-center mx-6 bg-n-background outline outline-1 outline-n-weak rounded-xl p-3"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="newMessage"
|
v-model="newMessage"
|
||||||
class="flex-1 bg-transparent border-none focus:outline-none text-sm mb-0"
|
class="flex-1 bg-transparent border-none focus:outline-none text-sm mb-0 text-n-slate-12 placeholder:text-n-slate-10"
|
||||||
:placeholder="t('CAPTAIN.PLAYGROUND.MESSAGE_PLACEHOLDER')"
|
:placeholder="t('CAPTAIN.PLAYGROUND.MESSAGE_PLACEHOLDER')"
|
||||||
@keyup.enter="sendMessage"
|
@keyup.enter="sendMessage"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ const getAvatarName = sender =>
|
|||||||
|
|
||||||
const getMessageStyle = sender =>
|
const getMessageStyle = sender =>
|
||||||
isUserMessage(sender)
|
isUserMessage(sender)
|
||||||
? 'bg-n-strong text-n-white'
|
? 'bg-n-solid-blue text-n-slate-12 rounded-br-sm rounded-bl-xl rounded-t-xl'
|
||||||
: 'bg-n-solid-iris text-n-slate-12';
|
: 'bg-n-solid-iris text-n-slate-12 rounded-bl-sm rounded-br-xl rounded-t-xl';
|
||||||
|
|
||||||
const scrollToBottom = async () => {
|
const scrollToBottom = async () => {
|
||||||
await nextTick();
|
await nextTick();
|
||||||
@@ -49,7 +49,10 @@ watch(() => props.messages.length, scrollToBottom);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="messageContainer" class="flex-1 overflow-y-auto mb-4 space-y-2">
|
<div
|
||||||
|
ref="messageContainer"
|
||||||
|
class="flex-1 overflow-y-auto mb-4 px-6 space-y-6"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(message, index) in messages"
|
v-for="(message, index) in messages"
|
||||||
:key="index"
|
:key="index"
|
||||||
@@ -57,15 +60,20 @@ watch(() => props.messages.length, scrollToBottom);
|
|||||||
:class="getMessageAlignment(message.sender)"
|
:class="getMessageAlignment(message.sender)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex items-start gap-1.5"
|
class="flex items-end gap-1.5 max-w-[90%] md:max-w-[60%]"
|
||||||
:class="getMessageDirection(message.sender)"
|
:class="getMessageDirection(message.sender)"
|
||||||
>
|
>
|
||||||
<Avatar :name="getAvatarName(message.sender)" rounded-full :size="24" />
|
<Avatar
|
||||||
|
:name="getAvatarName(message.sender)"
|
||||||
|
rounded-full
|
||||||
|
:size="24"
|
||||||
|
class="shrink-0"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
class="max-w-[80%] rounded-lg p-3 text-sm"
|
class="px-4 py-3 text-sm [overflow-wrap:break-word]"
|
||||||
:class="getMessageStyle(message.sender)"
|
:class="getMessageStyle(message.sender)"
|
||||||
>
|
>
|
||||||
<div class="break-words" v-html="formatMessage(message.content)" />
|
<div v-html="formatMessage(message.content)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ const assistantId = computed(() => Number(route.params.assistantId));
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageLayout
|
<PageLayout
|
||||||
:header-title="$t('CAPTAIN.PLAYGROUND.HEADER')"
|
|
||||||
show-assistant-switcher
|
show-assistant-switcher
|
||||||
:show-pagination-footer="false"
|
:show-pagination-footer="false"
|
||||||
|
:show-know-more="false"
|
||||||
class="h-full"
|
class="h-full"
|
||||||
>
|
>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="flex flex-col h-full">
|
<div class="flex flex-col h-full">
|
||||||
<AssistantPlayground :assistant-id="assistantId" />
|
<AssistantPlayground :assistant-id="assistantId" class="bg-n-solid-1" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ const handleDeleteSuccess = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageLayout
|
<PageLayout
|
||||||
:header-title="$t('CAPTAIN.ASSISTANTS.SETTINGS.HEADER')"
|
|
||||||
:is-fetching="isFetching"
|
:is-fetching="isFetching"
|
||||||
:show-pagination-footer="false"
|
:show-pagination-footer="false"
|
||||||
:show-know-more="false"
|
:show-know-more="false"
|
||||||
|
|||||||
@@ -195,7 +195,10 @@ const navigateToPendingFAQs = () => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initializeFromURL();
|
initializeFromURL();
|
||||||
store.dispatch('captainResponses/fetchPendingCount', selectedAssistantId);
|
store.dispatch(
|
||||||
|
'captainResponses/fetchPendingCount',
|
||||||
|
selectedAssistantId.value
|
||||||
|
);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user