Spaces:
Running
Running
Pulastya B
commited on
Commit
·
49fbcb2
1
Parent(s):
fad6660
feat: Add inline plot viewing in chat
Browse files- Add plots array to Message interface
- Extract plots from API response (result.plots)
- Render View Plot buttons similar to View Report
- Display plot count and individual view buttons
- Use emerald theme for plot buttons vs indigo for reports
- Opens plots in modal for full-screen viewing
FRRONTEEEND/components/ChatInterface.tsx
CHANGED
|
@@ -19,6 +19,11 @@ interface Message {
|
|
| 19 |
name: string;
|
| 20 |
path: string;
|
| 21 |
}>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
}
|
| 23 |
|
| 24 |
interface ChatSession {
|
|
@@ -133,12 +138,22 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
|
|
| 133 |
|
| 134 |
let assistantContent = '';
|
| 135 |
let reports: Array<{name: string, path: string}> = [];
|
|
|
|
| 136 |
|
| 137 |
// Check for reports in any /run endpoint response (not just when file is uploaded)
|
| 138 |
if (data.result) {
|
| 139 |
const result = data.result;
|
| 140 |
assistantContent = `✅ Analysis Complete!\n\n`;
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
// Extract report paths from workflow history
|
| 143 |
if (result.workflow_history) {
|
| 144 |
const reportTools = ['generate_ydata_profiling_report', 'generate_plotly_dashboard', 'generate_all_plots'];
|
|
@@ -187,7 +202,8 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
|
|
| 187 |
role: 'assistant',
|
| 188 |
content: assistantContent,
|
| 189 |
timestamp: new Date(),
|
| 190 |
-
reports: reports.length > 0 ? reports : undefined
|
|
|
|
| 191 |
}]);
|
| 192 |
} catch (error: any) {
|
| 193 |
console.error("Chat Error:", error);
|
|
@@ -456,6 +472,27 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
|
|
| 456 |
})}
|
| 457 |
</div>
|
| 458 |
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 459 |
<div className="mt-2 text-[10px] opacity-20 font-mono">
|
| 460 |
{msg.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
| 461 |
</div>
|
|
|
|
| 19 |
name: string;
|
| 20 |
path: string;
|
| 21 |
}>;
|
| 22 |
+
plots?: Array<{
|
| 23 |
+
title: string;
|
| 24 |
+
url: string;
|
| 25 |
+
type?: 'image' | 'html';
|
| 26 |
+
}>;
|
| 27 |
}
|
| 28 |
|
| 29 |
interface ChatSession {
|
|
|
|
| 138 |
|
| 139 |
let assistantContent = '';
|
| 140 |
let reports: Array<{name: string, path: string}> = [];
|
| 141 |
+
let plots: Array<{title: string, url: string, type?: 'image' | 'html'}> = [];
|
| 142 |
|
| 143 |
// Check for reports in any /run endpoint response (not just when file is uploaded)
|
| 144 |
if (data.result) {
|
| 145 |
const result = data.result;
|
| 146 |
assistantContent = `✅ Analysis Complete!\n\n`;
|
| 147 |
|
| 148 |
+
// Extract plots from result
|
| 149 |
+
if (result.plots && Array.isArray(result.plots)) {
|
| 150 |
+
plots = result.plots.map((plot: any) => ({
|
| 151 |
+
title: plot.title || 'Plot',
|
| 152 |
+
url: plot.url || plot.path?.replace('./outputs/', '/outputs/'),
|
| 153 |
+
type: (plot.url || plot.path)?.endsWith('.html') ? 'html' : 'image'
|
| 154 |
+
}));
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
// Extract report paths from workflow history
|
| 158 |
if (result.workflow_history) {
|
| 159 |
const reportTools = ['generate_ydata_profiling_report', 'generate_plotly_dashboard', 'generate_all_plots'];
|
|
|
|
| 202 |
role: 'assistant',
|
| 203 |
content: assistantContent,
|
| 204 |
timestamp: new Date(),
|
| 205 |
+
reports: reports.length > 0 ? reports : undefined,
|
| 206 |
+
plots: plots.length > 0 ? plots : undefined
|
| 207 |
}]);
|
| 208 |
} catch (error: any) {
|
| 209 |
console.error("Chat Error:", error);
|
|
|
|
| 472 |
})}
|
| 473 |
</div>
|
| 474 |
)}
|
| 475 |
+
{msg.plots && msg.plots.length > 0 && (
|
| 476 |
+
<div className="mt-4 space-y-3">
|
| 477 |
+
<div className="text-xs font-semibold text-white/60 mb-2">
|
| 478 |
+
📊 Generated Visualizations ({msg.plots.length})
|
| 479 |
+
</div>
|
| 480 |
+
<div className="flex flex-wrap gap-2">
|
| 481 |
+
{msg.plots.map((plot, idx) => (
|
| 482 |
+
<button
|
| 483 |
+
key={idx}
|
| 484 |
+
onClick={() => setReportModalUrl(`${window.location.origin}${plot.url}`)}
|
| 485 |
+
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-emerald-500/20 hover:bg-emerald-500/30 border border-emerald-500/30 text-emerald-200 text-xs font-medium transition-all group"
|
| 486 |
+
>
|
| 487 |
+
<svg className="w-3.5 h-3.5 group-hover:scale-110 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
| 488 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
| 489 |
+
</svg>
|
| 490 |
+
View {plot.title}
|
| 491 |
+
</button>
|
| 492 |
+
))}
|
| 493 |
+
</div>
|
| 494 |
+
</div>
|
| 495 |
+
)}
|
| 496 |
<div className="mt-2 text-[10px] opacity-20 font-mono">
|
| 497 |
{msg.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
| 498 |
</div>
|