Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Sync from huggingface/lerobot-dataset-visualizer via hub-sync
Browse files
src/app/[org]/[dataset]/[episode]/episode-viewer.tsx
CHANGED
|
@@ -21,10 +21,10 @@ import { AnnotationsTimeline } from "@/components/annotations-timeline";
|
|
| 21 |
import Sidebar from "@/components/side-nav";
|
| 22 |
import StatsPanel from "@/components/stats-panel";
|
| 23 |
import OverviewPanel from "@/components/overview-panel";
|
|
|
|
| 24 |
import Loading from "@/components/loading-component";
|
| 25 |
import HfAuthButton from "@/components/hf-auth-button";
|
| 26 |
import { EpisodeHeader, ThemeToggle } from "@/components/ui";
|
| 27 |
-
import { useTheme } from "@/utils/theme";
|
| 28 |
import { hasRobotModel } from "@/lib/so101-robot";
|
| 29 |
import {
|
| 30 |
crossEpisodeCache,
|
|
@@ -696,8 +696,6 @@ function EpisodeViewerInner({
|
|
| 696 |
// which would redraw this whole component ~12×/s. <UrlTimeSync /> handles
|
| 697 |
// the one thing here that needs `currentTime` (the ?t= URL writer).
|
| 698 |
const { seek, setIsPlaying, stepFrames } = useTimeControls();
|
| 699 |
-
/// Passed to the embedded lerobot-doctor Space, which follows `__theme` like any HF Space.
|
| 700 |
-
const theme = useTheme();
|
| 701 |
|
| 702 |
// ReplayViewer episode changer and play toggle — populated by ReplayViewer on mount
|
| 703 |
const replayChangerRef = useRef<((ep: number) => void) | undefined>(
|
|
@@ -1050,35 +1048,7 @@ function EpisodeViewerInner({
|
|
| 1050 |
)}
|
| 1051 |
|
| 1052 |
{activeTab === "doctor" && (
|
| 1053 |
-
<
|
| 1054 |
-
<div className="flex items-center justify-between px-1 pb-2 text-xs text-fg-muted">
|
| 1055 |
-
<span>
|
| 1056 |
-
Dataset quality diagnostics — powered by{" "}
|
| 1057 |
-
<a
|
| 1058 |
-
href="https://github.com/jashshah999/lerobot-doctor"
|
| 1059 |
-
target="_blank"
|
| 1060 |
-
rel="noopener noreferrer"
|
| 1061 |
-
className="underline hover:text-fg"
|
| 1062 |
-
>
|
| 1063 |
-
lerobot-doctor
|
| 1064 |
-
</a>
|
| 1065 |
-
</span>
|
| 1066 |
-
<a
|
| 1067 |
-
href={`https://jashshah999-lerobot-doctor.hf.space/?dataset=${org}/${dataset}`}
|
| 1068 |
-
target="_blank"
|
| 1069 |
-
rel="noopener noreferrer"
|
| 1070 |
-
className="underline hover:text-fg"
|
| 1071 |
-
>
|
| 1072 |
-
Open in new tab
|
| 1073 |
-
</a>
|
| 1074 |
-
</div>
|
| 1075 |
-
<iframe
|
| 1076 |
-
src={`https://jashshah999-lerobot-doctor.hf.space/?dataset=${org}/${dataset}&__theme=${theme}`}
|
| 1077 |
-
title="lerobot-doctor"
|
| 1078 |
-
className="flex-1 w-full rounded-lg border border-line bg-[var(--surface-0)]"
|
| 1079 |
-
sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
|
| 1080 |
-
/>
|
| 1081 |
-
</div>
|
| 1082 |
)}
|
| 1083 |
|
| 1084 |
{activeTab === "replay" && (
|
|
|
|
| 21 |
import Sidebar from "@/components/side-nav";
|
| 22 |
import StatsPanel from "@/components/stats-panel";
|
| 23 |
import OverviewPanel from "@/components/overview-panel";
|
| 24 |
+
import DoctorPanel from "@/components/doctor-panel";
|
| 25 |
import Loading from "@/components/loading-component";
|
| 26 |
import HfAuthButton from "@/components/hf-auth-button";
|
| 27 |
import { EpisodeHeader, ThemeToggle } from "@/components/ui";
|
|
|
|
| 28 |
import { hasRobotModel } from "@/lib/so101-robot";
|
| 29 |
import {
|
| 30 |
crossEpisodeCache,
|
|
|
|
| 696 |
// which would redraw this whole component ~12×/s. <UrlTimeSync /> handles
|
| 697 |
// the one thing here that needs `currentTime` (the ?t= URL writer).
|
| 698 |
const { seek, setIsPlaying, stepFrames } = useTimeControls();
|
|
|
|
|
|
|
| 699 |
|
| 700 |
// ReplayViewer episode changer and play toggle — populated by ReplayViewer on mount
|
| 701 |
const replayChangerRef = useRef<((ep: number) => void) | undefined>(
|
|
|
|
| 1048 |
)}
|
| 1049 |
|
| 1050 |
{activeTab === "doctor" && (
|
| 1051 |
+
<DoctorPanel repoId={datasetInfo.repoId} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1052 |
)}
|
| 1053 |
|
| 1054 |
{activeTab === "replay" && (
|
src/components/doctor-panel.tsx
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client";
|
| 2 |
+
|
| 3 |
+
import { useState } from "react";
|
| 4 |
+
import { InlineLoading } from "@/components/ui";
|
| 5 |
+
import { useTheme } from "@/utils/theme";
|
| 6 |
+
|
| 7 |
+
const DOCTOR_SPACE = "https://jashshah999-lerobot-doctor.hf.space/";
|
| 8 |
+
|
| 9 |
+
/** The lerobot-doctor Space, embedded for this dataset. */
|
| 10 |
+
export default function DoctorPanel({ repoId }: { repoId: string }) {
|
| 11 |
+
/// Passed to the embedded Space, which follows `__theme` like any HF Space.
|
| 12 |
+
const theme = useTheme();
|
| 13 |
+
const src = `${DOCTOR_SPACE}?dataset=${repoId}&__theme=${theme}`;
|
| 14 |
+
// Which address has finished loading. A new dataset or theme is a new address, so the frame
|
| 15 |
+
// reloads and this reads as loading again without any reset.
|
| 16 |
+
const [loadedSrc, setLoadedSrc] = useState<string | null>(null);
|
| 17 |
+
const loading = loadedSrc !== src;
|
| 18 |
+
|
| 19 |
+
return (
|
| 20 |
+
<div className="flex flex-col h-full">
|
| 21 |
+
<div className="flex items-center justify-between px-1 pb-2 text-xs text-fg-muted">
|
| 22 |
+
<span>
|
| 23 |
+
Dataset quality diagnostics — powered by{" "}
|
| 24 |
+
<a
|
| 25 |
+
href="https://github.com/jashshah999/lerobot-doctor"
|
| 26 |
+
target="_blank"
|
| 27 |
+
rel="noopener noreferrer"
|
| 28 |
+
className="underline hover:text-fg"
|
| 29 |
+
>
|
| 30 |
+
lerobot-doctor
|
| 31 |
+
</a>
|
| 32 |
+
</span>
|
| 33 |
+
<a
|
| 34 |
+
href={`${DOCTOR_SPACE}?dataset=${repoId}`}
|
| 35 |
+
target="_blank"
|
| 36 |
+
rel="noopener noreferrer"
|
| 37 |
+
className="underline hover:text-fg"
|
| 38 |
+
>
|
| 39 |
+
Open in new tab
|
| 40 |
+
</a>
|
| 41 |
+
</div>
|
| 42 |
+
<div className="relative min-h-0 flex-1">
|
| 43 |
+
<iframe
|
| 44 |
+
src={src}
|
| 45 |
+
title="lerobot-doctor"
|
| 46 |
+
onLoad={() => setLoadedSrc(src)}
|
| 47 |
+
aria-busy={loading}
|
| 48 |
+
className="h-full w-full rounded-lg border border-line bg-[var(--surface-0)]"
|
| 49 |
+
sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
|
| 50 |
+
/>
|
| 51 |
+
{/* The Space is another server, and one that sleeps when idle: until it answers the
|
| 52 |
+
frame is an empty box, which read as a broken tab. */}
|
| 53 |
+
{loading && (
|
| 54 |
+
<div className="pointer-events-none absolute inset-0 flex flex-col items-center justify-center rounded-lg border border-line bg-[var(--surface-0)]">
|
| 55 |
+
<InlineLoading label="Loading lerobot-doctor…" />
|
| 56 |
+
<p className="-mt-4 max-w-sm text-center text-xs text-fg-faint">
|
| 57 |
+
It runs in its own Space, which can take a moment to wake up if
|
| 58 |
+
nobody has used it recently.
|
| 59 |
+
</p>
|
| 60 |
+
</div>
|
| 61 |
+
)}
|
| 62 |
+
</div>
|
| 63 |
+
</div>
|
| 64 |
+
);
|
| 65 |
+
}
|
src/components/overview-panel.tsx
CHANGED
|
@@ -133,6 +133,7 @@ function FrameTile({
|
|
| 133 |
<Link
|
| 134 |
href={episodeHref(episode)}
|
| 135 |
title={`Open episode ${episode}`}
|
|
|
|
| 136 |
className={`flex gap-px overflow-hidden rounded outline-offset-2 ring-1 transition-shadow focus-visible:outline-2 focus-visible:outline-[var(--accent)] ${
|
| 137 |
isFlagged
|
| 138 |
? "ring-rose-500/70"
|
|
|
|
| 133 |
<Link
|
| 134 |
href={episodeHref(episode)}
|
| 135 |
title={`Open episode ${episode}`}
|
| 136 |
+
aria-label={`Open episode ${episode}`}
|
| 137 |
className={`flex gap-px overflow-hidden rounded outline-offset-2 ring-1 transition-shadow focus-visible:outline-2 focus-visible:outline-[var(--accent)] ${
|
| 138 |
isFlagged
|
| 139 |
? "ring-rose-500/70"
|