import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../../ui"; import { Card } from "../../ui"; import { Input } from "../../ui"; import { ScrollArea } from "../../ui"; import { Alert, AlertDescription } from "../../ui"; import { Button } from "../../ui"; import { DebuggerEvent, PinDebuggerEvent, PinType, HistoryPayload } from "@flyde/core"; import React, { useEffect } from "react"; import { timeAgo, useDebounce } from "../.."; import { BrowserOnlyReactJson } from "../../lib/analytics-value-renderer/BrowserJsonView"; import { Loader } from "../../lib/loader"; import { useDebuggerContext } from "../DebuggerContext"; export interface DataInspectionModalProps { onClose: () => void; item: { insId: string; pin?: { id: string; type: PinType } }; isOpen: boolean; } export const DataInspectionModal: React.FC = ( props ) => { const { onRequestHistory } = useDebuggerContext(); const { item, isOpen } = props; const [data, setData] = React.useState(); const [currIdx, setCurrIdx] = React.useState(0); const [search, setSearch] = React.useState(""); const [filteredValue, setFilteredValue] = React.useState([]); const [debouncedSearch] = useDebounce(search, 300); useEffect(() => { setFilteredValue( data?.lastSamples.filter((sample) => { if (typeof sample.val === "object") { return JSON.stringify(sample.val).includes(debouncedSearch); } return sample.val.toString().includes(debouncedSearch); }) ?? [] ); setCurrIdx(0); }, [data?.lastSamples, debouncedSearch]); React.useEffect(() => { async function fetchData() { const data = await onRequestHistory( item.insId, item.pin?.id ?? "", item.pin?.type ?? "input" ); setData(data); } fetchData(); }, [item, onRequestHistory]); const renderValue = (event: DebuggerEvent) => { const val = event.val; if (typeof val === "object") { return ; } return {val.toString()}; }; const renderEmptyState = () => { if (!data ||data.lastSamples.length > 0 && search.length > 0) { return ( No data found for search query "{search}" ); } return ( No events captured for instance {item.insId}{" "} {item.pin ? `and ${item.pin.id}` : ""}. Make sure a debugger is connected and your program was triggered. ); }; const itemName = `"${item.insId}" ${item.pin?.id ? `(${item.pin.id})` : ""}`; const renderInner = () => { if (!data) { return ; } if (data.total === 0) { return ( No events captured for instance {item.insId}{" "} {item.pin ? ( and pin {item.pin.id} ) : null} . Make sure debugger is running and your program was triggered. ); } const currEvent = filteredValue?.[currIdx] as PinDebuggerEvent; if (!currEvent) { return renderEmptyState(); } return (
{currEvent && (
Showing sample {currIdx} of event from{" "} {timeAgo(currEvent.time)} ( {new Date(currEvent.time).toLocaleString()})
Instance: {currEvent.insId}, Pin id:{" "} {currEvent.pinId}
Value:
)} {renderValue(currEvent)}
{filteredValue.map((sample, i) => { const pinId = (sample as PinDebuggerEvent).pinId; const label = `${data.total - i}. from pin "${pinId}"`; return ( ); })}
); }; return ( !open && props.onClose()}> Inspecting data for instance {itemName}
{data && (
{itemName} called {data.total} time(s) {data.total > 10 && (
Showing last 10 samples
)}
)} setSearch(e.target.value)} value={search} /> {debouncedSearch.length > 0 && (
Showing {filteredValue?.length} of {data?.lastSamples.length}{" "} samples matching query "{debouncedSearch}"
)}
{renderInner()}
); };