Skip to content

Commit

Permalink
Added json viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
matvp91 committed Dec 11, 2024
1 parent 73fc260 commit f2cf130
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 70 deletions.
Binary file modified bun.lockb
Binary file not shown.
22 changes: 0 additions & 22 deletions packages/app/src/components/DataDump.tsx

This file was deleted.

71 changes: 64 additions & 7 deletions packages/app/src/components/DataView.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
interface DataViewProps {
data: object | string;
redacted?: string[];
}

type Value = string | number | null | undefined | object;

export function DataView({ data }: DataViewProps) {
export function DataView({ data, redacted }: DataViewProps) {
if (typeof data === "string") {
data = JSON.parse(data);
}

return (
<div className="text-xs">
<Value name="" parent="" value={data} />
<div className="text-xs font-mono">
<Value name="" parent="" value={data} redacted={redacted} />
</div>
);
}
Expand All @@ -20,32 +21,48 @@ function Value({
name,
value,
parent,
redacted,
}: {
name: string;
value: Value | Value[];
parent: string;
redacted?: string[];
}) {
const path = [parent, name].filter((item) => !!item).join(".");

if (redacted?.some((lookup) => matchRedacted(lookup, path))) {
return null;
}

if (Array.isArray(value)) {
return (
<IteratedValue
name={name}
values={value.map((child, index) => [index.toString(), child])}
parent={path}
redacted={redacted}
isArray
/>
);
}
if (typeof value === "object" && value) {
const values = Object.entries(value);

values.sort((a, b) => (a[0] > b[0] ? 1 : -1));

return (
<IteratedValue name={name} values={Object.entries(value)} parent={path} />
<IteratedValue
name={name}
values={values}
parent={path}
redacted={redacted}
/>
);
}
if (value !== Object(value)) {
return (
<div className="ml-2" data-key={path}>
{name}: {String(value)}
{name}: <Primitive value={value} />
</div>
);
}
Expand All @@ -57,26 +74,66 @@ function IteratedValue({
values,
parent,
isArray,
redacted,
}: {
name: string;
values: [string, Value][];
parent: string;
isArray?: boolean;
redacted?: string[];
}) {
return (
<div className="ml-2">
{name ? `${name}: ` : ""} {isArray ? "[" : "{"}
{name ? `${name}: ` : ""}{" "}
{isArray ? (
<span className="text-lime-700">{"["}</span>
) : (
<span className="text-blue-700">{"{"}</span>
)}
{values.map(([childName, child]) => {
return (
<Value
key={`${parent}.${childName}`}
name={childName}
value={child}
parent={parent}
redacted={redacted}
/>
);
})}
{isArray ? "]" : "}"}
{isArray ? (
<span className="text-lime-700">{"]"}</span>
) : (
<span className="text-blue-700">{"}"}</span>
)}
</div>
);
}

function Primitive({ value }: { value: Value }) {
const str = String(value);
if (value === null || value === undefined) {
return <span className="opacity-50">{str}</span>;
}
if (typeof value === "string") {
return <span className="text-blue-700">"{str}"</span>;
}
if (typeof value === "boolean") {
return <span className="text-amber-600">{str}</span>;
}
if (typeof value === "number") {
if (Number.isNaN(value)) {
return <span className="opacity-50">{str}</span>;
}
return <span className="text-pink-600">{str}</span>;
}
return str;
}

function matchRedacted(wildcard: string, str: string) {
const lookup = wildcard.replace(/[.+^${}()|[\]\\]/g, "\\$&");
return new RegExp(
`^${lookup.replace(/\*/g, ".*").replace(/\?/g, ".")}$`,
"i",
).test(str);
}
4 changes: 2 additions & 2 deletions packages/app/src/components/FilePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Modal, ModalBody, ModalContent } from "@nextui-org/react";
import useSWR from "swr";
import { DataDump } from "./DataDump";
import { DataView } from "./DataView";
import { useAuth } from "../auth";
import type { StorageFile } from "@superstreamer/api/client";

Expand Down Expand Up @@ -50,7 +50,7 @@ export function FilePreview({ path, onClose }: FilePreviewProps) {

function Preview({ file }: { file: StorageFile }) {
if (file.mode === "payload") {
return <DataDump data={file.payload} />;
return <DataView data={file.payload} />;
}
if (file.mode === "url") {
if (file.type === "video") {
Expand Down
6 changes: 3 additions & 3 deletions packages/app/src/components/JobPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Card, CardBody, CardHeader } from "@nextui-org/react";
import { DataDump } from "./DataDump";
import { DataView } from "./DataView";
import { Format } from "./Format";
import { Logs } from "./Logs";
import type { Job } from "@superstreamer/api/client";
Expand Down Expand Up @@ -31,13 +31,13 @@ export function JobPage({ job, logs }: JobPageProps) {
<Card className="p-0">
<CardHeader className="p-4">Input</CardHeader>
<CardBody className="p-4 pt-0">
<DataDump data={job.inputData} />
<DataView data={job.inputData} />
</CardBody>
</Card>
<Card className="p-0">
<CardHeader className="p-4">Output</CardHeader>
<CardBody className="p-4 pt-0">
<DataDump data={job.outputData} />
{job.outputData ? <DataView data={job.outputData} /> : null}
</CardBody>
</Card>
</div>
Expand Down
82 changes: 52 additions & 30 deletions packages/app/src/components/PlayerStats.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,61 @@
import { Card } from "@nextui-org/react";
import { useEffect, useState } from "react";
import { DataView } from "./DataView";
import { usePlayer } from "../context/PlayerContext";

export function PlayerStats() {
const { player } = usePlayer();
const [state, setState] = useState({});

useEffect(() => {
if (!player) {
return;
}

const onUpdate = () => {
const state = extractPublicProps(player);
setState(state);
};

player.on("*", onUpdate);
onUpdate();

return () => {
player.off("*", onUpdate);
};
}, [player]);

return (
<Card className="h-full overflow-y-auto p-4">
<DataView
data={{
nulled: null,
undef: undefined,
obj: {
int: 10,
float: 1.5,
},
items: [
{
foo: "bar",
},
{
foo: "bar",
},
{
foo: "bar",
},
{
foo: "bar",
},
{
foo: "bar",
},
],
}}
/>
</Card>
<DataView
redacted={[
"subtitleTracks.*.track",
"audioTracks.*.track",
"qualities.*.levels",
"asset.player",
]}
data={state}
/>
);
}

function extractPublicProps(value: object) {
if (!("__proto__" in value)) {
return {};
}

const descriptors = Object.entries(
Object.getOwnPropertyDescriptors(value.__proto__),
);

const state = descriptors
// Get public getters only
.filter(([name, desc]) => !name.endsWith("_") && desc.get)
.map(([name]) => name)
// Grab each property by name and add it to an object
.reduce((acc, name) => {
// @ts-expect-error Named properties
acc[name] = player[name];
return acc;
}, {});

return state;
}
10 changes: 5 additions & 5 deletions packages/app/src/routes/(dashboard)/_layout/player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ function RouteComponent() {
<div className="h-screen p-8 flex gap-4">
<PlayerProvider>
<div className="grow flex flex-col gap-4">
<div className="bg-gray-200 rounded-lg overflow-hidden">
<div className="bg-gray-200 rounded-lg overflow-hidden shrink-0">
<div className="max-w-[500px] mx-auto">
<Player url={url} />
</div>
</div>
<Tabs
classNames={{
panel: "grow",
panel: "grow p-0",
}}
>
<Tab title="Config">
Expand All @@ -63,11 +63,11 @@ function RouteComponent() {
</Card>
</Tab>
<Tab title="Stats">
<div className="relative h-full">
<div className="absolute inset-0">
<Card className="relative h-full">
<div className="absolute inset-0 overflow-y-auto p-4">
<PlayerStats />
</div>
</div>
</Card>
</Tab>
</Tabs>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/player/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"typedoc": "typedoc --tsconfig tsconfig.typedoc.json"
},
"dependencies": {
"hls.js": "^1.6.0-beta.1",
"hls.js": "^1.6.0-beta.2",
"tseep": "^1.3.1",
"shared": "workspace:*"
},
Expand Down

0 comments on commit f2cf130

Please sign in to comment.