mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: better errors feedback
This commit is contained in:
parent
af7d5edd80
commit
854c7dd415
5 changed files with 118 additions and 35 deletions
|
|
@ -5,12 +5,18 @@ export const AIChatBotContext = createContext(null) as any;
|
||||||
export const AIChatBotDispatchContext = createContext(null) as any;
|
export const AIChatBotDispatchContext = createContext(null) as any;
|
||||||
|
|
||||||
export type AIChatBotStateTypes = {
|
export type AIChatBotStateTypes = {
|
||||||
|
|
||||||
messages: AIMessage[],
|
messages: AIMessage[],
|
||||||
isModalOpen: boolean,
|
isModalOpen: boolean,
|
||||||
aichat_uuid: string,
|
aichat_uuid: string,
|
||||||
isWaitingForResponse: boolean,
|
isWaitingForResponse: boolean,
|
||||||
chatInputValue: string
|
chatInputValue: string
|
||||||
|
error: AIError
|
||||||
|
}
|
||||||
|
|
||||||
|
type AIError = {
|
||||||
|
isError: boolean
|
||||||
|
status: number
|
||||||
|
error_message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function AIChatBotProvider({ children }: { children: React.ReactNode }) {
|
function AIChatBotProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
|
@ -20,7 +26,8 @@ function AIChatBotProvider({ children }: { children: React.ReactNode }) {
|
||||||
isModalOpen: false,
|
isModalOpen: false,
|
||||||
aichat_uuid: null,
|
aichat_uuid: null,
|
||||||
isWaitingForResponse: false,
|
isWaitingForResponse: false,
|
||||||
chatInputValue: ''
|
chatInputValue: '',
|
||||||
|
error: { isError: false, status: 0, error_message: ' ' } as AIError
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -60,6 +67,8 @@ function aiChatBotReducer(state: any, action: any) {
|
||||||
return { ...state, isWaitingForResponse: false };
|
return { ...state, isWaitingForResponse: false };
|
||||||
case 'setChatInputValue':
|
case 'setChatInputValue':
|
||||||
return { ...state, chatInputValue: action.payload };
|
return { ...state, chatInputValue: action.payload };
|
||||||
|
case 'setError':
|
||||||
|
return { ...state, error: action.payload };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled action type: ${action.type}`)
|
throw new Error(`Unhandled action type: ${action.type}`)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,13 @@ export type AIEditorStateTypes = {
|
||||||
chatInputValue: string,
|
chatInputValue: string,
|
||||||
selectedTool: 'Writer' | 'ContinueWriting' | 'MakeLonger' | 'GenerateQuiz' | 'Translate'
|
selectedTool: 'Writer' | 'ContinueWriting' | 'MakeLonger' | 'GenerateQuiz' | 'Translate'
|
||||||
isUserInputEnabled: boolean
|
isUserInputEnabled: boolean
|
||||||
|
error: AIError
|
||||||
|
}
|
||||||
|
|
||||||
|
type AIError = {
|
||||||
|
isError: boolean
|
||||||
|
status: number
|
||||||
|
error_message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function AIEditorProvider({ children }: { children: React.ReactNode }) {
|
function AIEditorProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
|
@ -26,7 +33,8 @@ function AIEditorProvider({ children }: { children: React.ReactNode }) {
|
||||||
isWaitingForResponse: false,
|
isWaitingForResponse: false,
|
||||||
chatInputValue: '',
|
chatInputValue: '',
|
||||||
selectedTool: 'Writer',
|
selectedTool: 'Writer',
|
||||||
isUserInputEnabled: true
|
isUserInputEnabled: true,
|
||||||
|
error: { isError: false, status: 0, error_message: ' ' } as AIError
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -74,6 +82,8 @@ function aIEditorReducer(state: any, action: any) {
|
||||||
return { ...state, isFeedbackModalOpen: false };
|
return { ...state, isFeedbackModalOpen: false };
|
||||||
case 'setIsUserInputEnabled':
|
case 'setIsUserInputEnabled':
|
||||||
return { ...state, isUserInputEnabled: action.payload };
|
return { ...state, isUserInputEnabled: action.payload };
|
||||||
|
case 'setError':
|
||||||
|
return { ...state, error: action.payload };
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useSession } from '@components/Contexts/SessionContext'
|
import { useSession } from '@components/Contexts/SessionContext'
|
||||||
import { sendActivityAIChatMessage, startActivityAIChatSession } from '@services/ai/ai';
|
import { sendActivityAIChatMessage, startActivityAIChatSession } from '@services/ai/ai';
|
||||||
import { BadgeInfo, NotebookTabs } from 'lucide-react';
|
import { AlertTriangle, BadgeInfo, NotebookTabs } from 'lucide-react';
|
||||||
import Avvvatars from 'avvvatars-react';
|
import Avvvatars from 'avvvatars-react';
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { FlaskConical, Keyboard, MessageCircle, MessageSquareIcon, Sparkle, Sparkles, X } from 'lucide-react'
|
import { FlaskConical, Keyboard, MessageCircle, MessageSquareIcon, Sparkle, Sparkles, X } from 'lucide-react'
|
||||||
|
|
@ -101,18 +101,30 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
|
||||||
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
||||||
await dispatchAIChatBot({ type: 'setIsWaitingForResponse' });
|
await dispatchAIChatBot({ type: 'setIsWaitingForResponse' });
|
||||||
const response = await sendActivityAIChatMessage(message, aiChatBotState.aichat_uuid, props.activity.activity_uuid)
|
const response = await sendActivityAIChatMessage(message, aiChatBotState.aichat_uuid, props.activity.activity_uuid)
|
||||||
|
if (response.success == false) {
|
||||||
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' });
|
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
await dispatchAIChatBot({ type: 'setChatInputValue', payload: '' });
|
await dispatchAIChatBot({ type: 'setChatInputValue', payload: '' });
|
||||||
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'ai', message: response.message, type: 'ai' } });
|
await dispatchAIChatBot({ type: 'setError', payload: { isError: true, status: response.status, error_message: response.data.detail } });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
|
await dispatchAIChatBot({ type: 'setChatInputValue', payload: '' });
|
||||||
|
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'ai', message: response.data.message, type: 'ai' } });
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
||||||
await dispatchAIChatBot({ type: 'setIsWaitingForResponse' });
|
await dispatchAIChatBot({ type: 'setIsWaitingForResponse' });
|
||||||
const response = await startActivityAIChatSession(message, props.activity.activity_uuid)
|
const response = await startActivityAIChatSession(message, props.activity.activity_uuid)
|
||||||
await dispatchAIChatBot({ type: 'setAichat_uuid', payload: response.aichat_uuid });
|
if (response.success == false) {
|
||||||
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' });
|
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
await dispatchAIChatBot({ type: 'setChatInputValue', payload: '' });
|
await dispatchAIChatBot({ type: 'setChatInputValue', payload: '' });
|
||||||
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'ai', message: response.message, type: 'ai' } });
|
await dispatchAIChatBot({ type: 'setError', payload: { isError: true, status: response.status, error_message: response.data.detail } });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await dispatchAIChatBot({ type: 'setAichat_uuid', payload: response.data.aichat_uuid });
|
||||||
|
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
|
await dispatchAIChatBot({ type: 'setChatInputValue', payload: '' });
|
||||||
|
await dispatchAIChatBot({ type: 'addMessage', payload: { sender: 'ai', message: response.data.message, type: 'ai' } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,7 +177,7 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className={`w-100 h-0.5 bg-white/5 rounded-full mx-auto mb-3 ${aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''}`}></div>
|
<div className={`w-100 h-0.5 bg-white/5 rounded-full mx-auto mb-3 ${aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''}`}></div>
|
||||||
{aiChatBotState.messages.length > 0 ? (
|
{aiChatBotState.messages.length > 0 && !aiChatBotState.error.isError ? (
|
||||||
<div className='flex-col h-[237px] w-full space-y-4 overflow-scroll scrollbar-w-2 scrollbar scrollbar-thumb-white/20 scrollbar-thumb-rounded-full scrollbar-track-rounded-full'>
|
<div className='flex-col h-[237px] w-full space-y-4 overflow-scroll scrollbar-w-2 scrollbar scrollbar-thumb-white/20 scrollbar-thumb-rounded-full scrollbar-track-rounded-full'>
|
||||||
{aiChatBotState.messages.map((message: AIMessage, index: number) => {
|
{aiChatBotState.messages.map((message: AIMessage, index: number) => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -177,6 +189,19 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
|
||||||
) : (
|
) : (
|
||||||
<AIMessagePlaceHolder sendMessage={sendMessage} activity_uuid={props.activity.activity_uuid} />
|
<AIMessagePlaceHolder sendMessage={sendMessage} activity_uuid={props.activity.activity_uuid} />
|
||||||
)}
|
)}
|
||||||
|
{aiChatBotState.error.isError && (
|
||||||
|
<div className='flex items-center h-[237px]'>
|
||||||
|
<div className='flex flex-col mx-auto w-[600px] space-y-2 p-5 rounded-lg bg-red-500/20 outline outline-1 outline-red-500'>
|
||||||
|
<AlertTriangle size={20} className='text-red-500' />
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
<h3 className='font-semibold text-red-200'>Something wrong happened</h3>
|
||||||
|
<span className='text-red-100 text-sm '>{aiChatBotState.error.error_message}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
<div className='flex space-x-2 items-center'>
|
<div className='flex space-x-2 items-center'>
|
||||||
<div className=''>
|
<div className=''>
|
||||||
<Avvvatars radius={3} border borderColor='white' borderSize={3} size={35} value={session.user.user_uuid} style="shape" />
|
<Avvvatars radius={3} border borderColor='white' borderSize={3} size={35} value={session.user.user_uuid} style="shape" />
|
||||||
|
|
@ -235,10 +260,11 @@ function AIMessage(props: AIMessageProps) {
|
||||||
|
|
||||||
const AIMessagePlaceHolder = (props: { activity_uuid: string, sendMessage: any }) => {
|
const AIMessagePlaceHolder = (props: { activity_uuid: string, sendMessage: any }) => {
|
||||||
const session = useSession() as any;
|
const session = useSession() as any;
|
||||||
|
|
||||||
const [feedbackModal, setFeedbackModal] = React.useState(false);
|
const [feedbackModal, setFeedbackModal] = React.useState(false);
|
||||||
return (
|
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes;
|
||||||
<div className='flex-col h-[237px] w-full'>
|
|
||||||
|
if (!aiChatBotState.error.isError) {
|
||||||
|
return <div className='flex-col h-[237px] w-full'>
|
||||||
<div className='flex flex-col text-center justify-center pt-12'>
|
<div className='flex flex-col text-center justify-center pt-12'>
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ y: 20, opacity: 0, filter: 'blur(5px)' }}
|
initial={{ y: 20, opacity: 0, filter: 'blur(5px)' }}
|
||||||
|
|
@ -271,7 +297,7 @@ const AIMessagePlaceHolder = (props: { activity_uuid: string, sendMessage: any }
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AIChatPredefinedQuestion = (props: { sendMessage: any, label: string }) => {
|
const AIChatPredefinedQuestion = (props: { sendMessage: any, label: string }) => {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||||
import learnhouseAI_icon from "public/learnhouse_ai_simple.png";
|
import learnhouseAI_icon from "public/learnhouse_ai_simple.png";
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { BetweenHorizontalStart, FastForward, Feather, FileStack, HelpCircle, Languages, MessageCircle, MoreVertical, Pen, X } from 'lucide-react';
|
import { AlertTriangle, BetweenHorizontalStart, FastForward, Feather, FileStack, HelpCircle, Languages, MessageCircle, MoreVertical, Pen, X } from 'lucide-react';
|
||||||
import { Editor } from '@tiptap/react';
|
import { Editor } from '@tiptap/react';
|
||||||
import { AIChatBotStateTypes, useAIChatBot, useAIChatBotDispatch } from '@components/Contexts/AI/AIChatBotContext';
|
import { AIChatBotStateTypes, useAIChatBot, useAIChatBotDispatch } from '@components/Contexts/AI/AIChatBotContext';
|
||||||
import { AIEditorStateTypes, useAIEditor, useAIEditorDispatch } from '@components/Contexts/AI/AIEditorContext';
|
import { AIEditorStateTypes, useAIEditor, useAIEditorDispatch } from '@components/Contexts/AI/AIEditorContext';
|
||||||
|
|
@ -96,20 +96,38 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
|
||||||
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
||||||
await dispatchAIEditor({ type: 'setIsWaitingForResponse' });
|
await dispatchAIEditor({ type: 'setIsWaitingForResponse' });
|
||||||
const response = await sendActivityAIChatMessage(message, aiEditorState.aichat_uuid, props.activity.activity_uuid)
|
const response = await sendActivityAIChatMessage(message, aiEditorState.aichat_uuid, props.activity.activity_uuid)
|
||||||
|
if (response.success === false) {
|
||||||
|
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
|
await dispatchAIEditor({ type: 'setIsModalClose' });
|
||||||
|
// wait for 200ms before opening the modal again
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
await dispatchAIEditor({ type: 'setError', payload: { isError: true, status: response.status, error_message: response.data.detail } });
|
||||||
|
await dispatchAIEditor({ type: 'setIsModalOpen' });
|
||||||
|
return '';
|
||||||
|
}
|
||||||
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
await dispatchAIEditor({ type: 'setChatInputValue', payload: '' });
|
await dispatchAIEditor({ type: 'setChatInputValue', payload: '' });
|
||||||
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'ai', message: response.message, type: 'ai' } });
|
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'ai', message: response.data.message, type: 'ai' } });
|
||||||
return response.message;
|
return response.data.message;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'user', message: message, type: 'user' } });
|
||||||
await dispatchAIEditor({ type: 'setIsWaitingForResponse' });
|
await dispatchAIEditor({ type: 'setIsWaitingForResponse' });
|
||||||
const response = await startActivityAIChatSession(message, props.activity.activity_uuid)
|
const response = await startActivityAIChatSession(message, props.activity.activity_uuid)
|
||||||
await dispatchAIEditor({ type: 'setAichat_uuid', payload: response.aichat_uuid });
|
if (response.success === false) {
|
||||||
|
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
|
await dispatchAIEditor({ type: 'setIsModalClose' });
|
||||||
|
// wait for 200ms before opening the modal again
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
await dispatchAIEditor({ type: 'setError', payload: { isError: true, status: response.status, error_message: response.data.detail } });
|
||||||
|
await dispatchAIEditor({ type: 'setIsModalOpen' });
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
await dispatchAIEditor({ type: 'setAichat_uuid', payload: response.data.aichat_uuid });
|
||||||
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
await dispatchAIEditor({ type: 'setChatInputValue', payload: '' });
|
await dispatchAIEditor({ type: 'setChatInputValue', payload: '' });
|
||||||
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'ai', message: response.message, type: 'ai' } });
|
await dispatchAIEditor({ type: 'addMessage', payload: { sender: 'ai', message: response.data.message, type: 'ai' } });
|
||||||
return response.message;
|
return response.data.message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,10 +176,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
|
||||||
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' });
|
||||||
}
|
}
|
||||||
} else if (label === 'GenerateQuiz') {
|
} else if (label === 'GenerateQuiz') {
|
||||||
// Send message to AI
|
// will be implemented in future stages
|
||||||
// Wait for response
|
|
||||||
// Add response to editor
|
|
||||||
// Close modal
|
|
||||||
} else if (label === 'Translate') {
|
} else if (label === 'Translate') {
|
||||||
let ai_message = '';
|
let ai_message = '';
|
||||||
let text_selection = getTipTapEditorSelectedText();
|
let text_selection = getTipTapEditorSelectedText();
|
||||||
|
|
@ -211,6 +226,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
|
||||||
|
|
||||||
// Wait for 0.3 seconds before adding the next word
|
// Wait for 0.3 seconds before adding the next word
|
||||||
await new Promise(resolve => setTimeout(resolve, 120));
|
await new Promise(resolve => setTimeout(resolve, 120));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,7 +329,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
|
||||||
<AiEditorActionScreen handleOperation={handleOperation} />
|
<AiEditorActionScreen handleOperation={handleOperation} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{aiEditorState.isUserInputEnabled && <div className="flex items-center space-x-2 cursor-pointer">
|
{aiEditorState.isUserInputEnabled && !aiEditorState.error.isError && <div className="flex items-center space-x-2 cursor-pointer">
|
||||||
<input onKeyDown={handleKeyPress} value={aiEditorState.chatInputValue} onChange={handleChange} placeholder='Ask AI' className='ring-1 ring-inset ring-white/20 w-full bg-gray-950/20 rounded-lg outline-none px-4 py-2 text-white text-sm placeholder:text-white/30'></input>
|
<input onKeyDown={handleKeyPress} value={aiEditorState.chatInputValue} onChange={handleChange} placeholder='Ask AI' className='ring-1 ring-inset ring-white/20 w-full bg-gray-950/20 rounded-lg outline-none px-4 py-2 text-white text-sm placeholder:text-white/30'></input>
|
||||||
<div className='bg-white/10 px-3 rounded-md outline outline-1 outline-neutral-200/20 py-2 hover:bg-white/20 hover:outline-neutral-200/40 delay-75 ease-linear transition-all'>
|
<div className='bg-white/10 px-3 rounded-md outline outline-1 outline-neutral-200/20 py-2 hover:bg-white/20 hover:outline-neutral-200/40 delay-75 ease-linear transition-all'>
|
||||||
<BetweenHorizontalStart size={20} className='text-white/50 hover:cursor-pointer' />
|
<BetweenHorizontalStart size={20} className='text-white/50 hover:cursor-pointer' />
|
||||||
|
|
@ -379,11 +395,11 @@ const AiEditorActionScreen = ({ handleOperation }: { handleOperation: any }) =>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{aiEditorState.selectedTool === 'Writer' && !aiEditorState.isWaitingForResponse &&
|
{aiEditorState.selectedTool === 'Writer' && !aiEditorState.isWaitingForResponse && !aiEditorState.error.isError &&
|
||||||
<div className='text-xl text-white/90 font-extrabold space-x-2'>
|
<div className='text-xl text-white/90 font-extrabold space-x-2'>
|
||||||
<span>Write about...</span>
|
<span>Write about...</span>
|
||||||
</div>}
|
</div>}
|
||||||
{aiEditorState.selectedTool === 'ContinueWriting' && !aiEditorState.isWaitingForResponse &&
|
{aiEditorState.selectedTool === 'ContinueWriting' && !aiEditorState.isWaitingForResponse && !aiEditorState.error.isError &&
|
||||||
<div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
<div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
||||||
<p className='mx-auto flex p-2 text-white/80 mt-4 font-bold justify-center text-sm align-middle'>Place your cursor at the end of a sentence to continue writing </p>
|
<p className='mx-auto flex p-2 text-white/80 mt-4 font-bold justify-center text-sm align-middle'>Place your cursor at the end of a sentence to continue writing </p>
|
||||||
<div onClick={() => {
|
<div onClick={() => {
|
||||||
|
|
@ -393,7 +409,7 @@ const AiEditorActionScreen = ({ handleOperation }: { handleOperation: any }) =>
|
||||||
<FastForward size={24} />
|
<FastForward size={24} />
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
{aiEditorState.selectedTool === 'MakeLonger' && !aiEditorState.isWaitingForResponse &&
|
{aiEditorState.selectedTool === 'MakeLonger' && !aiEditorState.isWaitingForResponse && !aiEditorState.error.isError &&
|
||||||
<div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
<div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
||||||
<p className='mx-auto flex p-2 text-white/80 mt-4 font-bold justify-center text-sm align-middle'>Select text to make longer </p>
|
<p className='mx-auto flex p-2 text-white/80 mt-4 font-bold justify-center text-sm align-middle'>Select text to make longer </p>
|
||||||
<div onClick={() => {
|
<div onClick={() => {
|
||||||
|
|
@ -403,7 +419,7 @@ const AiEditorActionScreen = ({ handleOperation }: { handleOperation: any }) =>
|
||||||
<FileStack size={24} />
|
<FileStack size={24} />
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
{aiEditorState.selectedTool === 'Translate' && !aiEditorState.isWaitingForResponse &&
|
{aiEditorState.selectedTool === 'Translate' && !aiEditorState.isWaitingForResponse && !aiEditorState.error.isError &&
|
||||||
<div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
<div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
||||||
<div className='mx-auto flex p-2 text-white/80 mt-4 font-bold justify-center text-sm align-middle space-x-6'>
|
<div className='mx-auto flex p-2 text-white/80 mt-4 font-bold justify-center text-sm align-middle space-x-6'>
|
||||||
<p>Translate selected text to </p>
|
<p>Translate selected text to </p>
|
||||||
|
|
@ -416,8 +432,7 @@ const AiEditorActionScreen = ({ handleOperation }: { handleOperation: any }) =>
|
||||||
<Languages size={24} />
|
<Languages size={24} />
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
{aiEditorState.isWaitingForResponse && <div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
{aiEditorState.isWaitingForResponse && !aiEditorState.error.isError && <div className='flex flex-col mx-auto justify-center align-middle items-center'>
|
||||||
|
|
||||||
<svg className="animate-spin mt-10 h-10 w-10 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<svg className="animate-spin mt-10 h-10 w-10 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
|
@ -425,6 +440,20 @@ const AiEditorActionScreen = ({ handleOperation }: { handleOperation: any }) =>
|
||||||
<p className='font-bold mt-4 text-white/90'>Thinking...</p>
|
<p className='font-bold mt-4 text-white/90'>Thinking...</p>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
|
{aiEditorState.error.isError && (
|
||||||
|
<div className='flex items-center h-auto pt-7'>
|
||||||
|
<div className='flex flex-col mx-auto w-full space-y-2 p-5 rounded-lg bg-red-500/20 outline outline-1 outline-red-500'>
|
||||||
|
<AlertTriangle size={20} className='text-red-500' />
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
<h3 className='font-semibold text-red-200'>Something wrong happened</h3>
|
||||||
|
<span className='text-red-100 text-sm '>{aiEditorState.error.error_message}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,12 @@ export async function startActivityAIChatSession(message: string, activity_uuid:
|
||||||
activity_uuid,
|
activity_uuid,
|
||||||
};
|
};
|
||||||
const result = await fetch(`${getAPIUrl()}ai/start/activity_chat_session`, RequestBody("POST", data, null));
|
const result = await fetch(`${getAPIUrl()}ai/start/activity_chat_session`, RequestBody("POST", data, null));
|
||||||
const res = await result.json();
|
const json = await result.json();
|
||||||
return res;
|
if (result.status === 200) {
|
||||||
|
return { success: true, data: json, status: result.status, HTTPmessage: result.statusText };
|
||||||
|
} else {
|
||||||
|
return { success: false, data: json, status: result.status, HTTPmessage: result.statusText };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sendActivityAIChatMessage(message: string, aichat_uuid: string, activity_uuid: string) {
|
export async function sendActivityAIChatMessage(message: string, aichat_uuid: string, activity_uuid: string) {
|
||||||
|
|
@ -18,6 +22,11 @@ export async function sendActivityAIChatMessage(message: string, aichat_uuid: st
|
||||||
activity_uuid,
|
activity_uuid,
|
||||||
};
|
};
|
||||||
const result = await fetch(`${getAPIUrl()}ai/send/activity_chat_message`, RequestBody("POST", data, null));
|
const result = await fetch(`${getAPIUrl()}ai/send/activity_chat_message`, RequestBody("POST", data, null));
|
||||||
const res = await result.json();
|
|
||||||
return res;
|
const json = await result.json();
|
||||||
|
if (result.status === 200) {
|
||||||
|
return { success: true, data: json, status: result.status, HTTPmessage: result.statusText };
|
||||||
|
} else {
|
||||||
|
return { success: false, data: json, status: result.status, HTTPmessage: result.statusText };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue