Skip to content

Commit

Permalink
use embedded rerun component instead of iframe. (viewer works but sti…
Browse files Browse the repository at this point in the history
…ll cannot load our files)
  • Loading branch information
alik-git committed Dec 10, 2024
1 parent ce51bf4 commit 71b6daf
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 30 deletions.
123 changes: 97 additions & 26 deletions src/components/terminal/TerminalSingleRobot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { components } from "@/gen/api";
import { useAuthentication } from "@/hooks/useAuth";
import ROUTES from "@/lib/types/routes";
import { FEATURE_FLAGS } from "@/lib/utils/featureFlags";
import WebViewer from "@rerun-io/web-viewer-react";

Check failure on line 14 in src/components/terminal/TerminalSingleRobot.tsx

View workflow job for this annotation

GitHub Actions / run-tests

Cannot find module '@rerun-io/web-viewer-react' or its corresponding type declarations.

interface Props {
robot: SingleRobotResponse;
Expand All @@ -22,6 +23,18 @@ interface Props {

type KRec = components["schemas"]["KRec"];

// Type definition for recording information returned from the API
// (For rerun viewer) Required for proper typing of recording data structure
interface KrecInfo {
urls: {
url: string;
filename: string;
expires_at: number;
checksum?: string | null;
};
contentType?: string; // (For debugging) Helps identify file types during development
}

const TerminalSingleRobot = ({ robot, onUpdateRobot }: Props) => {
const navigate = useNavigate();
const auth = useAuthentication();
Expand All @@ -39,7 +52,7 @@ const TerminalSingleRobot = ({ robot, onUpdateRobot }: Props) => {
const [krecs, setKrecs] = useState<KRec[]>([]);
const [deleteKrecId, setDeleteKrecId] = useState<string | null>(null);
const [selectedKrec, setSelectedKrec] = useState<KRec | null>(null);
const [krecInfo, setKrecInfo] = useState<any>(null);
const [krecInfo, setKrecInfo] = useState<KrecInfo | null>(null);

const addTerminalMessage = (message: string) => {
setTerminalMessages((prev) => [...prev, message]);
Expand Down Expand Up @@ -90,20 +103,61 @@ const TerminalSingleRobot = ({ robot, onUpdateRobot }: Props) => {
}
};

// (For rerun viewer) Fetches recording information needed for the viewer
const fetchKrecInfo = async (krecId: string) => {
try {
const { data } = await auth.client.GET("/krecs/info/{krec_id}", {
params: {
path: { krec_id: krecId },
},
params: { path: { krec_id: krecId } },
});

// (For debugging) Extract content type for debugging purposes
if (data?.urls?.url) {
const url = new URL(data.urls.url);
return {
...data,
contentType: url.searchParams.get("response-content-type") || "application/x-rerun"
};
}
return data;
} catch (error) {
addTerminalMessage(`Error fetching KRec info: ${error}`);
return null;
}
};

// (For rerun viewer) Handles selection and loading of recordings into the viewer
const handleKrecSelect = async (krec: KRec) => {
// (For debugging) Log selection for troubleshooting
console.log("Selected krec:", krec);
setSelectedKrec(krec);
const info = await fetchKrecInfo(krec.id);
console.log("Fetched krec info:", info);

// (For rerun viewer) Ensure data is valid before loading into viewer
if (info && 'urls' in info && info.urls?.url) {
setKrecInfo(info as KrecInfo);
addTerminalMessage(`KRec URL: ${info.urls.url}`);
} else {
addTerminalMessage("No valid URL found in recording info");
}
};

// (For rerun viewer) Prepares URLs for the Rerun viewer component
const getCleanRrdUrl = (url: string) => {
// (For debugging) Log URL processing steps
console.log("Original URL:", url);

// (For rerun viewer) Remove query parameters which can interfere with viewer
const baseUrl = url.split('?')[0];
console.log("Base URL:", baseUrl);

// (For debugging) Log file extension for troubleshooting
const fileExtension = baseUrl.split('.').pop()?.toLowerCase();
console.log("File extension:", fileExtension);

return baseUrl;
};

useEffect(() => {
const fetchKrecs = async () => {
try {
Expand All @@ -130,20 +184,23 @@ const TerminalSingleRobot = ({ robot, onUpdateRobot }: Props) => {
fetchKrecs();
}, [robot.robot_id]);

const handleKrecSelect = async (krec: KRec) => {
setSelectedKrec(krec);
const info = await fetchKrecInfo(krec.id);
setKrecInfo(info);
addTerminalMessage(`KRec URL: ${info?.urls?.url || 'No URL found'}`);
};

const getCleanRrdUrl = (url: string) => {
const rrdIndex = url.indexOf('.rrd');
if (rrdIndex !== -1) {
return url.substring(0, rrdIndex + 4); // +4 to include '.rrd'
useEffect(() => {
if (selectedKrec && krecInfo?.urls?.url) {
const cleanUrl = getCleanRrdUrl(krecInfo.urls.url);
if (cleanUrl) {
fetch(cleanUrl, {
mode: "no-cors",
credentials: "omit",
})
.then(() => {
console.log("Successfully pre-fetched RRD file");
})
.catch((error) => {
console.error("Error pre-fetching RRD file:", error);
});
}
}
return url;
};
}, [selectedKrec, krecInfo]);

return (
<div className="min-h-screen bg-black p-4 font-mono text-white">
Expand Down Expand Up @@ -380,19 +437,33 @@ const TerminalSingleRobot = ({ robot, onUpdateRobot }: Props) => {
</div>
</div>
<div className="p-4 flex flex-col items-center justify-center h-[calc(90vh-80px)]">
<span className="text-gray-500 mb-4">
Rerun Viewer
</span>
<span className="text-gray-500 mb-4">Rerun Viewer</span>
{selectedKrec && krecInfo?.urls?.url && (
<>
<div className="text-xs text-gray-500 mb-2">
Loading RRD file: {selectedKrec.name}
Loading recording: {selectedKrec.name}
</div>
<div className="w-full h-full min-h-[300px] border border-gray-700">
{/* Debug information panel */}
<div className="p-2 bg-black text-xs">
Debug Info:
<pre className="overflow-auto">
Original URL: {krecInfo.urls.url}
<br />
Clean URL: {getCleanRrdUrl(krecInfo.urls.url)}
<br />
File Name: {selectedKrec.name}
<br />
Content Type: {krecInfo.contentType || "unknown"}
</pre>
</div>
{/* Rerun Web Viewer component */}
<WebViewer
width="100%"
height="100%"
rrd={getCleanRrdUrl(krecInfo.urls.url)}
/>
</div>
<iframe
src={`https://app.rerun.io/version/0.20.0/?url=${encodeURIComponent(getCleanRrdUrl(krecInfo.urls.url))}`}
className="w-full h-full min-h-[300px] border-0"
onError={(e) => addTerminalMessage(`Iframe error: ${e}`)}
/>
</>
)}
<Button
Expand Down
25 changes: 21 additions & 4 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import tailwindcss from "tailwindcss";

import react from "@vitejs/plugin-react";
import path from "path";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
// Required for WebAssembly support
import wasm from "vite-plugin-wasm";
// Required for top-level await support, which is needed by the WASM modules
import topLevelAwait from "vite-plugin-top-level-await";

export default defineConfig({
plugins: [react(), tsconfigPaths()],
plugins: [
react(),
tsconfigPaths(),
wasm(), // Enables WebAssembly support
topLevelAwait() // Enables top-level await support
],
css: {
postcss: {
plugins: [tailwindcss()],
Expand All @@ -19,6 +27,15 @@ export default defineConfig({
},
build: {
outDir: "dist",
target: "esnext" // Required for modern JavaScript features used by WASM
},
assetsInclude: ["**/*.xml"],
});
assetsInclude: [
"**/*.xml",
"**/*.wasm" // Tells Vite to include .wasm files as assets
],
optimizeDeps: {
// Prevents Vite from trying to pre-bundle the web-viewer
// which would break the WASM functionality
exclude: ['@rerun-io/web-viewer-react']
}
});

0 comments on commit 71b6daf

Please sign in to comment.