diff --git a/src/interface/web/app/components/loading/loading.tsx b/src/interface/web/app/components/loading/loading.tsx
index 30761f9a..1e3ebf49 100644
--- a/src/interface/web/app/components/loading/loading.tsx
+++ b/src/interface/web/app/components/loading/loading.tsx
@@ -1,4 +1,9 @@
+import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
import { CircleNotch } from "@phosphor-icons/react";
+import { AppSidebar } from "../appSidebar/appSidebar";
+import { Separator } from "@/components/ui/separator";
+import { useIsMobileWidth } from "@/app/common/utils";
+import { KhojLogoType } from "../logo/khojLogo";
interface LoadingProps {
className?: string;
@@ -7,21 +12,39 @@ interface LoadingProps {
}
export default function Loading(props: LoadingProps) {
+ const isMobileWidth = useIsMobileWidth();
+
return (
// NOTE: We can display usage tips here for casual learning moments.
-
-
- {props.message || "Loading"}{" "}
-
-
-
+
+
+
+
+
+
+ {isMobileWidth ? (
+
+
+
+ ) : (
+ Ask Anything
+ )}
+
+
+
+
+ {props.message || "Loading"}{" "}
+
+
+
+
-
+
);
}
diff --git a/src/interface/web/app/components/mermaid/mermaid.tsx b/src/interface/web/app/components/mermaid/mermaid.tsx
index 193d9d81..14c71d99 100644
--- a/src/interface/web/app/components/mermaid/mermaid.tsx
+++ b/src/interface/web/app/components/mermaid/mermaid.tsx
@@ -1,6 +1,7 @@
import React, { useEffect, useState, useRef } from "react";
import mermaid from "mermaid";
-import { Info } from "@phosphor-icons/react";
+import { Download, Info } from "@phosphor-icons/react";
+import { Button } from "@/components/ui/button";
interface MermaidProps {
chart: string;
@@ -41,8 +42,71 @@ const Mermaid: React.FC
= ({ chart }) => {
mermaid.contentLoaded();
}, []);
+ const handleExport = async () => {
+ if (!elementRef.current) return;
+
+ try {
+ // Get SVG element
+ const svgElement = elementRef.current.querySelector("svg");
+ if (!svgElement) throw new Error("No SVG found");
+
+ // Get SVG viewBox dimensions
+ const viewBox = svgElement.getAttribute("viewBox")?.split(" ").map(Number) || [
+ 0, 0, 0, 0,
+ ];
+ const [, , viewBoxWidth, viewBoxHeight] = viewBox;
+
+ // Create canvas with viewBox dimensions
+ const canvas = document.createElement("canvas");
+ const scale = 2; // For better resolution
+ canvas.width = viewBoxWidth * scale;
+ canvas.height = viewBoxHeight * scale;
+ const ctx = canvas.getContext("2d");
+ if (!ctx) throw new Error("Failed to get canvas context");
+
+ // Convert SVG to data URL
+ const svgData = new XMLSerializer().serializeToString(svgElement);
+ const svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
+ const svgUrl = URL.createObjectURL(svgBlob);
+
+ // Create and load image
+ const img = new Image();
+ img.src = svgUrl;
+
+ await new Promise((resolve, reject) => {
+ img.onload = () => {
+ // Scale context for better resolution
+ ctx.scale(scale, scale);
+ ctx.drawImage(img, 0, 0, viewBoxWidth, viewBoxHeight);
+
+ canvas.toBlob((blob) => {
+ if (!blob) {
+ reject(new Error("Failed to create blob"));
+ return;
+ }
+
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `mermaid-diagram-${Date.now()}.png`;
+ a.click();
+
+ // Cleanup
+ URL.revokeObjectURL(url);
+ URL.revokeObjectURL(svgUrl);
+ resolve(true);
+ }, "image/png");
+ };
+
+ img.onerror = () => reject(new Error("Failed to load SVG"));
+ });
+ } catch (error) {
+ console.error("Error exporting diagram:", error);
+ setMermaidError("Failed to export diagram");
+ }
+ };
+
useEffect(() => {
- console.log("Rendering mermaid chart:", chart);
if (elementRef.current) {
elementRef.current.removeAttribute("data-processed");
@@ -79,6 +143,12 @@ const Mermaid: React.FC = ({ chart }) => {
{chart}
)}
+ {!mermaidError && (
+
+ )}
);
};