Skip to content

Commit 32d5b00

Browse files
committed
Improve metric titles and presets
1 parent 8ab18c2 commit 32d5b00

File tree

4 files changed

+86
-7
lines changed

4 files changed

+86
-7
lines changed

src/components/ChartContainer.jsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,15 @@ export default function ChartContainer({
392392
);
393393
}
394394

395-
const metricNames = metrics.map(m => m.name || m.keyword);
395+
const metricNames = metrics.map((m, idx) => {
396+
if (m.name && m.name.trim()) return m.name.trim();
397+
if (m.keyword) return m.keyword.replace(/[:]/g, '').trim();
398+
if (m.regex) {
399+
const sanitized = m.regex.replace(/[^a-zA-Z0-9_]/g, '').trim();
400+
return sanitized || `metric${idx + 1}`;
401+
}
402+
return `metric${idx + 1}`;
403+
});
396404
const metricDataArrays = {};
397405
metricNames.forEach(name => {
398406
metricDataArrays[name] = parsedData

src/components/FileConfigModal.jsx

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState, useEffect } from 'react';
22
import { X, Settings, TrendingDown, TrendingUp, Sliders, BarChart3, Target, Code, Zap } from 'lucide-react';
3+
import { METRIC_PRESETS } from '../metricPresets.js';
34

45
// 匹配模式枚举
56
const MATCH_MODES = {
@@ -23,6 +24,16 @@ const MODE_CONFIG = {
2324
}
2425
};
2526

27+
function getMetricTitle(metric, index) {
28+
if (metric.name && metric.name.trim()) return metric.name.trim();
29+
if (metric.keyword) return metric.keyword.replace(/[:]/g, '').trim();
30+
if (metric.regex) {
31+
const sanitized = metric.regex.replace(/[^a-zA-Z0-9_]/g, '').trim();
32+
return sanitized || `Metric ${index + 1}`;
33+
}
34+
return `Metric ${index + 1}`;
35+
}
36+
2637
export function FileConfigModal({ file, isOpen, onClose, onSave, globalParsingConfig }) {
2738
const [config, setConfig] = useState({
2839
metrics: [],
@@ -62,6 +73,17 @@ export function FileConfigModal({ file, isOpen, onClose, onSave, globalParsingCo
6273
}));
6374
};
6475

76+
const applyPreset = (index, presetLabel) => {
77+
const preset = METRIC_PRESETS.find(p => p.label === presetLabel);
78+
if (!preset) return;
79+
setConfig(prev => ({
80+
...prev,
81+
metrics: prev.metrics.map((m, i) =>
82+
i === index ? { ...m, ...preset } : m
83+
)
84+
}));
85+
};
86+
6587
const handleRangeChange = (field, value) => {
6688
setConfig(prev => ({
6789
...prev,
@@ -83,9 +105,22 @@ export function FileConfigModal({ file, isOpen, onClose, onSave, globalParsingCo
83105
// 渲染配置项的函数
84106
const renderConfigPanel = (type, configItem, index) => {
85107
const ModeIcon = MODE_CONFIG[configItem.mode].icon;
86-
108+
87109
return (
88110
<div className="space-y-2">
111+
<div>
112+
<label className="block text-xs font-medium text-gray-700 mb-1">预设</label>
113+
<select
114+
onChange={(e) => applyPreset(index, e.target.value)}
115+
className="w-full px-2 py-1 text-xs border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none"
116+
defaultValue=""
117+
>
118+
<option value="">选择预设</option>
119+
{METRIC_PRESETS.map(p => (
120+
<option key={p.label} value={p.label}>{p.label}</option>
121+
))}
122+
</select>
123+
</div>
89124
{/* 模式选择 */}
90125
<div>
91126
<label className="block text-xs font-medium text-gray-700 mb-1">
@@ -202,7 +237,7 @@ export function FileConfigModal({ file, isOpen, onClose, onSave, globalParsingCo
202237
<div key={idx} className="border rounded-lg p-3">
203238
<h4 className="text-sm font-medium text-gray-800 mb-2 flex items-center gap-1">
204239
<TrendingDown size={16} className="text-red-500" aria-hidden="true" />
205-
{cfg.name || `Metric ${idx + 1}`} 解析配置
240+
{getMetricTitle(cfg, idx)} 解析配置
206241
</h4>
207242
{renderConfigPanel(`metric-${idx}`, cfg, idx)}
208243
</div>

src/components/RegexControls.jsx

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState, useEffect, useCallback } from 'react';
22
import { Settings, Zap, Eye, ChevronDown, ChevronUp, Target, Code, ZoomIn } from 'lucide-react';
3+
import { METRIC_PRESETS } from '../metricPresets.js';
34

45
// 匹配模式枚举
56
const MATCH_MODES = {
@@ -23,6 +24,17 @@ const MODE_CONFIG = {
2324
}
2425
};
2526

27+
// 根据配置生成友好的标题
28+
function getMetricTitle(metric, index) {
29+
if (metric.name && metric.name.trim()) return metric.name.trim();
30+
if (metric.keyword) return metric.keyword.replace(/[:]/g, '').trim();
31+
if (metric.regex) {
32+
const sanitized = metric.regex.replace(/[^a-zA-Z0-9_]/g, '').trim();
33+
return sanitized || `Metric ${index + 1}`;
34+
}
35+
return `Metric ${index + 1}`;
36+
}
37+
2638
// 数值提取器类
2739
export class ValueExtractor {
2840
// 关键词匹配
@@ -215,7 +227,7 @@ export function RegexControls({
215227
if (file.content) {
216228
globalParsingConfig.metrics.forEach((cfg, idx) => {
217229
const matches = extractValues(file.content, cfg.mode, cfg);
218-
const key = cfg.name || `metric${idx + 1}`;
230+
const key = getMetricTitle(cfg, idx);
219231
if (!results[key]) results[key] = [];
220232
results[key].push({
221233
fileName: file.name,
@@ -299,13 +311,21 @@ export function RegexControls({
299311
onGlobalParsingConfigChange({ metrics: newMetrics });
300312
};
301313

314+
const applyPreset = (index, presetLabel) => {
315+
const preset = METRIC_PRESETS.find(p => p.label === presetLabel);
316+
if (!preset) return;
317+
const newMetrics = [...globalParsingConfig.metrics];
318+
newMetrics[index] = { ...newMetrics[index], ...preset };
319+
onGlobalParsingConfigChange({ metrics: newMetrics });
320+
};
321+
302322
const handleXRangeChange = (field, value) => {
303323
const newRange = { ...xRange, [field]: value === '' ? undefined : Number(value) };
304324
onXRangeChange(newRange);
305325
};
306326

307327
// 渲染配置项的函数
308-
const renderConfigPanel = (type, config, onConfigChange) => {
328+
const renderConfigPanel = (type, config, onConfigChange, index) => {
309329
const ModeIcon = MODE_CONFIG[config.mode].icon;
310330

311331
return (
@@ -318,6 +338,16 @@ export function RegexControls({
318338
onChange={(e) => onConfigChange('name', e.target.value)}
319339
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none"
320340
/>
341+
<select
342+
onChange={(e) => applyPreset(index, e.target.value)}
343+
className="w-full px-2 py-1 text-xs border border-gray-300 rounded-md mt-1 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none"
344+
defaultValue=""
345+
>
346+
<option value="">选择预设</option>
347+
{METRIC_PRESETS.map(p => (
348+
<option key={p.label} value={p.label}>{p.label}</option>
349+
))}
350+
</select>
321351
</div>
322352
{/* 模式选择 */}
323353
<div>
@@ -430,9 +460,9 @@ export function RegexControls({
430460
</button>
431461
<h4 className="text-sm font-medium text-gray-800 mb-2 flex items-center gap-1">
432462
<span className="w-3 h-3 bg-blue-500 rounded-full"></span>
433-
{cfg.name || `Metric ${idx + 1}`} 解析配置
463+
{getMetricTitle(cfg, idx)} 解析配置
434464
</h4>
435-
{renderConfigPanel(`metric-${idx}`, cfg, (field, value) => handleMetricChange(idx, field, value))}
465+
{renderConfigPanel(`metric-${idx}`, cfg, (field, value) => handleMetricChange(idx, field, value), idx)}
436466
</div>
437467
))}
438468
<button

src/metricPresets.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const METRIC_PRESETS = [
2+
{ label: 'Loss', name: 'Loss', mode: 'keyword', keyword: 'loss:' },
3+
{ label: 'Grad Norm', name: 'Grad Norm', mode: 'keyword', keyword: 'norm:' },
4+
{ label: 'Accuracy', name: 'Accuracy', mode: 'keyword', keyword: 'acc:' },
5+
{ label: 'Learning Rate', name: 'Learning Rate', mode: 'keyword', keyword: 'lr:' }
6+
];

0 commit comments

Comments
 (0)