mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-20 02:16:39 +00:00
Merge branch 'main' of https://github.com/ManishMadan2882/docsgpt
This commit is contained in:
commit
fab367f041
8 files changed
+115
-24
No files matched your search
@@ -316,7 +316,7 @@ class UploadFile(Resource):
|
|||||||
for file in files:
|
for file in files:
|
||||||
filename = secure_filename(file.filename)
|
filename = secure_filename(file.filename)
|
||||||
file.save(os.path.join(temp_dir, filename))
|
file.save(os.path.join(temp_dir, filename))
|
||||||
|
print(f"Saved file: {filename}")
|
||||||
zip_path = shutil.make_archive(
|
zip_path = shutil.make_archive(
|
||||||
base_name=os.path.join(save_dir, job_name),
|
base_name=os.path.join(save_dir, job_name),
|
||||||
format="zip",
|
format="zip",
|
||||||
@@ -324,6 +324,26 @@ class UploadFile(Resource):
|
|||||||
)
|
)
|
||||||
final_filename = os.path.basename(zip_path)
|
final_filename = os.path.basename(zip_path)
|
||||||
shutil.rmtree(temp_dir)
|
shutil.rmtree(temp_dir)
|
||||||
|
task = ingest.delay(
|
||||||
|
settings.UPLOAD_FOLDER,
|
||||||
|
[
|
||||||
|
".rst",
|
||||||
|
".md",
|
||||||
|
".pdf",
|
||||||
|
".txt",
|
||||||
|
".docx",
|
||||||
|
".csv",
|
||||||
|
".epub",
|
||||||
|
".html",
|
||||||
|
".mdx",
|
||||||
|
".json",
|
||||||
|
".xlsx",
|
||||||
|
".pptx",
|
||||||
|
],
|
||||||
|
job_name,
|
||||||
|
final_filename,
|
||||||
|
user,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
file = files[0]
|
file = files[0]
|
||||||
final_filename = secure_filename(file.filename)
|
final_filename = secure_filename(file.filename)
|
||||||
@@ -350,9 +370,10 @@ class UploadFile(Resource):
|
|||||||
final_filename,
|
final_filename,
|
||||||
user,
|
user,
|
||||||
)
|
)
|
||||||
except Exception as err:
|
|
||||||
return make_response(jsonify({"success": False, "error": str(err)}), 400)
|
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
print(f"Error: {err}")
|
||||||
|
return make_response(jsonify({"success": False, "error": str(err)}), 400)
|
||||||
return make_response(jsonify({"success": True, "task_id": task.id}), 200)
|
return make_response(jsonify({"success": True, "task_id": task.id}), 200)
|
||||||
|
|
||||||
|
|
||||||
@@ -423,6 +444,11 @@ class TaskStatus(Resource):
|
|||||||
|
|
||||||
task = celery.AsyncResult(task_id)
|
task = celery.AsyncResult(task_id)
|
||||||
task_meta = task.info
|
task_meta = task.info
|
||||||
|
print(f"Task status: {task.status}")
|
||||||
|
if not isinstance(
|
||||||
|
task_meta, (dict, list, str, int, float, bool, type(None))
|
||||||
|
):
|
||||||
|
task_meta = str(task_meta) # Convert to a string representation
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
return make_response(jsonify({"success": False, "error": str(err)}), 400)
|
return make_response(jsonify({"success": False, "error": str(err)}), 400)
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ function Dropdown({
|
|||||||
: option.description
|
: option.description
|
||||||
}`}
|
}`}
|
||||||
</span>
|
</span>
|
||||||
{showEdit && onEdit && (
|
{showEdit && onEdit && option.type !== 'public' && (
|
||||||
<img
|
<img
|
||||||
src={Edit}
|
src={Edit}
|
||||||
alt="Edit"
|
alt="Edit"
|
||||||
|
|||||||
@@ -1,29 +1,30 @@
|
|||||||
import { Fragment, useEffect, useRef, useState } from 'react';
|
import { Fragment, useEffect, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import newChatIcon from '../assets/openNewChat.svg';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import Hero from '../Hero';
|
||||||
import ArrowDown from '../assets/arrow-down.svg';
|
import ArrowDown from '../assets/arrow-down.svg';
|
||||||
|
import newChatIcon from '../assets/openNewChat.svg';
|
||||||
import Send from '../assets/send.svg';
|
import Send from '../assets/send.svg';
|
||||||
import SendDark from '../assets/send_dark.svg';
|
import SendDark from '../assets/send_dark.svg';
|
||||||
|
import ShareIcon from '../assets/share.svg';
|
||||||
import SpinnerDark from '../assets/spinner-dark.svg';
|
import SpinnerDark from '../assets/spinner-dark.svg';
|
||||||
import Spinner from '../assets/spinner.svg';
|
import Spinner from '../assets/spinner.svg';
|
||||||
import RetryIcon from '../components/RetryIcon';
|
import RetryIcon from '../components/RetryIcon';
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import Hero from '../Hero';
|
|
||||||
import { useDarkTheme, useMediaQuery } from '../hooks';
|
import { useDarkTheme, useMediaQuery } from '../hooks';
|
||||||
import { ShareConversationModal } from '../modals/ShareConversationModal';
|
import { ShareConversationModal } from '../modals/ShareConversationModal';
|
||||||
import { setConversation, updateConversationId } from './conversationSlice';
|
|
||||||
import { selectConversationId } from '../preferences/preferenceSlice';
|
import { selectConversationId } from '../preferences/preferenceSlice';
|
||||||
import { AppDispatch } from '../store';
|
import { AppDispatch } from '../store';
|
||||||
import ConversationBubble from './ConversationBubble';
|
import ConversationBubble from './ConversationBubble';
|
||||||
import { handleSendFeedback } from './conversationHandlers';
|
import { handleSendFeedback } from './conversationHandlers';
|
||||||
import { FEEDBACK, Query } from './conversationModels';
|
import { FEEDBACK, Query } from './conversationModels';
|
||||||
import ShareIcon from '../assets/share.svg';
|
|
||||||
import {
|
import {
|
||||||
addQuery,
|
addQuery,
|
||||||
fetchAnswer,
|
fetchAnswer,
|
||||||
selectQueries,
|
selectQueries,
|
||||||
selectStatus,
|
selectStatus,
|
||||||
|
setConversation,
|
||||||
|
updateConversationId,
|
||||||
updateQuery,
|
updateQuery,
|
||||||
} from './conversationSlice';
|
} from './conversationSlice';
|
||||||
|
|
||||||
@@ -302,14 +303,14 @@ export default function Conversation() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-11/12 flex-col items-end self-center rounded-2xl bg-opacity-0 pb-1 sm:w-[62%] h-auto">
|
<div className="flex w-11/12 flex-col items-end self-center rounded-2xl bg-opacity-0 z-3 sm:w-[62%] h-auto">
|
||||||
<div className="flex w-full items-center rounded-[40px] border border-silver bg-white py-1 dark:bg-raisin-black">
|
<div className="flex w-full items-center rounded-[40px] border border-silver bg-white py-1 dark:bg-raisin-black">
|
||||||
<textarea
|
<textarea
|
||||||
id="inputbox"
|
id="inputbox"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
placeholder={t('inputPlaceholder')}
|
placeholder={t('inputPlaceholder')}
|
||||||
className={`inputbox-style h-16 w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-full bg-white pt-5 pb-[22px] text-base leading-tight opacity-100 focus:outline-none dark:bg-raisin-black dark:text-bright-gray`}
|
className={`inputbox-style w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-full bg-transparent py-5 text-base leading-tight opacity-100 focus:outline-none dark:bg-transparent dark:text-bright-gray`}
|
||||||
onInput={handleInput}
|
onInput={handleInput}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === 'Enter' && !e.shiftKey) {
|
if (e.key === 'Enter' && !e.shiftKey) {
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
|
import 'katex/dist/katex.min.css';
|
||||||
|
|
||||||
import { forwardRef, useState } from 'react';
|
import { forwardRef, useState } from 'react';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||||
|
import rehypeKatex from 'rehype-katex';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import remarkMath from 'remark-math';
|
import remarkMath from 'remark-math';
|
||||||
import rehypeKatex from 'rehype-katex';
|
|
||||||
import 'katex/dist/katex.min.css';
|
|
||||||
import DocsGPT3 from '../assets/cute_docsgpt3.svg';
|
import DocsGPT3 from '../assets/cute_docsgpt3.svg';
|
||||||
import Dislike from '../assets/dislike.svg?react';
|
import Dislike from '../assets/dislike.svg?react';
|
||||||
import Document from '../assets/document.svg';
|
import Document from '../assets/document.svg';
|
||||||
@@ -16,13 +18,13 @@ import Sources from '../assets/sources.svg';
|
|||||||
import Avatar from '../components/Avatar';
|
import Avatar from '../components/Avatar';
|
||||||
import CopyButton from '../components/CopyButton';
|
import CopyButton from '../components/CopyButton';
|
||||||
import Sidebar from '../components/Sidebar';
|
import Sidebar from '../components/Sidebar';
|
||||||
|
import SpeakButton from '../components/TextToSpeechButton';
|
||||||
import {
|
import {
|
||||||
selectChunks,
|
selectChunks,
|
||||||
selectSelectedDocs,
|
selectSelectedDocs,
|
||||||
} from '../preferences/preferenceSlice';
|
} from '../preferences/preferenceSlice';
|
||||||
import classes from './ConversationBubble.module.css';
|
import classes from './ConversationBubble.module.css';
|
||||||
import { FEEDBACK, MESSAGE_TYPE } from './conversationModels';
|
import { FEEDBACK, MESSAGE_TYPE } from './conversationModels';
|
||||||
import SpeakButton from '../components/TextToSpeechButton';
|
|
||||||
|
|
||||||
const DisableSourceFE = import.meta.env.VITE_DISABLE_SOURCE_FE || false;
|
const DisableSourceFE = import.meta.env.VITE_DISABLE_SOURCE_FE || false;
|
||||||
|
|
||||||
@@ -41,6 +43,7 @@ const ConversationBubble = forwardRef<
|
|||||||
{ message, type, className, feedback, handleFeedback, sources, retryBtn },
|
{ message, type, className, feedback, handleFeedback, sources, retryBtn },
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
|
// const bubbleRef = useRef<HTMLDivElement | null>(null);
|
||||||
const chunks = useSelector(selectChunks);
|
const chunks = useSelector(selectChunks);
|
||||||
const selectedDocs = useSelector(selectSelectedDocs);
|
const selectedDocs = useSelector(selectSelectedDocs);
|
||||||
const [isLikeHovered, setIsLikeHovered] = useState(false);
|
const [isLikeHovered, setIsLikeHovered] = useState(false);
|
||||||
@@ -141,7 +144,7 @@ const ConversationBubble = forwardRef<
|
|||||||
/>
|
/>
|
||||||
<p className="text-base font-semibold">Sources</p>
|
<p className="text-base font-semibold">Sources</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-3 mr-5 max-w-[90vw] md:max-w-[70vw] lg:max-w-[50vw]">
|
<div className="fade-in ml-3 mr-5 max-w-[90vw] md:max-w-[70vw] lg:max-w-[50vw]">
|
||||||
<div className="grid grid-cols-2 gap-2 lg:grid-cols-4">
|
<div className="grid grid-cols-2 gap-2 lg:grid-cols-4">
|
||||||
{sources?.slice(0, 3)?.map((source, index) => (
|
{sources?.slice(0, 3)?.map((source, index) => (
|
||||||
<div key={index} className="relative">
|
<div key={index} className="relative">
|
||||||
@@ -190,7 +193,7 @@ const ConversationBubble = forwardRef<
|
|||||||
</div>
|
</div>
|
||||||
{activeTooltip === index && (
|
{activeTooltip === index && (
|
||||||
<div
|
<div
|
||||||
className={`absolute left-1/2 z-30 max-h-48 w-40 translate-x-[-50%] translate-y-[3px] rounded-xl bg-[#FBFBFB] p-4 text-black shadow-xl dark:bg-chinese-black dark:text-chinese-silver sm:w-56`}
|
className={`absolute left-1/2 z-50 max-h-48 w-40 translate-x-[-50%] translate-y-[3px] rounded-xl bg-[#FBFBFB] p-4 text-black shadow-xl dark:bg-chinese-black dark:text-chinese-silver sm:w-56`}
|
||||||
onMouseOver={() => setActiveTooltip(index)}
|
onMouseOver={() => setActiveTooltip(index)}
|
||||||
onMouseOut={() => setActiveTooltip(null)}
|
onMouseOut={() => setActiveTooltip(null)}
|
||||||
>
|
>
|
||||||
@@ -231,14 +234,14 @@ const ConversationBubble = forwardRef<
|
|||||||
<p className="text-base font-semibold">Answer</p>
|
<p className="text-base font-semibold">Answer</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`ml-2 mr-5 flex max-w-[90vw] rounded-[28px] bg-gray-1000 py-[14px] px-7 dark:bg-gun-metal md:max-w-[70vw] lg:max-w-[50vw] ${
|
className={`fade-in-bubble ml-2 mr-5 flex max-w-[90vw] rounded-[28px] bg-gray-1000 py-[14px] px-7 dark:bg-gun-metal md:max-w-[70vw] lg:max-w-[50vw] ${
|
||||||
type === 'ERROR'
|
type === 'ERROR'
|
||||||
? 'relative flex-row items-center rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
|
? 'relative flex-row items-center rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
|
||||||
: 'flex-col rounded-3xl'
|
: 'flex-col rounded-3xl'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
className="whitespace-pre-wrap break-normal leading-normal"
|
className="fade-in whitespace-pre-wrap break-normal leading-normal"
|
||||||
remarkPlugins={[remarkGfm, remarkMath]}
|
remarkPlugins={[remarkGfm, remarkMath]}
|
||||||
rehypePlugins={[rehypeKatex]}
|
rehypePlugins={[rehypeKatex]}
|
||||||
components={{
|
components={{
|
||||||
|
|||||||
@@ -514,3 +514,29 @@ input:-webkit-autofill:focus {
|
|||||||
.logs-table {
|
.logs-table {
|
||||||
font-family: 'IBMPlexMono-Medium', system-ui;
|
font-family: 'IBMPlexMono-Medium', system-ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fade-in {
|
||||||
|
animation: fadeIn 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in-bubble {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
animation: fadeInUp 0.5s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ActiveState } from '../models/misc';
|
import { ActiveState } from '../models/misc';
|
||||||
import Exit from '../assets/exit.svg';
|
import Exit from '../assets/exit.svg';
|
||||||
import Input from '../components/Input';
|
import Input from '../components/Input';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
function AddPrompt({
|
function AddPrompt({
|
||||||
setModalState,
|
setModalState,
|
||||||
@@ -9,6 +10,7 @@ function AddPrompt({
|
|||||||
setNewPromptName,
|
setNewPromptName,
|
||||||
newPromptContent,
|
newPromptContent,
|
||||||
setNewPromptContent,
|
setNewPromptContent,
|
||||||
|
disableSave,
|
||||||
}: {
|
}: {
|
||||||
setModalState: (state: ActiveState) => void;
|
setModalState: (state: ActiveState) => void;
|
||||||
handleAddPrompt?: () => void;
|
handleAddPrompt?: () => void;
|
||||||
@@ -16,6 +18,7 @@ function AddPrompt({
|
|||||||
setNewPromptName: (name: string) => void;
|
setNewPromptName: (name: string) => void;
|
||||||
newPromptContent: string;
|
newPromptContent: string;
|
||||||
setNewPromptContent: (content: string) => void;
|
setNewPromptContent: (content: string) => void;
|
||||||
|
disableSave: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@@ -23,6 +26,8 @@ function AddPrompt({
|
|||||||
className="absolute top-3 right-4 m-2 w-3"
|
className="absolute top-3 right-4 m-2 w-3"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setModalState('INACTIVE');
|
setModalState('INACTIVE');
|
||||||
|
setNewPromptName('');
|
||||||
|
setNewPromptContent('');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img className="filter dark:invert" src={Exit} />
|
<img className="filter dark:invert" src={Exit} />
|
||||||
@@ -41,7 +46,7 @@ function AddPrompt({
|
|||||||
className="h-10 rounded-lg"
|
className="h-10 rounded-lg"
|
||||||
value={newPromptName}
|
value={newPromptName}
|
||||||
onChange={(e) => setNewPromptName(e.target.value)}
|
onChange={(e) => setNewPromptName(e.target.value)}
|
||||||
></Input>
|
/>
|
||||||
<div className="relative bottom-12 left-3 mt-[-3.00px]">
|
<div className="relative bottom-12 left-3 mt-[-3.00px]">
|
||||||
<span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver">
|
<span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver">
|
||||||
Prompt Name
|
Prompt Name
|
||||||
@@ -62,6 +67,8 @@ function AddPrompt({
|
|||||||
<button
|
<button
|
||||||
onClick={handleAddPrompt}
|
onClick={handleAddPrompt}
|
||||||
className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:opacity-90"
|
className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:opacity-90"
|
||||||
|
disabled={disableSave}
|
||||||
|
title={disableSave && newPromptName ? 'Name already exists' : ''}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
@@ -79,6 +86,7 @@ function EditPrompt({
|
|||||||
editPromptContent,
|
editPromptContent,
|
||||||
setEditPromptContent,
|
setEditPromptContent,
|
||||||
currentPromptEdit,
|
currentPromptEdit,
|
||||||
|
disableSave,
|
||||||
}: {
|
}: {
|
||||||
setModalState: (state: ActiveState) => void;
|
setModalState: (state: ActiveState) => void;
|
||||||
handleEditPrompt?: (id: string, type: string) => void;
|
handleEditPrompt?: (id: string, type: string) => void;
|
||||||
@@ -87,6 +95,7 @@ function EditPrompt({
|
|||||||
editPromptContent: string;
|
editPromptContent: string;
|
||||||
setEditPromptContent: (content: string) => void;
|
setEditPromptContent: (content: string) => void;
|
||||||
currentPromptEdit: { name: string; id: string; type: string };
|
currentPromptEdit: { name: string; id: string; type: string };
|
||||||
|
disableSave: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@@ -140,7 +149,8 @@ function EditPrompt({
|
|||||||
handleEditPrompt &&
|
handleEditPrompt &&
|
||||||
handleEditPrompt(currentPromptEdit.id, currentPromptEdit.type);
|
handleEditPrompt(currentPromptEdit.id, currentPromptEdit.type);
|
||||||
}}
|
}}
|
||||||
disabled={currentPromptEdit.type === 'public'}
|
disabled={currentPromptEdit.type === 'public' || disableSave}
|
||||||
|
title={disableSave && editPromptName ? 'Name already exists' : ''}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
@@ -151,6 +161,7 @@ function EditPrompt({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function PromptsModal({
|
export default function PromptsModal({
|
||||||
|
existingPrompts,
|
||||||
modalState,
|
modalState,
|
||||||
setModalState,
|
setModalState,
|
||||||
type,
|
type,
|
||||||
@@ -166,6 +177,7 @@ export default function PromptsModal({
|
|||||||
handleAddPrompt,
|
handleAddPrompt,
|
||||||
handleEditPrompt,
|
handleEditPrompt,
|
||||||
}: {
|
}: {
|
||||||
|
existingPrompts: { name: string; id: string; type: string }[];
|
||||||
modalState: ActiveState;
|
modalState: ActiveState;
|
||||||
setModalState: (state: ActiveState) => void;
|
setModalState: (state: ActiveState) => void;
|
||||||
type: 'ADD' | 'EDIT';
|
type: 'ADD' | 'EDIT';
|
||||||
@@ -181,6 +193,25 @@ export default function PromptsModal({
|
|||||||
handleAddPrompt?: () => void;
|
handleAddPrompt?: () => void;
|
||||||
handleEditPrompt?: (id: string, type: string) => void;
|
handleEditPrompt?: (id: string, type: string) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const [disableSave, setDisableSave] = React.useState(true);
|
||||||
|
const handlePrompNameChange = (edit: boolean, newName: string) => {
|
||||||
|
const nameExists = existingPrompts.find(
|
||||||
|
(prompt) => newName === prompt.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newName && !nameExists) {
|
||||||
|
setDisableSave(false);
|
||||||
|
} else {
|
||||||
|
setDisableSave(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edit) {
|
||||||
|
setEditPromptName(newName);
|
||||||
|
} else {
|
||||||
|
setNewPromptName(newName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let view;
|
let view;
|
||||||
|
|
||||||
if (type === 'ADD') {
|
if (type === 'ADD') {
|
||||||
@@ -189,9 +220,10 @@ export default function PromptsModal({
|
|||||||
setModalState={setModalState}
|
setModalState={setModalState}
|
||||||
handleAddPrompt={handleAddPrompt}
|
handleAddPrompt={handleAddPrompt}
|
||||||
newPromptName={newPromptName}
|
newPromptName={newPromptName}
|
||||||
setNewPromptName={setNewPromptName}
|
setNewPromptName={handlePrompNameChange.bind(null, false)}
|
||||||
newPromptContent={newPromptContent}
|
newPromptContent={newPromptContent}
|
||||||
setNewPromptContent={setNewPromptContent}
|
setNewPromptContent={setNewPromptContent}
|
||||||
|
disableSave={disableSave}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (type === 'EDIT') {
|
} else if (type === 'EDIT') {
|
||||||
@@ -200,10 +232,11 @@ export default function PromptsModal({
|
|||||||
setModalState={setModalState}
|
setModalState={setModalState}
|
||||||
handleEditPrompt={handleEditPrompt}
|
handleEditPrompt={handleEditPrompt}
|
||||||
editPromptName={editPromptName}
|
editPromptName={editPromptName}
|
||||||
setEditPromptName={setEditPromptName}
|
setEditPromptName={handlePrompNameChange.bind(null, true)}
|
||||||
editPromptContent={editPromptContent}
|
editPromptContent={editPromptContent}
|
||||||
setEditPromptContent={setEditPromptContent}
|
setEditPromptContent={setEditPromptContent}
|
||||||
currentPromptEdit={currentPromptEdit}
|
currentPromptEdit={currentPromptEdit}
|
||||||
|
disableSave={disableSave}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ export default function Prompts({
|
|||||||
}
|
}
|
||||||
setModalState('INACTIVE');
|
setModalState('INACTIVE');
|
||||||
onSelectPrompt(newPromptName, newPrompt.id, newPromptContent);
|
onSelectPrompt(newPromptName, newPrompt.id, newPromptContent);
|
||||||
setNewPromptName(newPromptName);
|
setNewPromptName('');
|
||||||
|
setNewPromptContent('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
@@ -178,6 +179,7 @@ export default function Prompts({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PromptsModal
|
<PromptsModal
|
||||||
|
existingPrompts={prompts}
|
||||||
type={modalType}
|
type={modalType}
|
||||||
modalState={modalState}
|
modalState={modalState}
|
||||||
setModalState={setModalState}
|
setModalState={setModalState}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function Upload({
|
|||||||
<div className="relative w-32 h-32 rounded-full">
|
<div className="relative w-32 h-32 rounded-full">
|
||||||
<div className="absolute inset-0 rounded-full shadow-[0_0_10px_2px_rgba(0,0,0,0.3)_inset] dark:shadow-[0_0_10px_2px_rgba(0,0,0,0.3)_inset]"></div>
|
<div className="absolute inset-0 rounded-full shadow-[0_0_10px_2px_rgba(0,0,0,0.3)_inset] dark:shadow-[0_0_10px_2px_rgba(0,0,0,0.3)_inset]"></div>
|
||||||
<div
|
<div
|
||||||
className={`absolute inset-0 rounded-full ${progressPercent === 100 ? 'shadow-xl shadow-lime-300/50 dark:shadow-lime-300/50 bg-gradient-to-r from-white to-gray-400 dark:bg-gradient-to-br dark:from-gray-500 dark:to-gray-300' : 'shadow-[0_2px_0_#FF3D00_inset] dark:shadow-[0_2px_0_#FF3D00_inset]'}`}
|
className={`absolute inset-0 rounded-full ${progressPercent === 100 ? 'shadow-xl shadow-lime-300/50 dark:shadow-lime-300/50 bg-gradient-to-r from-white to-gray-400 dark:bg-gradient-to-br dark:from-gray-500 dark:to-gray-300' : 'shadow-[0_4px_0_#7D54D1] dark:shadow-[0_4px_0_#7D54D1]'}`}
|
||||||
style={{
|
style={{
|
||||||
animation: `${progressPercent === 100 ? 'none' : 'rotate 2s linear infinite'}`,
|
animation: `${progressPercent === 100 ? 'none' : 'rotate 2s linear infinite'}`,
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in new issue
Block a user