Files
pmomusic/pmoapp/web/src/Logs.tsx

66 lines
1.7 KiB
TypeScript

// Logs.tsx
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
export type LogEntry = {
id: string;
level: "info" | "warn" | "error" | "debug";
message: string;
};
type LogsProps = {
logs: LogEntry[];
theme: "light" | "dark";
};
export function Logs({ logs }: LogsProps) {
const levelClass = (level: LogEntry["level"]) => {
switch (level) {
case "info":
return "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200";
case "warn":
return "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200";
case "error":
return "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200";
case "debug":
return "bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200";
default:
return "bg-gray-100 dark:bg-gray-800";
}
};
const decodeMessage = (msg: string) => {
const txt = document.createElement("textarea");
txt.innerHTML = msg;
return txt.value;
};
return (
<div className="p-4 space-y-2">
{logs.map((log) => (
<div
key={log.id}
className={`rounded-lg shadow p-3 ${levelClass(log.level)}`}
>
<ReactMarkdown
rehypePlugins={[rehypeRaw]}
children={decodeMessage(log.message)}
components={{
code({ className, children, ...props }) {
return (
<code
className={`bg-black/20 px-1 py-0.5 rounded ${className || ""}`}
{...props}
>
{children}
</code>
);
},
}}
/>
</div>
))}
</div>
);
}