Skip to content

Commit

Permalink
Better data model for chunk values, and time filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarlagerlof committed Jan 15, 2024
1 parent 5de8a71 commit 6ce371b
Show file tree
Hide file tree
Showing 13 changed files with 2,157 additions and 71 deletions.
2 changes: 1 addition & 1 deletion packages/chrome-extension/public/fetch-patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ window.fetch = async (...args) => {
? Object.fromEntries(headers.entries())
: headers,
fetchStartTime,
chunkValue: value,
chunkValue: Array.from(value),
chunkStartTime,
chunkEndTime,
},
Expand Down
10 changes: 8 additions & 2 deletions packages/core/src/components/FlightResponse.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";

import { FlightResponsePanel } from "./FlightResponse";
import { createFlightResponse } from "../createFlightResponse";
import { alvarDevExampleData } from "../example-data/alvar-dev";

const meta: Meta<typeof FlightResponsePanel> = {
component: FlightResponsePanel,
Expand All @@ -9,6 +11,10 @@ const meta: Meta<typeof FlightResponsePanel> = {
export default meta;
type Story = StoryObj<typeof FlightResponsePanel>;

export const FlightResponsePanelExample: Story = {
args: {},
export const alvarDev: Story = {
name: "alvar.dev",
render: () => {
const flightResponse = createFlightResponse(alvarDevExampleData);
return <FlightResponsePanel flightResponse={flightResponse} />;
},
};
12 changes: 9 additions & 3 deletions packages/core/src/components/FlightResponse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,21 @@ export function FlightResponsePanel({
</div>
<div>
<Ariakit.TabPanel store={tab} tabId={defaultSelectedId}>
<FlightResponseTabSplit flightResponse={flightResponse} />
<ErrorBoundary FallbackComponent={GenericErrorBoundaryFallback}>
<FlightResponseTabSplit flightResponse={flightResponse} />
</ErrorBoundary>
</Ariakit.TabPanel>

<Ariakit.TabPanel store={tab}>
<FlightResponseTabNetwork flightResponse={flightResponse} />
<ErrorBoundary FallbackComponent={GenericErrorBoundaryFallback}>
<FlightResponseTabNetwork flightResponse={flightResponse} />
</ErrorBoundary>
</Ariakit.TabPanel>

<Ariakit.TabPanel store={tab}>
<FlightResponseTabRaw flightResponse={flightResponse} />
<ErrorBoundary FallbackComponent={GenericErrorBoundaryFallback}>
<FlightResponseTabRaw flightResponse={flightResponse} />
</ErrorBoundary>
</Ariakit.TabPanel>
</div>
</div>
Expand Down
14 changes: 12 additions & 2 deletions packages/core/src/components/FlightResponseTabNetwork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import {
FlightResponse,
isParsedObject,
} from "../react/ReactFlightClient";
import { useEffect, useRef } from "react";
import { useContext, useEffect, useRef } from "react";
import * as d3 from "d3";
import { EndTimeContext } from "./ViewerStreams";

interface Node extends d3.SimulationNodeDatum {
id: string;
isInTimeRange: boolean;
}

interface Link extends d3.SimulationLinkDatum<Node> {
Expand Down Expand Up @@ -51,7 +53,11 @@ export const drawNetwork = (
context.beginPath();
context.moveTo(node.x + RADIUS, node.y);
context.arc(node.x, node.y, RADIUS, 0, 2 * Math.PI);
context.fillStyle = node.id === "0" ? "#002fca" : "#001a6e";
context.fillStyle = node.isInTimeRange
? node.id === "0"
? "#002fca"
: "#001a6e"
: "#4b5563";
context.fill();
context.fillStyle = "#ffffff";
context.fillText(node.id, node.x - 5, node.y + 4);
Expand Down Expand Up @@ -182,9 +188,12 @@ export function FlightResponseTabNetwork({
}: {
flightResponse: FlightResponse;
}) {
const endTime = useContext(EndTimeContext);

const nodes: Node[] = flightResponse._chunks.map((chunk) => {
return {
id: chunk.id,
isInTimeRange: chunk.startTime <= endTime,
};
});

Expand Down Expand Up @@ -215,6 +224,7 @@ export function FlightResponseTabNetwork({
.force("collide", d3.forceCollide().radius(RADIUS))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.tick(200)

// at each iteration of the simulation, draw the network diagram with the new node positions
.on("tick", () => {
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/components/FlightResponseTabRaw.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { useContext } from "react";
import { FlightResponse } from "../react/ReactFlightClient";
import { FlightResponseChunkRaw } from "./FlightResponseChunkRaw";
import { EndTimeContext } from "./ViewerStreams";

export function FlightResponseTabRaw({
flightResponse,
}: {
flightResponse: FlightResponse;
}) {
const endTime = useContext(EndTimeContext);

const timeFilteredChunks = flightResponse._chunks.filter(
(chunk) => chunk.startTime <= endTime,
);

return (
<ul className="flex flex-col gap-4 font-code dark:text-white">
{flightResponse._chunks.map((chunk) => (
{timeFilteredChunks.map((chunk) => (
<li key={chunk.id}>
<FlightResponseChunkRaw data={chunk} />
</li>
Expand Down
17 changes: 12 additions & 5 deletions packages/core/src/components/FlightResponseTabSplit.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useTransition } from "react";
import { useContext, useState, useTransition } from "react";
import * as Ariakit from "@ariakit/react";
import { ErrorBoundary } from "react-error-boundary";
import { GenericErrorBoundaryFallback } from "./GenericErrorBoundaryFallback";
Expand All @@ -8,6 +8,7 @@ import { FlightResponseChunkModule } from "./FlightResponseChunkModule";
import { FlightResponseChunkHint } from "./FlightResponseChunkHint";
import { FlightResponseChunkModel } from "./FlightResponseChunkModel";
import { DownArrowIcon, RightArrowIcon } from "./FlightResponseIcons";
import { EndTimeContext } from "./ViewerStreams";

export function FlightResponseTabSplit({
flightResponse,
Expand Down Expand Up @@ -56,9 +57,15 @@ export function FlightResponseTabSplit({
setSelectedId: selectTab,
});

const endTime = useContext(EndTimeContext);

const timeFilteredChunks = flightResponse._chunks.filter(
(chunk) => chunk.startTime <= endTime,
);

return (
<div className="divide-y-1 dark:divide-slate-600">
{flightResponse._chunks.length === 0 ? null : (
{timeFilteredChunks.length === 0 ? null : (
<>
<div className="flex flex-col gap-2 pb-3">
<div className="text-black dark:text-white">
Expand All @@ -69,7 +76,7 @@ export function FlightResponseTabSplit({
store={tab}
className="flex flex-row flex-wrap gap-2 md:pb-0"
>
{flightResponse._chunks.map((row) => (
{timeFilteredChunks.map((row) => (
<Ariakit.Tab
className="group rounded-md border-none text-left outline outline-2 outline-offset-2 outline-transparent transition-all duration-200"
key={row.id}
Expand Down Expand Up @@ -102,15 +109,15 @@ export function FlightResponseTabSplit({
opacity: isPending ? "0.6" : "1",
}}
>
{flightResponse._chunks.length === 0 ? (
{timeFilteredChunks.length === 0 ? (
<p className="text-black dark:text-white">
Please enter a payload to see results
</p>
) : selectedTab === null || selectTab === undefined ? (
<p className="text-black dark:text-white">Please select a row</p>
) : null}

{flightResponse._chunks
{timeFilteredChunks
.filter((row) => String(row.id) == currentTab)
.map((row) => (
<ErrorBoundary
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/ViewerPayload.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react";

import { ViewerPayload } from "../viewer/ViewerPayload";
import { ViewerPayload } from "./ViewerPayload";
// import { nextJsExampleData } from "../example-data/nextjs";
import { ghNextExampleData } from "../example-data/gh-fredkiss-dev";
import { RscChunkMessage } from "../types";
Expand Down
22 changes: 15 additions & 7 deletions packages/core/src/components/ViewerStreams.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import type { Meta, StoryObj } from "@storybook/react";

import { ViewerStreams } from "./ViewerStreams";
// import { nextJsExampleData } from "../example-data/nextjs";
import { ghNextExampleData } from "../example-data/gh-fredkiss-dev";
// import { ghNextExampleData } from "../example-data/gh-fredkiss-dev";
import { alvarDevExampleData } from "../example-data/alvar-dev";
// import { neurodiversityWikiExampleData } from "../example-data/neurodiversity-wiki";

const meta: Meta<typeof ViewerStreams> = {
Expand All @@ -19,16 +20,23 @@ type Story = StoryObj<typeof ViewerStreams>;
// },
// };

export const GhNext: Story = {
name: "gh-issues.vercel.app",
args: {
messages: ghNextExampleData,
},
};
// export const GhNext: Story = {
// name: "gh-issues.vercel.app",
// args: {
// messages: ghNextExampleData,
// },
// };

// export const NeurodiversityWiki: Story = {
// name: "neurodiversity.wiki",
// args: {
// messages: neurodiversityWikiExampleData,
// },
// };

export const alvarDev: Story = {
name: "alvar.dev",
args: {
messages: alvarDevExampleData,
},
};
23 changes: 15 additions & 8 deletions packages/core/src/components/ViewerStreams.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createContext } from "react";
import { createFlightResponse } from "../createFlightResponse";
import { RscChunkMessage } from "../types";
import { FlightResponsePanel } from "./FlightResponse";
Expand All @@ -17,7 +18,7 @@ export function ViewerStreams({ messages }: { messages: RscChunkMessage[] }) {
messages,
timeScrubber.endTime,
);
const groupedMessages = useGroupedMessages(timeFilteredMessages);
const groupedMessages = useGroupedMessages(messages);

const pathTabs = useFlightResponseSelector(timeFilteredMessages, {
follow: false,
Expand All @@ -33,13 +34,19 @@ export function ViewerStreams({ messages }: { messages: RscChunkMessage[] }) {
<div className="flex h-full min-h-full flex-col gap-4">
<TimeScrubber {...timeScrubber} />

<FlightResponseSelector {...pathTabs}>
{!pathTabs.currentTab ? (
<span className="dark:text-white">Please select a url</span>
) : (
<FlightResponsePanel flightResponse={flightResponse} />
)}
</FlightResponseSelector>
<p className="dark:text-white">{timeScrubber.endTime}</p>

<EndTimeContext.Provider value={timeScrubber.endTime}>
<FlightResponseSelector {...pathTabs}>
{!pathTabs.currentTab ? (
<span className="dark:text-white">Please select a url</span>
) : (
<FlightResponsePanel flightResponse={flightResponse} />
)}
</FlightResponseSelector>
</EndTimeContext.Provider>
</div>
);
}

export const EndTimeContext = createContext<number>(0);
47 changes: 7 additions & 40 deletions packages/core/src/createFlightResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,24 @@ import { createStringDecoder } from "./react/ReactFlightClientConfigBrowser";
export function createFlightResponse(
messages: RscChunkMessage[],
): FlightResponse {
// if (messages.length === 0) {
// return null;
// }

const responseBuffer: Array<Uint8Array> = [];

for (const [index, message] of messages.entries()) {
responseBuffer[index] = new Uint8Array(
Object.keys(message.data.chunkValue).length,
);
for (const [key, value] of Object.entries(message.data.chunkValue)) {
responseBuffer[index][Number(key)] = Number(value);
}
}

// for (let i = 0; i < messages.length; i++) {
// responseBuffer[i] = new Uint8Array(
// Object.keys(messages[i].data.chunkValue).length,
// );
// for (let n = 0; n < messages[i].data.chunkValue.length; n++) {
// responseBuffer[i][n] = Number(messages[i].data.chunkValue[n]);
// }
// }

const response = {
// @ts-expect-error TODO: fix this
const response: FlightResponse = {
_buffer: [],
_rowID: 0,
_rowTag: 0,
_rowLength: 0,
_rowState: 0,
_stringDecoder: createStringDecoder(),
_chunks: [] as FlightResponse["_chunks"],
} satisfies FlightResponse;
};

response._fromJSON = createFromJSONCallback(response);

// const flightResponses = messages.map((message) => {
// return {
// _buffer: message.data.chunkValue,
// _rowID: message.data.chunkId,
// _rowLength: 1
// } satisfies FlightResponse
// })

for (const buffer of responseBuffer) {
processBinaryChunk(response, buffer);
for (let i = 0; i < messages.length; i++) {
response._currentStartTime = messages[i].data.chunkStartTime;
response._currentEndTime = messages[i].data.chunkEndTime;
processBinaryChunk(response, Uint8Array.from(messages[i].data.chunkValue));
}

// for (let i = 0; i < responseBuffer.length; i++) {
// processBinaryChunk(response, responseBuffer[i]);
// }

return response;
}
Loading

0 comments on commit 6ce371b

Please sign in to comment.