Artteiv's picture
The last samurai, a way of life
621d93e
<!doctype html>
<html>
<head>
<title>Python Project</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token }}">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/marked.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
background-color: #2A2A2A;
color: white;
}
.container {
display: flex;
height: 100vh;
}
.left-column {
width: 25%;
background-color: #3A3A3A;
padding: 20px;
overflow-y: auto;
}
.right-column {
width: 75%;
background-color: #2E2E2E;
padding: 20px;
overflow-y: auto;
}
.logout-button {
margin-left: 30px;
/* Adjust this value for more space */
}
</style>
</head>
<script>
function textAreaAdjust(element) {
element.style.height = "1px";
element.style.height = (element.scrollHeight/2) + "px";
}
</script>
<body>
<div id="app" class="container">
<div class="left-column">
<h2 class="text-xl font-medium mb-4">Lịch sử đoạn chat<button @click="logout"
class="bg-blue-500 text-white px-2 py-1 rounded mt-2 logout-button">
<a :href="`/users/logout`">Logout</a>
</button></h2>
<ul class="list-none">
{% for x in rooms %}
<li class="p-2 bg-[#4A4A4A] mb-2 rounded flex justify-between items-center">
<a :href="`/chat?id={{x.id}}`" class="cursor-pointer">{{ x.name }}</a>
<a :href="`/chat/delete?id={{x.id}}`" class="bg-red-500 text-white px-2 py-1 rounded">
Xoá
</a>
</li>
{% endfor %}
</ul>
</div>
<div class="right-column flex flex-col md:mx-auto mx-0 bg-[#2E2E2E] w-full h-screen">
<div class="flex flex-col h-full">
<!-- head -->
<div class="flex flex-row justify-between items-center p-4 select-none">
<h1 class="text-2xl font-medium text-center">
<a :href="`/chat`">Create new</a>
</h1>
</div>
<!-- config -->
<!-- messages -->
<div class="flex flex-col overflow-y-auto scroll-smooth" id="messages">
<div v-for="(message,index) in messages" :key="message.id"
class="flex flex-col odd:bg-[#F7F7F7]/10 group">
<div class="p-4 flex flex-col justify-between gap-4">
<div class="flex flex-row gap-4 capitalize">
<div class="text-gray-400 text-sm">
<textarea
class="text-gray-400 text-sm size-full outline-0 bg-transparent border-none text-white rounded-lg resize-none"
:rows="message.role" v-model="message.role" readonly>
</textarea>
</div>
<div class="flex flex-col w-full">
<div v-html="renderedMarkdown(message.content)" class="markdown-preview"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- send message -->
<div class="flex flex-row justify-between items-center p-4 sticky bottom-0 bg-[#2E2E2E]" v-if="!showConfig">
<div class="w-full flex flex-row border border-1 border-[#919191] rounded-xl px-4 py-6 items-center">
<textarea
class="w-full h-full outline-0 bg-transparent border-none text-white resize-none text-md max-h-[100px]"
v-on:keyup.enter="sendMessageAPI" placeholder="Type a message"
:rows="message.split('\n').length" v-model="message"></textarea>
<div class="flex flex-col justify-end gap-4 text-[#2E2E2E] rounded-md p-1"
:class="{'bg-white':message!='','bg-white/10':message==''}">
<button @click="sendMessageAPI">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
</button>
</div>
</div>
</div>
</div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
var roomdata = {{ roomdata| safe }};
createApp({
data() {
return {
showConfig: false,
configFields: [
{
name: "endPoint",
type: "text",
label: "End Point"
},
{
name: "apiKey",
type: "text",
label: "API Key"
},
{
name: "model",
type: "text",
label: "Model"
},
{
name: "temperature",
type: "number",
label: "Temperature"
},
{
name: "presence_penalty",
type: "number",
label: "Presence Penalty"
},
{
name: "top_p",
type: "number",
label: "Top P"
},
{
name: "frequency_penalty",
type: "number",
label: "Frequency Penalty"
},
],
isLoading: false,
isFirst: true,
message: '',
messages: roomdata.messages,
// cs:roomdata,
chatSocket: null,
config: {
endPoint: "",
apiKey: "",
model: "gpt-3.5-turbo",
temperature: 1,
presence_penalty: 0,
top_p: 1,
frequency_penalty: 0,
stream: true
},
// roomdata: roomdata
}
},
created() {
// const roomdata = JSON.parse('roomdata');
const params = new URLSearchParams(window.location.search);
this.id = params.get('id');//chat id
if (this.id == null) {
return
}
// this.connect()
this.ques = params.get('ques');
if (this.ques != null && this.isFirst == true) {
this.message = this.ques;
this.isFirst = false;
this.sendMessageAPI();
}
},
methods: {
refresh() {
this.send(true);
},
renderedMarkdown(content) {
return marked.parse(content);
}
,
deleteChat(id) {
window.location.href = '/chat/delete?id=' + id;
return;
},
sendMessageAPI() {
console.log("call sendMesageAPI");
if (this.id == null) {
window.location.href = '/chat/newchat?ques=' + this.message;
return;
}
this.ques = this.message;
this.message = "";
this.messages.push({
role: "user",
content: this.ques
});
fetch('/chat/messages/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'roomid': this.id,
'message': this.ques,
'messages': this.messages,
})
})
.then(response => response.json())
.then(data => {
this.messages.push({
role: "model",
content: data.message
});
})
.catch(error => {
console.error('Error sending or fetching messages:', error);
});
},
},
}).mount('#app');
</script>
</div>
</body>
</html>