Skip to content

Commit

Permalink
refactor: Enhance error handling, message editing and prompt display (#…
Browse files Browse the repository at this point in the history
…5310)

* 📝 (newChatMessage.tsx): add event listener to handle tab visibility change and update state accordingly
📝 (newChatMessage.tsx): remove event listener when component unmounts to prevent memory leaks

* ✨ (use-tab-visibility.tsx): introduce custom hook useTabVisibility to track tab visibility changes in the browser
📝 (newChatMessage.tsx, newChatView.tsx): import and use useTabVisibility hook to handle tab visibility changes and update chat behavior accordingly

* 📝 (newChatMessage.tsx): remove duplicate import of useTabVisibility and update import path
📝 (newChatView.tsx): remove duplicate import of useTabVisibility and update import path
✨ (use-tab-visibility.tsx): create a new custom hook to track tab visibility changes in the browser

* reducing to smaller components

* 📝 (frontend): remove unused imports and clean up code in various files to improve code readability and maintainability

* 📝 (editMessage/index.tsx): Rename EditMessage component to MarkdownField for better clarity and consistency
📝 (newChatMessage.tsx): Replace EditMessage component with MarkdownField component for rendering chat messages with markdown support
📝 (newChatView.tsx): Add conditional rendering to display a message when no chat messages are fetched

✨ (chatViewWrapper/index.tsx): Add messageFetched prop to ChatView component to handle messages fetching status and improve component functionality.

* prompt viedw

* Refactor chat view component and remove unused prop

* [autofix.ci] apply automated fixes

---------

Co-authored-by: anovazzi1 <otavio2204@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent 9a8f721 commit 01c1d47
Show file tree
Hide file tree
Showing 13 changed files with 703 additions and 590 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import IconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import {
Select,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { ForwardedIconComponent } from "@/components/common/genericIconComponent";
import { TextShimmer } from "@/components/ui/TextShimmer";
import { cn } from "@/utils/utils";
import { AnimatePresence, motion } from "framer-motion";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import CodeTabsComponent from "../../../../../../../components/core/codeTabsComponent/ChatCodeTabComponent";
import LogoIcon from "../chatLogoIcon";

export const ErrorView = ({
closeChat,
fitViewNode,
chat,
showError,
lastMessage,
blocks,
}: {
blocks: any;
showError: boolean;
lastMessage: boolean;
closeChat?: () => void;
fitViewNode: (id: string) => void;
chat: any;
}) => {
return (
<>
<div className="w-5/6 max-w-[768px] py-4 word-break-break-word">
<AnimatePresence mode="wait">
{!showError && lastMessage ? (
<motion.div
key="loading"
initial={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="flex w-full gap-4 rounded-md p-2"
>
<LogoIcon />
<div className="flex items-center">
<TextShimmer className="" duration={1}>
Flow running...
</TextShimmer>
</div>
</motion.div>
) : (
<motion.div
key="error"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
className="flex w-full gap-4 rounded-md p-2"
>
<LogoIcon />
{blocks.map((block, blockIndex) => (
<div
key={blockIndex}
className="w-full rounded-xl border border-error-red-border bg-error-red p-4 text-[14px] text-foreground"
>
{block.contents.map((content, contentIndex) => {
if (content.type === "error") {
return (
<div className="" key={contentIndex}>
<div className="mb-2 flex items-center">
<ForwardedIconComponent
className="mr-2 h-[18px] w-[18px] text-destructive"
name="OctagonAlert"
/>
{content.component && (
<>
<span>
An error occured in the{" "}
<span
className={cn(
closeChat ?? "cursor-pointer underline",
)}
onClick={() => {
fitViewNode(
chat.properties?.source?.id ?? "",
);
closeChat?.();
}}
>
<strong>{content.component}</strong>
</span>{" "}
Component, stopping your flow. See below for
more details.
</span>
</>
)}
</div>
<div>
<h3 className="pb-3 font-semibold">
Error details:
</h3>
{content.field && (
<p className="pb-1">Field: {content.field}</p>
)}
{content.reason && (
<span className="">
<Markdown
linkTarget="_blank"
remarkPlugins={[remarkGfm]}
components={{
a: ({ node, ...props }) => (
<a
href={props.href}
target="_blank"
className="underline"
rel="noopener noreferrer"
>
{props.children}
</a>
),
p({ node, ...props }) {
return (
<span className="inline-block w-fit max-w-full">
{props.children}
</span>
);
},
code: ({
node,
inline,
className,
children,
...props
}) => {
let content = children as string;
if (
Array.isArray(children) &&
children.length === 1 &&
typeof children[0] === "string"
) {
content = children[0] as string;
}
if (typeof content === "string") {
if (content.length) {
if (content[0] === "▍") {
return (
<span className="form-modal-markdown-span"></span>
);
}
}

const match = /language-(\w+)/.exec(
className || "",
);

return !inline ? (
<CodeTabsComponent
language={(match && match[1]) || ""}
code={String(content).replace(
/\n$/,
"",
)}
/>
) : (
<code
className={className}
{...props}
>
{content}
</code>
);
}
},
}}
>
{content.reason}
</Markdown>
</span>
)}
{content.solution && (
<div className="mt-4">
<h3 className="pb-3 font-semibold">
Steps to fix:
</h3>
<ol className="list-decimal pl-5">
<li>Check the component settings</li>
<li>Ensure all required fields are filled</li>
<li>Re-run your flow</li>
</ol>
</div>
)}
</div>
</div>
);
}
return null;
})}
</div>
))}
</motion.div>
)}
</AnimatePresence>
</div>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { cn } from "@/utils/utils";

import { EMPTY_OUTPUT_SEND_MESSAGE } from "@/constants/constants";
import Markdown from "react-markdown";
import rehypeMathjax from "rehype-mathjax";
import remarkGfm from "remark-gfm";
import CodeTabsComponent from "../../../../../../../components/core/codeTabsComponent/ChatCodeTabComponent";
import EditMessageField from "../editMessageField";

type MarkdownFieldProps = {
chat: any;
isEmpty: boolean;
chatMessage: string;
editedFlag: React.ReactNode;
};

export const MarkdownField = ({
chat,
isEmpty,
chatMessage,
editedFlag,
}: MarkdownFieldProps) => {
return (
<div className="w-full items-baseline gap-2">
<Markdown
remarkPlugins={[remarkGfm]}
linkTarget="_blank"
rehypePlugins={[rehypeMathjax]}
className={cn(
"markdown prose flex w-fit max-w-full flex-col items-baseline text-[14px] font-normal word-break-break-word dark:prose-invert",
isEmpty ? "text-muted-foreground" : "text-primary",
)}
components={{
p({ node, ...props }) {
return <span className="w-fit max-w-full">{props.children}</span>;
},
ol({ node, ...props }) {
return <ol className="max-w-full">{props.children}</ol>;
},
ul({ node, ...props }) {
return <ul className="max-w-full">{props.children}</ul>;
},
pre({ node, ...props }) {
return <>{props.children}</>;
},
code: ({ node, inline, className, children, ...props }) => {
let content = children as string;
if (
Array.isArray(children) &&
children.length === 1 &&
typeof children[0] === "string"
) {
content = children[0] as string;
}
if (typeof content === "string") {
if (content.length) {
if (content[0] === "▍") {
return <span className="form-modal-markdown-span"></span>;
}
}

const match = /language-(\w+)/.exec(className || "");

return !inline ? (
<CodeTabsComponent
language={(match && match[1]) || ""}
code={String(content).replace(/\n$/, "")}
/>
) : (
<code className={className} {...props}>
{content}
</code>
);
}
},
}}
>
{isEmpty && !chat.stream_url ? EMPTY_OUTPUT_SEND_MESSAGE : chatMessage}
</Markdown>
{editedFlag}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const convertFiles = (
files:
| (
| string
| {
path: string;
type: string;
name: string;
}
)[]
| undefined,
) => {
if (!files) return [];
return files.map((file) => {
if (typeof file === "string") {
return file;
}
return file.path;
});
};
Loading

0 comments on commit 01c1d47

Please sign in to comment.