287 lines
9.1 KiB
JavaScript
287 lines
9.1 KiB
JavaScript
// Copyright 2023 The casbin Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import React from "react";
|
|
import {Spin} from "antd";
|
|
import moment from "moment";
|
|
import ChatMenu from "./ChatMenu";
|
|
import ChatBox from "./ChatBox";
|
|
import * as Setting from "./Setting";
|
|
import * as ChatBackend from "./backend/ChatBackend";
|
|
import * as MessageBackend from "./backend/MessageBackend";
|
|
import i18next from "i18next";
|
|
import BaseListPage from "./BaseListPage";
|
|
|
|
class ChatPage extends BaseListPage {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.menu = React.createRef();
|
|
}
|
|
|
|
UNSAFE_componentWillMount() {
|
|
this.setState({
|
|
loading: true,
|
|
});
|
|
|
|
this.fetch();
|
|
}
|
|
|
|
newChat(chat) {
|
|
const randomName = Setting.getRandomName();
|
|
return {
|
|
owner: "admin", // this.props.account.applicationName,
|
|
name: `chat_${randomName}`,
|
|
createdTime: moment().format(),
|
|
updatedTime: moment().format(),
|
|
// organization: this.props.account.owner,
|
|
displayName: `New Chat - ${randomName}`,
|
|
type: "AI",
|
|
category: chat !== undefined ? chat.category : "Chat Category - 1",
|
|
user1: `${this.props.account.owner}/${this.props.account.name}`,
|
|
user2: "",
|
|
users: [`${this.props.account.owner}/${this.props.account.name}`],
|
|
messageCount: 0,
|
|
};
|
|
}
|
|
|
|
newMessage(text) {
|
|
const randomName = Setting.getRandomName();
|
|
return {
|
|
owner: "admin", // this.props.account.messagename,
|
|
name: `message_${randomName}`,
|
|
createdTime: moment().format(),
|
|
// organization: this.props.account.owner,
|
|
chat: this.state.chatName,
|
|
replyTo: "",
|
|
author: `${this.props.account.owner}/${this.props.account.name}`,
|
|
text: text,
|
|
};
|
|
}
|
|
|
|
sendMessage(text) {
|
|
const newMessage = this.newMessage(text);
|
|
MessageBackend.addMessage(newMessage)
|
|
.then((res) => {
|
|
if (res.status === "ok") {
|
|
this.getMessages(this.state.chatName);
|
|
} else {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
|
});
|
|
}
|
|
|
|
getMessages(chatName) {
|
|
MessageBackend.getChatMessages(chatName)
|
|
.then((res) => {
|
|
this.setState({
|
|
messages: res.data,
|
|
});
|
|
|
|
if (res.data.length > 0) {
|
|
const lastMessage = res.data[res.data.length - 1];
|
|
if (lastMessage.author === "AI" && lastMessage.replyTo !== "" && lastMessage.text === "") {
|
|
let text = "";
|
|
MessageBackend.getMessageAnswer(lastMessage.owner, lastMessage.name, (data) => {
|
|
if (data === "") {
|
|
data = "\n";
|
|
}
|
|
|
|
const lastMessage2 = Setting.deepCopy(lastMessage);
|
|
text += data;
|
|
lastMessage2.text = text;
|
|
res.data[res.data.length - 1] = lastMessage2;
|
|
this.setState({
|
|
messages: res.data,
|
|
});
|
|
}, (error) => {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to get answer")}: ${error}`);
|
|
|
|
const lastMessage2 = Setting.deepCopy(lastMessage);
|
|
lastMessage2.text = `#ERROR#: ${error}`;
|
|
res.data[res.data.length - 1] = lastMessage2;
|
|
this.setState({
|
|
messages: res.data,
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
Setting.scrollToDiv(`chatbox-list-item-${res.data.length}`);
|
|
});
|
|
}
|
|
|
|
addChat(chat) {
|
|
const newChat = this.newChat(chat);
|
|
ChatBackend.addChat(newChat)
|
|
.then((res) => {
|
|
if (res.status === "ok") {
|
|
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
|
this.setState({
|
|
chatName: newChat.name,
|
|
messages: null,
|
|
});
|
|
this.getMessages(newChat.name);
|
|
|
|
this.fetch({}, false);
|
|
} else {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
|
});
|
|
}
|
|
|
|
deleteChat(chats, i, chat) {
|
|
ChatBackend.deleteChat(chat)
|
|
.then((res) => {
|
|
if (res.status === "ok") {
|
|
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
|
const data = Setting.deleteRow(this.state.data, i);
|
|
const j = Math.min(i, data.length - 1);
|
|
if (j < 0) {
|
|
this.setState({
|
|
chatName: undefined,
|
|
messages: [],
|
|
data: data,
|
|
});
|
|
} else {
|
|
const focusedChat = data[j];
|
|
this.setState({
|
|
chatName: focusedChat.name,
|
|
messages: null,
|
|
data: data,
|
|
});
|
|
this.getMessages(focusedChat.name);
|
|
}
|
|
} else {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
|
});
|
|
}
|
|
|
|
getCurrentChat() {
|
|
return this.state.data.filter(chat => chat.name === this.state.chatName)[0];
|
|
}
|
|
|
|
renderTable(chats) {
|
|
const onSelectChat = (i) => {
|
|
const chat = chats[i];
|
|
this.setState({
|
|
chatName: chat.name,
|
|
messages: null,
|
|
});
|
|
this.getMessages(chat.name);
|
|
};
|
|
|
|
const onAddChat = () => {
|
|
const chat = this.getCurrentChat();
|
|
this.addChat(chat);
|
|
};
|
|
|
|
const onDeleteChat = (i) => {
|
|
const chat = chats[i];
|
|
this.deleteChat(chats, i, chat);
|
|
};
|
|
|
|
if (this.state.loading) {
|
|
return (
|
|
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
|
<Spin size="large" tip={i18next.t("login:Loading")} style={{paddingTop: "10%"}} />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div style={{display: "flex", height: "calc(100vh - 136px)"}}>
|
|
<div style={{width: "250px", height: "100%", backgroundColor: "white", borderRight: "1px solid rgb(245,245,245)", borderBottom: "1px solid rgb(245,245,245)"}}>
|
|
<ChatMenu ref={this.menu} chats={chats} onSelectChat={onSelectChat} onAddChat={onAddChat} onDeleteChat={onDeleteChat} />
|
|
</div>
|
|
<div style={{flex: 1, height: "100%", backgroundColor: "white", position: "relative"}}>
|
|
{
|
|
(this.state.messages === undefined || this.state.messages === null) ? null : (
|
|
<div style={{
|
|
position: "absolute",
|
|
top: -50,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
backgroundImage: "url(https://cdn.casbin.org/img/casdoor-logo_1185x256.png)",
|
|
backgroundPosition: "center",
|
|
backgroundRepeat: "no-repeat",
|
|
backgroundSize: "200px auto",
|
|
backgroundBlendMode: "luminosity",
|
|
filter: "grayscale(80%) brightness(140%) contrast(90%)",
|
|
opacity: 0.5,
|
|
pointerEvents: "none",
|
|
}}>
|
|
</div>
|
|
)
|
|
}
|
|
<ChatBox messages={this.state.messages} sendMessage={(text) => {this.sendMessage(text);}} account={this.props.account} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
fetch = (params = {}, setLoading = true) => {
|
|
let field = params.searchedColumn, value = params.searchText;
|
|
const sortField = params.sortField, sortOrder = params.sortOrder;
|
|
if (params.category !== undefined && params.category !== null) {
|
|
field = "category";
|
|
value = params.category;
|
|
} else if (params.type !== undefined && params.type !== null) {
|
|
field = "type";
|
|
value = params.type;
|
|
}
|
|
if (setLoading) {
|
|
this.setState({loading: true});
|
|
}
|
|
ChatBackend.getChats("admin", -1, field, value, sortField, sortOrder)
|
|
.then((res) => {
|
|
if (res.status === "ok") {
|
|
this.setState({
|
|
loading: false,
|
|
data: res.data,
|
|
messages: [],
|
|
searchText: params.searchText,
|
|
searchedColumn: params.searchedColumn,
|
|
});
|
|
|
|
const chats = res.data;
|
|
if (this.state.chatName === undefined && chats.length > 0) {
|
|
const chat = chats[0];
|
|
this.getMessages(chat.name);
|
|
this.setState({
|
|
chatName: chat.name,
|
|
});
|
|
}
|
|
|
|
if (!setLoading) {
|
|
this.menu.current.setSelectedKeyToNewChat(chats);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
export default ChatPage;
|