Skip to content

Add sidebar toggle #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ChartContainer from './components/ChartContainer';
import { ComparisonControls } from './components/ComparisonControls';
import { Header } from './components/Header';
import { FileConfigModal } from './components/FileConfigModal';
import { PanelLeftClose, PanelLeftOpen } from 'lucide-react';

function App() {
const [uploadedFiles, setUploadedFiles] = useState([]);
Expand Down Expand Up @@ -37,6 +38,7 @@ function App() {
const [, setDragCounter] = useState(0);
const [xRange, setXRange] = useState({ min: undefined, max: undefined });
const [maxStep, setMaxStep] = useState(0);
const [sidebarVisible, setSidebarVisible] = useState(true);

const handleFilesUploaded = useCallback((files) => {
const filesWithDefaults = files.map(file => ({
Expand Down Expand Up @@ -188,7 +190,7 @@ function App() {
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 relative">
{/* 全页面拖拽覆盖层 */}
{globalDragOver && (
<div
<div
className="fixed inset-0 bg-blue-600 bg-opacity-95 z-50 flex items-center justify-center backdrop-blur-sm drag-overlay-fade-in"
>
<div
Expand Down Expand Up @@ -230,20 +232,31 @@ function App() {
</div>
)}

{!sidebarVisible && (
<button
onClick={() => setSidebarVisible(true)}
className="fixed top-3 left-3 z-40 p-2 bg-white rounded-full shadow-md text-gray-600 hover:text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500"
aria-label="显示工具栏"
>
<PanelLeftOpen size={20} aria-hidden="true" />
</button>
)}

<div className="w-full px-3 py-3">
<main

<main
id="main-content"
className="grid grid-cols-1 xl:grid-cols-5 gap-3"
className="grid grid-cols-1 xl:grid-cols-5 gap-3"
role="main"
>
<aside
className="xl:col-span-1 space-y-3"
role="complementary"
aria-label="控制面板"
>
{/* 标题信息 */}
<div className="bg-white rounded-lg shadow-md p-3">
{sidebarVisible && (
<aside
className="xl:col-span-1 space-y-3"
role="complementary"
aria-label="控制面板"
>
{/* 标题信息 */}
<div className="bg-white rounded-lg shadow-md p-3">
<div className="flex items-center gap-2 mb-2">
<div className="p-2 bg-blue-100 rounded-lg">
<svg className="w-5 h-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
Expand All @@ -253,6 +266,13 @@ function App() {
<h1 className="text-lg font-bold text-gray-800">
Log Analyzer
</h1>
<button
onClick={() => setSidebarVisible(false)}
className="ml-auto p-1 text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded"
aria-label="隐藏工具栏"
>
<PanelLeftClose size={16} aria-hidden="true" />
</button>
</div>
<p className="text-sm text-gray-600 mb-3">
📊 分析和可视化大模型训练日志中的损失函数和梯度范数数据
Expand Down Expand Up @@ -375,11 +395,12 @@ function App() {
</div>
</div>
</div>
</section>
</aside>
</section>
</aside>
)}

<section
className="xl:col-span-4"
<section
className={sidebarVisible ? 'xl:col-span-4' : 'xl:col-span-5'}
role="region"
aria-label="图表显示区域"
>
Expand Down
72 changes: 59 additions & 13 deletions src/components/ChartContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,30 @@ export default function ChartContainer({
return result;
};

const calculateYRange = useCallback((dataArray) => {
let min = Infinity;
let max = -Infinity;
dataArray.forEach(item => {
item.data.forEach(point => {
const inRange =
(xRange.min === undefined || point.x >= xRange.min) &&
(xRange.max === undefined || point.x <= xRange.max);
if (inRange) {
if (point.y < min) min = point.y;
if (point.y > max) max = point.y;
}
});
});
if (min === Infinity || max === -Infinity) {
return { min: 0, max: 1 };
}
if (min === max) {
return { min: min - 1, max: max + 1 };
}
const pad = (max - min) * 0.05;
return { min: min - pad, max: max + pad };
}, [xRange]);

const chartOptions = useMemo(() => ({
responsive: true,
maintainAspectRatio: false,
Expand Down Expand Up @@ -326,7 +350,6 @@ export default function ChartContainer({
display: true,
title: { display: true, text: 'Value' },
bounds: 'data',
grace: '20%',
ticks: {
callback: function (value) {
return Number(value.toPrecision(2));
Expand Down Expand Up @@ -429,6 +452,15 @@ export default function ChartContainer({
const dataArray = metricDataArrays[key] || [];
const showComparison = dataArray.length === 2;

const yRange = calculateYRange(dataArray);
const options = {
...chartOptions,
scales: {
...chartOptions.scales,
y: { ...chartOptions.scales.y, min: yRange.min, max: yRange.max }
}
};

let stats = null;
if (showComparison) {
const normalDiff = getComparisonData(dataArray[0].data, dataArray[1].data, 'normal');
Expand All @@ -442,6 +474,30 @@ export default function ChartContainer({
};
}

let comparisonChart = null;
if (showComparison) {
const compData = createComparisonChartData(dataArray[0], dataArray[1], key);
const compRange = calculateYRange(compData.datasets);
const compOptions = {
...chartOptions,
scales: {
...chartOptions.scales,
y: { ...chartOptions.scales.y, min: compRange.min, max: compRange.max }
}
};
comparisonChart = (
<ResizablePanel title={`⚖️ ${key} 对比分析 (${compareMode})`} initialHeight={440}>
<ChartWrapper
chartId={`metric-comp-${idx}`}
onRegisterChart={registerChart}
onSyncHover={syncHoverToAllCharts}
data={compData}
options={compOptions}
/>
</ResizablePanel>
);
}

return (
<div key={key} className="flex flex-col gap-3">
<ResizablePanel title={key} initialHeight={440}>
Expand All @@ -450,20 +506,10 @@ export default function ChartContainer({
onRegisterChart={registerChart}
onSyncHover={syncHoverToAllCharts}
data={createChartData(dataArray)}
options={chartOptions}
options={options}
/>
</ResizablePanel>
{showComparison && (
<ResizablePanel title={`⚖️ ${key} 对比分析 (${compareMode})`} initialHeight={440}>
<ChartWrapper
chartId={`metric-comp-${idx}`}
onRegisterChart={registerChart}
onSyncHover={syncHoverToAllCharts}
data={createComparisonChartData(dataArray[0], dataArray[1], key)}
options={chartOptions}
/>
</ResizablePanel>
)}
{comparisonChart}
{stats && (
<div className="bg-white rounded-lg shadow-md p-3">
<h4 className="text-sm font-medium text-gray-700 mb-1">{key} 差值统计</h4>
Expand Down