Skip to content

Commit 2eb0dce

Browse files
authored
Merge pull request #210 from krishauser/sr_viz_shiyang_clean
fix control panel re upload bug
2 parents a0e1c1f + 911d8ea commit 2eb0dce

2 files changed

Lines changed: 28 additions & 54 deletions

File tree

GEMstack/onboard/visualization/sr_viz/threeD/next.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const nextConfig: NextConfig = {
55
eslint: {
66
ignoreDuringBuilds: true,
77
},
8+
typescript: {
9+
ignoreBuildErrors: true,
10+
},
811
};
912

1013
export default nextConfig;

GEMstack/onboard/visualization/sr_viz/threeD/src/components/ControlPanel.tsx

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,68 +19,41 @@ export default function ControlPanel({
1919
}) {
2020
const [isOpen, setIsOpen] = useState(false);
2121
const [fileName, setFileName] = useState<string | null>(null);
22-
const setTimeline = useTimelineStore((state) => state.setTimeline);
23-
24-
// ref so we can clear input.value after upload
2522
const fileInputRef = useRef<HTMLInputElement>(null);
23+
const prevKeyRef = useRef<string | null>(null);
24+
const setTimeline = useTimelineStore((state) => state.setTimeline);
2625

2726
const handleFileUpload = async (
2827
event: React.ChangeEvent<HTMLInputElement>
2928
) => {
3029
const uploaded = event.target.files?.[0];
3130
if (!uploaded) return;
32-
3331
setFileName(uploaded.name);
34-
35-
try {
36-
const entries = await parseLogFile(uploaded);
37-
const timeline: TimelineData = buildTimeline(entries);
38-
setTimeline(timeline);
39-
reset();
40-
console.log("timeline loaded:", timeline);
41-
} catch (err) {
42-
console.error("Failed to parse log file:", err);
43-
}
44-
45-
// reset the input so same filename can be re‐picked
46-
if (fileInputRef.current) {
47-
fileInputRef.current.value = "";
48-
}
32+
const entries = await parseLogFile(uploaded);
33+
const timeline: TimelineData = buildTimeline(entries);
34+
setTimeline(timeline);
35+
reset();
36+
fileInputRef.current!.value = "";
4937
};
5038

51-
const handleContextMenu = (event: React.MouseEvent) => {
52-
event.preventDefault();
53-
setIsOpen((o) => !o);
54-
};
55-
56-
// auto‐load from Flask if folder+file props provided
5739
useEffect(() => {
5840
if (!folder || !file) return;
59-
60-
const fetchLog = async () => {
41+
const key = `${folder}/${file}`;
42+
if (prevKeyRef.current === key) return;
43+
prevKeyRef.current = key;
44+
(async () => {
6145
const url = `http://localhost:5000/raw_logs/${encodeURIComponent(
6246
folder
6347
)}/${encodeURIComponent(file)}`;
64-
65-
try {
66-
const res = await fetch(url);
67-
if (!res.ok) {
68-
throw new Error(`Failed to fetch ${file} (status ${res.status})`);
69-
}
70-
const text = await res.text();
71-
const fakeFile = new File([text], file, { type: "text/plain" });
72-
const entries = await parseLogFile(fakeFile);
73-
const timeline = buildTimeline(entries);
74-
setTimeline(timeline);
75-
reset();
76-
setFileName(file);
77-
console.log("Timeline loaded from Flask API:", timeline);
78-
} catch (err) {
79-
console.error("Failed to load remote log file:", err);
80-
}
81-
};
82-
83-
fetchLog();
48+
const res = await fetch(url);
49+
const text = await res.text();
50+
const fakeFile = new File([text], file, { type: "text/plain" });
51+
const entries = await parseLogFile(fakeFile);
52+
const timeline = buildTimeline(entries);
53+
setTimeline(timeline);
54+
reset();
55+
setFileName(file);
56+
})();
8457
}, [folder, file, reset, setTimeline]);
8558

8659
return (
@@ -89,7 +62,10 @@ export default function ControlPanel({
8962
className={`fixed top-0 left-0 h-full w-48 max-w-[90vw] bg-black/80 text-white shadow-lg transform transition-transform duration-300 ease-in-out z-40 overflow-y-auto flex flex-col ${
9063
isOpen ? "translate-x-0" : "-translate-x-full"
9164
}`}
92-
onContextMenu={handleContextMenu}
65+
onContextMenu={(e) => {
66+
e.preventDefault();
67+
setIsOpen((o) => !o);
68+
}}
9369
>
9470
{isOpen && (
9571
<>
@@ -100,12 +76,10 @@ export default function ControlPanel({
10076
<button
10177
onClick={() => setIsOpen(false)}
10278
className="text-white p-1 rounded hover:bg-white/10"
103-
title="Close Panel"
10479
>
10580
<RxCross2 className="w-4 h-4" />
10681
</button>
10782
</div>
108-
10983
<div className="p-4">
11084
<label className="inline-flex items-center gap-2 cursor-pointer text-gray-300 text-sm px-4 py-2 border border-gray-500 rounded hover:bg-white/10 transition">
11185
<TiUpload className="w-4 h-4" />
@@ -125,17 +99,14 @@ export default function ControlPanel({
12599
</>
126100
)}
127101
</div>
128-
129102
{!isOpen && (
130103
<button
131104
onClick={() => setIsOpen(true)}
132105
className="fixed top-1/2 left-0 -translate-y-1/2 z-50 bg-black/80 text-white w-3 h-8 flex items-center justify-center rounded-r hover:bg-black border-l border-white/20"
133-
title="Open Panel"
134-
onContextMenu={(e) => e.preventDefault()}
135106
>
136107
<span className="text-xs"></span>
137108
</button>
138109
)}
139110
</>
140111
);
141-
}
112+
}

0 commit comments

Comments
 (0)