Skip to content

Commit 6b5ece9

Browse files
committed
Display plot by default
Signed-off-by: Vineeth Kalluru <[email protected]>
1 parent 1f47016 commit 6b5ece9

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed

components/Chat/HtmlFileRenderer.tsx

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ export const HtmlFileRenderer: React.FC<HtmlFileRendererProps> = ({
1515
isInlineHtml = false,
1616
htmlContent: inlineHtmlContent
1717
}) => {
18-
const [isExpanded, setIsExpanded] = useState<boolean>(false);
18+
const [isExpanded, setIsExpanded] = useState<boolean>(true);
1919
const [htmlContent, setHtmlContent] = useState<string>(inlineHtmlContent || '');
2020
const [isLoading, setIsLoading] = useState<boolean>(false);
2121
const [error, setError] = useState<string>('');
22+
const [fileExists, setFileExists] = useState<boolean | null>(null);
2223

2324
const cleanFilePath = (path: string): string => {
2425
// For inline HTML, return a descriptive name
@@ -36,14 +37,57 @@ export const HtmlFileRenderer: React.FC<HtmlFileRendererProps> = ({
3637
return cleaned;
3738
};
3839

40+
const checkFileExists = async () => {
41+
// For inline HTML, file always "exists"
42+
if (isInlineHtml && inlineHtmlContent) {
43+
setFileExists(true);
44+
return;
45+
}
46+
47+
try {
48+
const cleanPath = cleanFilePath(filePath);
49+
console.log('Checking if HTML file exists:', cleanPath);
50+
51+
// Use a simple GET request to check if file exists
52+
// We'll abort quickly to avoid downloading large files
53+
const controller = new AbortController();
54+
const timeoutId = setTimeout(() => controller.abort(), 3000); // 3 second timeout
55+
56+
const response = await fetch(`/api/load-html-file?path=${encodeURIComponent(cleanPath)}`, {
57+
signal: controller.signal
58+
});
59+
60+
clearTimeout(timeoutId);
61+
62+
if (response.ok) {
63+
setFileExists(true);
64+
} else if (response.status === 404) {
65+
console.log(`File does not exist: ${cleanPath} (404 Not Found)`);
66+
setFileExists(false);
67+
} else {
68+
console.log(`File check failed: ${cleanPath} (${response.status})`);
69+
setFileExists(false);
70+
}
71+
} catch (err: any) {
72+
// If it's an abort error, still check - might just be slow
73+
if (err.name === 'AbortError') {
74+
console.log(`File check timed out, assuming file exists: ${filePath}`);
75+
setFileExists(true);
76+
} else {
77+
console.log(`Error checking file existence: ${err.message}`);
78+
setFileExists(false);
79+
}
80+
}
81+
};
82+
3983
const loadHtmlContent = async () => {
4084
// If it's inline HTML, content is already provided
4185
if (isInlineHtml && inlineHtmlContent) {
4286
setHtmlContent(inlineHtmlContent);
4387
return;
4488
}
4589

46-
if (isExpanded && !htmlContent && !error) {
90+
if (isExpanded && !htmlContent && !error && fileExists) {
4791
setIsLoading(true);
4892
setError('');
4993

@@ -69,10 +113,38 @@ export const HtmlFileRenderer: React.FC<HtmlFileRendererProps> = ({
69113
};
70114

71115
useEffect(() => {
72-
if (isExpanded) {
116+
// First check if file exists
117+
checkFileExists();
118+
}, [filePath, isInlineHtml, inlineHtmlContent]);
119+
120+
useEffect(() => {
121+
// Only load content if file exists and component is expanded
122+
if (isExpanded && fileExists) {
73123
loadHtmlContent();
74124
}
75-
}, [isExpanded, filePath, isInlineHtml, inlineHtmlContent]);
125+
}, [isExpanded, fileExists]);
126+
127+
// Don't render the component if file doesn't exist
128+
if (fileExists === false) {
129+
return null;
130+
}
131+
132+
// Show loading state while checking file existence
133+
if (fileExists === null) {
134+
return (
135+
<div className="my-4 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
136+
<div className="bg-gradient-to-r from-green-50 to-blue-50 dark:from-green-900/20 dark:to-blue-900/20 px-4 py-3">
137+
<div className="flex items-center gap-3">
138+
<IconFile size={20} className="text-green-600 dark:text-green-400" />
139+
<div className="animate-pulse">
140+
<div className="h-4 bg-gray-300 dark:bg-gray-600 rounded w-32 mb-2"></div>
141+
<div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-48"></div>
142+
</div>
143+
</div>
144+
</div>
145+
</div>
146+
);
147+
}
76148

77149
const openInSystemBrowser = () => {
78150
if (isInlineHtml) {
@@ -145,7 +217,7 @@ export const HtmlFileRenderer: React.FC<HtmlFileRendererProps> = ({
145217
{isInlineHtml ? 'Inline HTML' : 'HTML Plot'}
146218
</span>
147219
<span className="text-xs text-gray-500 dark:text-gray-400">
148-
{isInlineHtml ? 'HTML response content' : 'Interactive Bokeh visualization'}
220+
{isInlineHtml ? 'HTML response content' : 'Interactive visualization'}
149221
</span>
150222
</div>
151223
</div>

public/__ENV.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

utils/app/htmlFileDetector.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ export interface HtmlFileLink {
4848
/(?<!href=["']?)`?([^\s"'<>`]+\.html)`?(?!["'])/g,
4949
// File paths in backticks specifically
5050
/`([^`]+\.html)`/g,
51+
// File paths wrapped in double quotes
52+
/"([^"]+\.html)"/g,
53+
// File paths wrapped in single quotes
54+
/'([^']+\.html)'/g,
5155
];
5256

5357
patterns.forEach((pattern, patternIndex) => {
@@ -83,6 +87,24 @@ export interface HtmlFileLink {
8387
filePath = match[1];
8488
linkText = extractFilenameFromPath(filePath);
8589

90+
// Ensure file:// prefix
91+
if (!filePath.startsWith('file://')) {
92+
filePath = `file://${filePath}`;
93+
}
94+
} else if (patternIndex === 5) {
95+
// File path wrapped in double quotes
96+
filePath = match[1];
97+
linkText = extractFilenameFromPath(filePath);
98+
99+
// Ensure file:// prefix
100+
if (!filePath.startsWith('file://')) {
101+
filePath = `file://${filePath}`;
102+
}
103+
} else if (patternIndex === 6) {
104+
// File path wrapped in single quotes
105+
filePath = match[1];
106+
linkText = extractFilenameFromPath(filePath);
107+
86108
// Ensure file:// prefix
87109
if (!filePath.startsWith('file://')) {
88110
filePath = `file://${filePath}`;
@@ -193,6 +215,12 @@ export interface HtmlFileLink {
193215
// Remove HTML file paths wrapped in backticks specifically
194216
cleanContent = cleanContent.replace(/`([^`]+\.html)`/g, '');
195217

218+
// Remove HTML file paths wrapped in double quotes
219+
cleanContent = cleanContent.replace(/"([^"]+\.html)"/g, '');
220+
221+
// Remove HTML file paths wrapped in single quotes
222+
cleanContent = cleanContent.replace(/'([^']+\.html)'/g, '');
223+
196224
// Clean up extra whitespace
197225
cleanContent = cleanContent.replace(/\n\s*\n\s*\n/g, '\n\n');
198226
cleanContent = cleanContent.trim();

0 commit comments

Comments
 (0)