RS-AAAI / frontend /src /pages /ResultsPage.tsx
peihsin0715
Add example
ad9612f
import PipelineProgress from '../components/PipelineProgress';
import { useJobRunner } from '../hooks/JobRunnerProvider';
import { useMemo } from 'react';
export default function ResultsPage() {
const { result, resp, loading, error, url } = useJobRunner();
// 判斷是否為 example(從前面頁面寫入的 cfgDraft)
const isExample = useMemo(() => {
try {
const draft = localStorage.getItem('cfgDraft');
if (!draft) return false;
const parsed = JSON.parse(draft);
return parsed?.dataset === 'example';
} catch {
return false;
}
}, []);
// ---- Example 模式:不跑程式,直接顯示兩張 Plotly HTML ----
if (isExample) {
const oriHtml = 'ori_sentiment_distribution.html';
const ftHtml = 'ft_sentiment_distribution.html';
const oriCsv = 'ori_generation_results.csv';
const ftCsv = 'finetune_aug_generation_result.csv';
return (
<div className="space-y-6">
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur">
<h2 className="text-lg font-semibold mb-2">Example Preview</h2>
<p className="text-sm text-slate-600">
This is a fixed example preview. The pipeline was not executed.
</p>
</section>
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur">
<h2 className="text-lg font-semibold mb-4">Distribution</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<figure className="rounded-xl overflow-hidden border bg-white">
<iframe
src={oriHtml}
title="Original distribution (Plotly)"
className="w-full"
style={{ height: 480, border: '0' }}
/>
<figcaption className="p-3 text-sm text-slate-600">Original</figcaption>
</figure>
<figure className="rounded-xl overflow-hidden border bg-white">
<iframe
src={ftHtml}
title="Counterfactual distribution (Plotly)"
className="w-full"
style={{ height: 480, border: '0' }}
/>
<figcaption className="p-3 text-sm text-slate-600">Counterfactual Augmented</figcaption>
</figure>
</div>
</section>
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur">
<h2 className="text-lg font-semibold mb-4">Download Report</h2>
<ul className="space-y-2">
<li>
<a
className="text-indigo-600 hover:underline"
href={oriCsv}
target="_blank"
rel="noreferrer"
download
>
Original Generation CSV
</a>
</li>
<li>
<a
className="text-indigo-600 hover:underline"
href={ftCsv}
target="_blank"
rel="noreferrer"
download
>
Counterfactual / Fine-tuned Generation CSV
</a>
</li>
</ul>
</section>
</div>
);
}
// ---- 原本流程(非 example)----
// 判斷是否為 html 檔
const isHtml = (s: string) => /\.html?(?:$|\?)/i.test(s);
// 渲染圖表:根據副檔名決定用 <img> 或 <iframe>
const renderPlot = (srcRaw: string, title: string, alt: string) => {
const src = url(srcRaw);
if (isHtml(srcRaw)) {
return (
<iframe
src={src}
title={title}
className="w-full"
style={{ height: 480, border: '0' }}
/>
);
}
return (
<img
src={src}
alt={alt}
className="w-full h-auto"
loading="lazy"
onError={(e) => {
e.currentTarget.alt = `${alt} loading failed`;
}}
/>
);
};
if (loading && !resp) {
return (
<div className="space-y-6">
<PipelineProgress />
<section className="grid grid-cols-1 md:grid-cols-2 gap-6">
{[0, 1].map((i) => (
<div key={i} className="rounded-2xl border bg-white/70 backdrop-blur p-3">
<div className="w-full h-64 rounded-xl bg-gradient-to-b from-slate-200 to-slate-100 animate-pulse" />
<div className="mt-3 h-4 w-40 rounded bg-slate-200 animate-pulse" />
</div>
))}
</section>
</div>
);
}
if (error) {
return (
<div className="p-6 rounded-2xl bg-red-50 border border-red-200 text-red-700">
{error}
</div>
);
}
if (!result || !resp) {
return (
<div className="p-6 rounded-2xl bg-white/70 border border-white/40">
Task not executed yet
</div>
);
}
const m = result.metrics!;
const plots = resp.results.plots;
const r = resp.results as any;
const links: { label: string; href: string }[] = [];
if (r?.generation_file) {
links.push({ label: 'Generation CSV', href: r.generation_file });
}
if (r?.sentiment_subset_file) {
links.push({ label: 'Original sentiment subset CSV', href: r.sentiment_subset_file });
}
if (r?.cf_sentiment_subset_file) {
links.push({ label: 'CF sentiment subset CSV', href: r.cf_sentiment_subset_file });
}
if (r?.run_config_files?.markdown) {
links.push({ label: 'Run Config (Markdown)', href: r.run_config_files.markdown });
}
if (r?.run_config_files?.json) {
links.push({ label: 'Run Config (JSON)', href: r.run_config_files.json });
}
if (r?.finetuned_model_zip) {
links.push({ label: 'Fine-tuned Model (ZIP)', href: r.finetuned_model_zip });
} else if (r?.finetuned_model_dir) {
links.push({ label: 'Fine-tuned Model Folder', href: r.finetuned_model_dir });
}
return (
<div className="space-y-6">
{loading && <PipelineProgress />}
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur">
<h2 className="text-lg font-semibold mb-3">Metric</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="p-4 rounded-xl bg-slate-50 border">
<div className="text-slate-500 text-sm">Original Difference</div>
<div className="text-2xl font-bold">{m.finalMeanDiff.toFixed(4)}</div>
</div>
<div className="p-4 rounded-xl bg-slate-50 border">
<div className="text-slate-500 text-sm">CF Difference</div>
<div className="text-2xl font-bold">
{resp.results.metrics.cfFinalMeanDiff.toFixed(4)}
</div>
</div>
</div>
</section>
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur">
<h2 className="text-lg font-semibold mb-4">Distribution</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<figure className="rounded-xl overflow-hidden border bg-white">
{renderPlot(plots.original_sentiment, 'Original distribution (Plotly)', 'Original distribution')}
<figcaption className="p-3 text-sm text-slate-600">Original</figcaption>
</figure>
<figure className="rounded-xl overflow-hidden border bg-white">
{renderPlot(plots.counterfactual_sentiment, 'Counterfactual distribution (Plotly)', 'Counterfactual distribution')}
<figcaption className="p-3 text-sm text-slate-600">Counterfactual Augmented</figcaption>
</figure>
</div>
</section>
{links.length > 0 && (
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur">
<h2 className="text-lg font-semibold mb-4">Download Report</h2>
<ul className="space-y-2">
{links.map((l) => (
<li key={l.label}>
<a
className="text-indigo-600 hover:underline"
href={url(l.href)}
target="_blank"
rel="noreferrer"
download
>
{l.label}
</a>
</li>
))}
</ul>
</section>
)}
</div>
);
}