<template>
<Header :name="$route.name" :title="$t($route.name)" />
<q-btn style="position:absolute; top:40px; right:5px; z-index: 9999;" @click="toolbarOpen = true" padding="xs"
icon="settings" size="sm" />
<Toolbar ref="toolbar" :open="toolbarOpen" width="300px" top="75px" align="right" @close="toolbarOpen = false"
bg-color="whitesmoke">
<component :is="'ChatToolbar'" bgColor="whitesmoke" :data="$data" />
</Toolbar>
<div id="chat-container">
<q-scroll-area @scroll="scrolled" ref="scroll" :style="{ height: ($q.screen.height - 75 - 65) + 'px' }">
<div v-for="msg of messages" key="id" class="row">
<div v-if="msg.parent_id == null" class="row q-ml-sm q-mt-sm">
<div class="prompt"><span v-html="msg.message" />
<q-btn flat style="position:absolute; right:50px;" round size="xs" icon="edit"
@click="message = msg.message"></q-btn>
<q-btn v-if="msg.id && msg.id != 0" flat style="position:absolute; right:30px;" round size="xs"
icon="delete" @click="deleteMessage(msg.id)"></q-btn>
</div>
</div>
<div v-else class="row response" v-html="msg.message.replaceAll('\\', '')">
</div>
</div>
</q-scroll-area>
</div>
<div class="row q-ml-sm">
<div class="col-11">
<q-input v-model="message" :label="$t('Type your prompt')" @keyup.enter="sendMessage" />
</div>
<div class="col-1 right-item">
<q-btn flat class="q-ma-sm" round size="sm" icon="send" @click="sendMessage"></q-btn>
</div>
</div>
</template>
<script>
/**
* Chat component
* @component components/chat
* @description Chat component
* @example
* <Chat />
*/
import Header from "./header.vue";
import Toolbar from "./toolbar.vue";
import ChatToolbar from "./chat-toolbar.vue";
export default {
name: "Chat",
components: {
Header,
Toolbar,
ChatToolbar
},
data() {
return {
storable: ["selectedModel", "saveMessages"],
message: '',
models: [],
messages: [],
selectedModel: { value: 1, label: "mixtral" },
saveMessages: false,
toolbarOpen: false,
};
},
beforeRouteEnter(to, from, next) {
next(vm => { vm.init(to.name); });
},
beforeRouteUpdate(to, from, next) {
this.routeKey++;
this.init(to.name);
next();
},
beforeRouteLeave(to, from, next) {
this.saveStorable(this, from.name);
next();
},
async mounted() {
},
methods: {
async deleteMessage(id) {
let response = await this.post("Chat/DeleteMessage", { id: id.toString() });
if (response != null) {
let index = this.messages.findIndex(m => m.id == id);
this.messages.splice(index, 1);
index = this.messages.findIndex(m => m.parent_id == id);
this.messages.splice(index, 1);
};
},
async init(name) {
this.loadStorable(this, name);
this.models = this.$store.catalogs.aiModels; // await this.get("Chat/GetAIModels");
this.messages = await this.get("Chat/GetMessages");
this.scrollToBottom();
},
scrolled(info) {
},
scrollToBottom() {
this.$nextTick(() => {
//this.$refs.scroll.setScrollPercentage("vertical", 1., 0);
this.$refs.scroll.setScrollPosition("vertical", 9999999);
});
},
async sendMessage() {
if (this.message.trim() !== '') {
this.messages.push({ id: null, parent_id: null, message: this.message });
let response = await this.post("Chat/SendMessage", { message: this.message, saveMessages: this.saveMessages.toString(), model: this.selectedModel.label });
if (response != null) {
this.messages.push({
id: response.id_response,
message: response.content,
parent_id: response.id_prompt
});
let pm = this.messages.find(m => m.id == null);
pm.id = response.id_prompt;
this.message = '';
this.scrollToBottom();
};
}
}
}
};
</script>
<style scoped>
#chat-container {
display: absolute;
width: 100%;
}
.prompt {
color: teal;
}
.response {
margin-left: 20px;
}
.input {
position: absolute;
bottom: 0px;
height: 50px;
background-color: white;
}
</style>