mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-04 21:30:24 +08:00
Improve chat UI
This commit is contained in:
@ -13,8 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Menu} from "antd";
|
import {Button, Menu} from "antd";
|
||||||
import {LayoutOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, LayoutOutlined, PlusOutlined} from "@ant-design/icons";
|
||||||
|
|
||||||
class ChatMenu extends React.Component {
|
class ChatMenu extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -38,6 +38,7 @@ class ChatMenu extends React.Component {
|
|||||||
categories[chat.category].push(chat);
|
categories[chat.category].push(chat);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const selectedKeys = this.state === undefined ? [] : this.state.selectedKeys;
|
||||||
return Object.keys(categories).map((category, index) => {
|
return Object.keys(categories).map((category, index) => {
|
||||||
return {
|
return {
|
||||||
key: `${index}`,
|
key: `${index}`,
|
||||||
@ -45,10 +46,50 @@ class ChatMenu extends React.Component {
|
|||||||
label: category,
|
label: category,
|
||||||
children: categories[category].map((chat, chatIndex) => {
|
children: categories[category].map((chat, chatIndex) => {
|
||||||
const globalChatIndex = chats.indexOf(chat);
|
const globalChatIndex = chats.indexOf(chat);
|
||||||
|
const isSelected = selectedKeys.includes(`${index}-${chatIndex}`);
|
||||||
return {
|
return {
|
||||||
key: `${index}-${chatIndex}`,
|
key: `${index}-${chatIndex}`,
|
||||||
index: globalChatIndex,
|
index: globalChatIndex,
|
||||||
label: chat.displayName,
|
label: (
|
||||||
|
<div
|
||||||
|
className="menu-item-container"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{chat.displayName}
|
||||||
|
{isSelected && (
|
||||||
|
<DeleteOutlined
|
||||||
|
className="menu-item-delete-icon"
|
||||||
|
style={{
|
||||||
|
visibility: "visible",
|
||||||
|
color: "inherit",
|
||||||
|
transition: "color 0.3s",
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.color = "rgba(89,54,213,0.6)";
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.color = "inherit";
|
||||||
|
}}
|
||||||
|
onMouseDown={(e) => {
|
||||||
|
e.currentTarget.style.color = "rgba(89,54,213,0.4)";
|
||||||
|
}}
|
||||||
|
onMouseUp={(e) => {
|
||||||
|
e.currentTarget.style.color = "rgba(89,54,213,0.6)";
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (this.props.onDelete) {
|
||||||
|
this.props.onDelete(globalChatIndex);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
@ -85,6 +126,31 @@ class ChatMenu extends React.Component {
|
|||||||
const items = this.chatsToItems(this.props.chats);
|
const items = this.chatsToItems(this.props.chats);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
style={{
|
||||||
|
width: "calc(100% - 8px)",
|
||||||
|
height: "40px",
|
||||||
|
margin: "4px",
|
||||||
|
borderColor: "rgb(229,229,229)",
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.borderColor = "rgba(89,54,213,0.6)";
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.borderColor = "rgba(0, 0, 0, 0.1)";
|
||||||
|
}}
|
||||||
|
onMouseDown={(e) => {
|
||||||
|
e.currentTarget.style.borderColor = "rgba(89,54,213,0.4)";
|
||||||
|
}}
|
||||||
|
onMouseUp={(e) => {
|
||||||
|
e.currentTarget.style.borderColor = "rgba(89,54,213,0.6)";
|
||||||
|
}}
|
||||||
|
onClick={this.props.onNewChat}
|
||||||
|
>
|
||||||
|
New Chat
|
||||||
|
</Button>
|
||||||
<Menu
|
<Menu
|
||||||
mode="inline"
|
mode="inline"
|
||||||
openKeys={this.state.openKeys}
|
openKeys={this.state.openKeys}
|
||||||
@ -93,6 +159,7 @@ class ChatMenu extends React.Component {
|
|||||||
onSelect={this.onSelect}
|
onSelect={this.onSelect}
|
||||||
items={items}
|
items={items}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,8 @@ class ProviderEditPage extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
||||||
}
|
}
|
||||||
|
case "AI":
|
||||||
|
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
||||||
default:
|
default:
|
||||||
return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip"));
|
||||||
}
|
}
|
||||||
@ -278,17 +280,20 @@ class ProviderEditPage extends React.Component {
|
|||||||
this.updateProviderField("type", "Alipay");
|
this.updateProviderField("type", "Alipay");
|
||||||
} else if (value === "Captcha") {
|
} else if (value === "Captcha") {
|
||||||
this.updateProviderField("type", "Default");
|
this.updateProviderField("type", "Default");
|
||||||
|
} else if (value === "AI") {
|
||||||
|
this.updateProviderField("type", "OpenAI API - GPT");
|
||||||
}
|
}
|
||||||
})}>
|
})}>
|
||||||
{
|
{
|
||||||
[
|
[
|
||||||
{id: "OAuth", name: "OAuth"},
|
{id: "AI", name: "AI"},
|
||||||
|
{id: "Captcha", name: "Captcha"},
|
||||||
{id: "Email", name: "Email"},
|
{id: "Email", name: "Email"},
|
||||||
|
{id: "OAuth", name: "OAuth"},
|
||||||
|
{id: "Payment", name: "Payment"},
|
||||||
|
{id: "SAML", name: "SAML"},
|
||||||
{id: "SMS", name: "SMS"},
|
{id: "SMS", name: "SMS"},
|
||||||
{id: "Storage", name: "Storage"},
|
{id: "Storage", name: "Storage"},
|
||||||
{id: "SAML", name: "SAML"},
|
|
||||||
{id: "Payment", name: "Payment"},
|
|
||||||
{id: "Captcha", name: "Captcha"},
|
|
||||||
]
|
]
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
.map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
|
.map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
|
||||||
@ -437,6 +442,8 @@ class ProviderEditPage extends React.Component {
|
|||||||
{
|
{
|
||||||
this.state.provider.category === "Captcha" && this.state.provider.type === "Default" ? null : (
|
this.state.provider.category === "Captcha" && this.state.provider.type === "Default" ? null : (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
this.state.provider.category === "AI" ? null : (
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{this.getClientIdLabel(this.state.provider)}
|
{this.getClientIdLabel(this.state.provider)}
|
||||||
@ -447,6 +454,8 @@ class ProviderEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{this.getClientSecretLabel(this.state.provider)}
|
{this.getClientSecretLabel(this.state.provider)}
|
||||||
|
@ -204,6 +204,12 @@ export const OtherProviderInfo = {
|
|||||||
url: "https://www.cloudflare.com/products/turnstile/",
|
url: "https://www.cloudflare.com/products/turnstile/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AI: {
|
||||||
|
"OpenAI API - GPT": {
|
||||||
|
logo: `${StaticBaseUrl}/img/social_openai.svg`,
|
||||||
|
url: "https://platform.openai.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function initCountries() {
|
export function initCountries() {
|
||||||
@ -855,6 +861,10 @@ export function getProviderTypeOptions(category) {
|
|||||||
{id: "GEETEST", name: "GEETEST"},
|
{id: "GEETEST", name: "GEETEST"},
|
||||||
{id: "Cloudflare Turnstile", name: "Cloudflare Turnstile"},
|
{id: "Cloudflare Turnstile", name: "Cloudflare Turnstile"},
|
||||||
]);
|
]);
|
||||||
|
} else if (category === "AI") {
|
||||||
|
return ([
|
||||||
|
{id: "OpenAI API - GPT", name: "OpenAI API - GPT"},
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user