mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-05 01:58:50 +01:00
chore: reorganize client files for docker
This commit is contained in:
parent
affbaaf1a5
commit
f5e079742a
93 changed files with 178726 additions and 1 deletions
156
client/src/components/Conversations/Conversation.jsx
Normal file
156
client/src/components/Conversations/Conversation.jsx
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
import React, { useState, useRef } from 'react';
|
||||
import RenameButton from './RenameButton';
|
||||
import DeleteButton from './DeleteButton';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { setConversation } from '~/store/convoSlice';
|
||||
import { setCustomGpt, setModel, setCustomModel } from '~/store/submitSlice';
|
||||
import { setMessages } from '~/store/messageSlice';
|
||||
import { setText } from '~/store/textSlice';
|
||||
import manualSWR from '~/utils/fetchers';
|
||||
import ConvoIcon from '../svg/ConvoIcon';
|
||||
|
||||
export default function Conversation({
|
||||
id,
|
||||
parentMessageId,
|
||||
conversationId,
|
||||
title = 'New conversation',
|
||||
bingData,
|
||||
chatGptLabel = null,
|
||||
promptPrefix = null
|
||||
}) {
|
||||
const [renaming, setRenaming] = useState(false);
|
||||
const [titleInput, setTitleInput] = useState(title);
|
||||
const { modelMap } = useSelector((state) => state.models);
|
||||
const inputRef = useRef(null);
|
||||
const dispatch = useDispatch();
|
||||
const { trigger } = manualSWR(`http://localhost:3080/messages/${id}`, 'get');
|
||||
const rename = manualSWR(`http://localhost:3080/convos/update`, 'post');
|
||||
|
||||
const clickHandler = async () => {
|
||||
if (conversationId === id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const convo = { title, error: false, conversationId: id, chatGptLabel, promptPrefix };
|
||||
|
||||
if (bingData) {
|
||||
const { conversationSignature, clientId, invocationId } = bingData;
|
||||
dispatch(
|
||||
setConversation({
|
||||
...convo,
|
||||
parentMessageId: null,
|
||||
conversationSignature,
|
||||
clientId,
|
||||
invocationId
|
||||
})
|
||||
);
|
||||
} else {
|
||||
dispatch(
|
||||
setConversation({
|
||||
...convo,
|
||||
parentMessageId,
|
||||
conversationSignature: null,
|
||||
clientId: null,
|
||||
invocationId: null
|
||||
})
|
||||
);
|
||||
}
|
||||
const data = await trigger();
|
||||
|
||||
if (chatGptLabel) {
|
||||
dispatch(setModel('chatgptCustom'));
|
||||
} else {
|
||||
dispatch(setModel(data[1].sender));
|
||||
}
|
||||
|
||||
if (modelMap[data[1].sender.toLowerCase()]) {
|
||||
console.log('sender', data[1].sender);
|
||||
dispatch(setCustomModel(data[1].sender.toLowerCase()));
|
||||
} else {
|
||||
dispatch(setCustomModel(null));
|
||||
}
|
||||
|
||||
dispatch(setMessages(data));
|
||||
dispatch(setCustomGpt(convo));
|
||||
dispatch(setText(''));
|
||||
};
|
||||
|
||||
const renameHandler = (e) => {
|
||||
e.preventDefault();
|
||||
setRenaming(true);
|
||||
setTimeout(() => {
|
||||
inputRef.current.focus();
|
||||
}, 25);
|
||||
};
|
||||
|
||||
const cancelHandler = (e) => {
|
||||
e.preventDefault();
|
||||
setRenaming(false);
|
||||
};
|
||||
|
||||
const onRename = (e) => {
|
||||
e.preventDefault();
|
||||
setRenaming(false);
|
||||
if (titleInput === title) {
|
||||
return;
|
||||
}
|
||||
rename.trigger({ conversationId, title: titleInput });
|
||||
};
|
||||
|
||||
const handleKeyPress = (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
onRename(e);
|
||||
}
|
||||
};
|
||||
|
||||
const aProps = {
|
||||
className:
|
||||
'animate-flash group relative flex cursor-pointer items-center gap-3 break-all rounded-md bg-gray-800 py-3 px-3 pr-14 hover:bg-gray-800'
|
||||
};
|
||||
|
||||
if (conversationId !== id) {
|
||||
aProps.className =
|
||||
'group relative flex cursor-pointer items-center gap-3 break-all rounded-md py-3 px-3 hover:bg-[#2A2B32] hover:pr-4';
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
onClick={() => clickHandler()}
|
||||
{...aProps}
|
||||
>
|
||||
<ConvoIcon />
|
||||
<div className="relative max-h-5 flex-1 overflow-hidden text-ellipsis break-all">
|
||||
{renaming === true ? (
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
className="m-0 mr-0 w-full border border-blue-500 bg-transparent p-0 text-sm leading-tight outline-none"
|
||||
value={titleInput}
|
||||
onChange={(e) => setTitleInput(e.target.value)}
|
||||
onBlur={onRename}
|
||||
onKeyPress={handleKeyPress}
|
||||
/>
|
||||
) : (
|
||||
titleInput
|
||||
)}
|
||||
</div>
|
||||
{conversationId === id ? (
|
||||
<div className="visible absolute right-1 z-10 flex text-gray-300">
|
||||
<RenameButton
|
||||
conversationId={id}
|
||||
renaming={renaming}
|
||||
renameHandler={renameHandler}
|
||||
onRename={onRename}
|
||||
/>
|
||||
<DeleteButton
|
||||
conversationId={id}
|
||||
renaming={renaming}
|
||||
cancelHandler={cancelHandler}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="absolute inset-y-0 right-0 z-10 w-8 bg-gradient-to-l from-gray-900 group-hover:from-[#2A2B32]" />
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
31
client/src/components/Conversations/DeleteButton.jsx
Normal file
31
client/src/components/Conversations/DeleteButton.jsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import TrashIcon from '../svg/TrashIcon';
|
||||
import CrossIcon from '../svg/CrossIcon';
|
||||
import manualSWR from '~/utils/fetchers';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { setConversation } from '~/store/convoSlice';
|
||||
import { setMessages } from '~/store/messageSlice';
|
||||
|
||||
export default function DeleteButton({ conversationId, renaming, cancelHandler }) {
|
||||
const dispatch = useDispatch();
|
||||
const { trigger } = manualSWR(
|
||||
`http://localhost:3080/convos/clear`,
|
||||
'post',
|
||||
() => {
|
||||
dispatch(setMessages([]));
|
||||
dispatch(setConversation({ title: 'New chat', conversationId: null, parentMessageId: null }));
|
||||
}
|
||||
);
|
||||
|
||||
const clickHandler = () => trigger({ conversationId });
|
||||
const handler = renaming ? cancelHandler : clickHandler;
|
||||
|
||||
return (
|
||||
<button
|
||||
className="p-1 hover:text-white"
|
||||
onClick={handler}
|
||||
>
|
||||
{ renaming ? <CrossIcon/> : <TrashIcon />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
13
client/src/components/Conversations/RenameButton.jsx
Normal file
13
client/src/components/Conversations/RenameButton.jsx
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import React from 'react';
|
||||
import RenameIcon from '../svg/RenameIcon';
|
||||
import CheckMark from '../svg/CheckMark';
|
||||
|
||||
export default function RenameButton({ onClick, renaming, renameHandler, onRename }) {
|
||||
const handler = renaming ? onRename : renameHandler;
|
||||
|
||||
return (
|
||||
<button className="p-1 hover:text-white" onClick={handler}>
|
||||
{renaming ? <CheckMark /> : <RenameIcon />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
46
client/src/components/Conversations/index.jsx
Normal file
46
client/src/components/Conversations/index.jsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import React from 'react';
|
||||
import Conversation from './Conversation';
|
||||
|
||||
export default function Conversations({ conversations, conversationId, showMore }) {
|
||||
const clickHandler = async (e) => {
|
||||
e.preventDefault();
|
||||
await showMore();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{conversations &&
|
||||
conversations.length > 0 &&
|
||||
conversations.map((convo) => {
|
||||
const bingData = convo.conversationSignature
|
||||
? {
|
||||
conversationSignature: convo.conversationSignature,
|
||||
clientId: convo.clientId,
|
||||
invocationId: convo.invocationId
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Conversation
|
||||
key={convo.conversationId}
|
||||
id={convo.conversationId}
|
||||
parentMessageId={convo.parentMessageId}
|
||||
title={convo.title}
|
||||
conversationId={conversationId}
|
||||
chatGptLabel={convo.chatGptLabel}
|
||||
promptPrefix={convo.promptPrefix}
|
||||
bingData={bingData}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{conversations && conversations.length >= 12 && conversations.length % 12 === 0 && (
|
||||
<button
|
||||
onClick={clickHandler}
|
||||
className="btn btn-dark btn-small m-auto mb-2 flex justify-center gap-2"
|
||||
>
|
||||
Show more
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue