Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use request histories for the history panel #69

Merged
merged 5 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/swr-devtools-extensions/src/panel.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8"/>
<style>
html {
height: 100%;
Expand Down
2 changes: 2 additions & 0 deletions packages/swr-devtools-panel/src/components/CacheData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const CacheDataView = ({ data }: { data: any }) => {
data={data}
theme="railscasts"
invertTheme={!matchMedia("(prefers-color-scheme: dark)").matches}
hideRoot
shouldExpandNode={(_keyPath, _data, level) => level < 3}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React, { useState } from "react";
import styled from "styled-components";
import { Cache } from "swr";

import { PanelType } from "./SWRDevToolPanel";
import { CacheData } from "./CacheData";
import { CacheKey } from "./CacheKey";
import { useDevToolsCache } from "../devtools-cache";
import { SearchInput } from "./SearchInput";
import { DevToolsCacheData } from "swr-devtools/lib/swr-cache";

export const Panel = ({
export const CachePanel = ({
cacheData,
type,
selectedItemKey,
Expand Down
145 changes: 145 additions & 0 deletions packages/swr-devtools-panel/src/components/HistoryPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import React, { useState } from "react";
import styled from "styled-components";
import { CacheData } from "./CacheData";

const TYPE_MAP = {
success: "✅",
ongoing: "🏃‍♂️",
error: "❌",
};

export const HistoryPanel = ({
tracks,
selectedItem,
onSelectedItem,
}: {
tracks: any[];
selectedItem: any;
onSelectedItem: (data: any) => void;
}) => {
const histories = tracks.flatMap((track) => track.items);
histories.sort((a, b) => {
if (a.data.startTime < b.data.startTime) return 1;
if (a.data.startTime > b.data.startTime) return -1;
return 0;
});
return (
<PanelWrapper>
<PanelItem>
<CacheItems>
{histories.map((track) => (
<CacheItem
key={track.key}
isSelected={selectedItem && selectedItem.id === track.data.id}
>
<CacheItemButton
onClick={() => {
if (
track.data.type === "success" ||
track.data.type === "error"
) {
onSelectedItem({
...track.data,
timestamp: track.data.endTime,
timestampString: formatTime(track.data.endTime),
});
}
}}
>
<CacheText>
<div>{track.data.key}</div>
{/* @ts-expect-error */}
<Labels>{TYPE_MAP[track.data.type]}</Labels>
</CacheText>
<Timestamp>{formatTime(track.data.startTime)}</Timestamp>
</CacheItemButton>
</CacheItem>
))}
</CacheItems>
</PanelItem>
<VerticalDivider />
<PanelItem>
{selectedItem && <CacheData devToolsCacheData={selectedItem} />}
</PanelItem>
</PanelWrapper>
);
};

const formatTime = (date: Date) =>
`${String(date.getHours()).padStart(2, "0")}:${String(
date.getMinutes()
).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}`;

const PanelWrapper = styled.section`
box-sizing: border-box;
display: flex;
justify-content: space-around;
padding: 0;
height: 100%;
border-top: solid 1px var(--swr-devtools-border-color);
`;

const PanelItem = styled.div`
flex: 1;
overflow: auto;
`;

const CacheItems = styled.ul`
margin: 0;
list-style: none;
padding-inline-start: 0;
`;

const CacheItem = styled.li<{ isSelected: boolean }>`
padding: 0;
border-bottom: solid 1px var(--swr-devtools-border-color);
background-color: ${(props) =>
props.isSelected ? "var(--swr-devtools-selected-bg-color)" : "none"};
&:hover {
background-color: ${(props) =>
props.isSelected
? "var(--swr-devtools-selected-bg-color)"
: "var(--swr-devtools-hover-bg-color)"};
}
`;

const VerticalDivider = styled.div`
background-color: var(--swr-devtools-border-color);
width: 1px;
`;

const CacheText = styled.div`
display: inline-flex;
align-items: center;
justify-content: space-between;
margin-right: auto;
flex: 1;
padding-left: 8px;
min-height: 2em;
`;

const CacheItemButton = styled.button`
display: flex;
align-items: center;
gap: 2px;
width: 100%;
height: 100%;
padding: 0.2rem 0;
border: none;
background: transparent;
color: var(--swr-devtools-text-color);
cursor: pointer;
text-align: left;
`;

const Timestamp = styled.span`
margin-right: 8px;
`;

const Labels = styled.div`
display: flex;
gap: 4px;
align-items: center;
margin-left: 8px;
margin-right: 4px;
`;
32 changes: 26 additions & 6 deletions packages/swr-devtools-panel/src/components/NetworkPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { MouseEvent, useCallback, useState } from "react";
import styled from "styled-components";
import { Cache } from "swr";
import { EventEmitter, RequestsById, useRequests, useTracks } from "../request";
import { CacheData } from "./CacheData";

import { PanelType } from "./SWRDevToolPanel";
import { Timeline } from "./timeline";
Expand All @@ -12,6 +13,11 @@ function formatTime(time: number, step: number) {
return time + "ms";
}

const formatDateTime = (date: Date) =>
`${String(date.getHours()).padStart(2, "0")}:${String(
date.getMinutes()
).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}`;

export const NetworkPanel = ({
requestsById,
tracks,
Expand All @@ -21,7 +27,7 @@ export const NetworkPanel = ({
tracks: any[];
startTime: number;
}) => {
const [requestDetail, setRequestDetail] = useState<null | string>(null);
const [requestDetail, setRequestDetail] = useState<null | any>(null);

const [trackScale, setTrackScale] = React.useState(5);
const [timelineHoverX, setTimelineHoverX] = React.useState(-1);
Expand All @@ -46,8 +52,10 @@ export const NetworkPanel = ({
<PanelWrapper>
{requestDetail ? (
<Detail>
{requestDetail}
<button onClick={() => setRequestDetail(null)}>Close</button>
<CacheData devToolsCacheData={requestDetail} />
<CloseButtonWrapper>
<button onClick={() => setRequestDetail(null)}>Close</button>
</CloseButtonWrapper>
</Detail>
) : null}
<TimelineWrapper>
Expand Down Expand Up @@ -119,7 +127,13 @@ export const NetworkPanel = ({
<Request
title={`(${item.data.type}) ` + item.data.key}
type={item.data.type}
onClick={() => setRequestDetail(JSON.stringify(item.data))}
onClick={() =>
setRequestDetail({
...item.data,
timestamp: item.data.endTime,
timestampString: formatDateTime(item.data.endTime),
})
}
>
{item.data.key}
</Request>
Expand Down Expand Up @@ -228,16 +242,22 @@ const TrackLabel = styled.div<{ i: number }>`

const Detail = styled.div`
position: absolute;
background: white;
background: var(--swr-devtools-network-panel-bg-color);
z-index: 2;
height: 70%;
top: 15%;
padding: 10px;
overflow: scroll;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 0 3px 10px #0000001a;
border: 1px solid #0000001a;
max-width: 500px;
width: 50%;
`;

const CloseButtonWrapper = styled.div`
text-align: center;
padding: 10px;
`;

const Header = styled.div`
Expand Down
18 changes: 12 additions & 6 deletions packages/swr-devtools-panel/src/components/SWRDevToolPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Cache } from "swr";
import { NetworkPanel } from "./NetworkPanel";
import { DevToolsCacheData } from "swr-devtools/lib/swr-cache";

import { Panel } from "./Panel";
import { CachePanel } from "./CachePanel";
import { HistoryPanel } from "./HistoryPanel";
import { Tab } from "./Tab";
import { EventEmitter, useRequests, useTracks } from "../request";
import { useDevToolsCache } from "../devtools-cache";
Expand Down Expand Up @@ -79,11 +80,12 @@ export const SWRDevToolPanel = ({ cache, events }: Props) => {
const [activePanel, setActivePanel] = useState<Panel["key"]>("current");
const [selectedDevToolsCacheData, selectDevToolsCacheData] =
useState<DevToolsCacheData | null>(null);
const [selectedHistoryData, setSelectedHistoryData] = useState<any>(null);

const requestsById = useRequests(events);
const tracks = useTracks(requestsById);
const startTime = useState(() => Date.now())[0];
const [currentCacheData, historyCacheData] = useDevToolsCache(cache);
const [cacheData] = useDevToolsCache(cache);

return (
<DevToolWindow>
Expand Down Expand Up @@ -116,11 +118,15 @@ export const SWRDevToolPanel = ({ cache, events }: Props) => {
tracks={tracks}
startTime={startTime}
/>
) : activePanel === "history" ? (
<HistoryPanel
tracks={tracks}
selectedItem={selectedHistoryData}
onSelectedItem={(data: any) => setSelectedHistoryData(data)}
/>
) : (
<Panel
cacheData={
activePanel === "current" ? currentCacheData : historyCacheData
}
<CachePanel
cacheData={cacheData}
type={activePanel}
selectedItemKey={selectedDevToolsCacheData}
onSelectItem={selectDevToolsCacheData}
Expand Down
15 changes: 14 additions & 1 deletion packages/swr-devtools-panel/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type SWRRequest = {
type: "success" | "error" | "discarded" | "ongoing";
startTime: Date;
endTime: Date | null;
data?: any;
error?: any;
};

export type RequestsById = Record<string, SWRRequest[]>;
Expand All @@ -25,7 +27,15 @@ export function useRequests(events: EventEmitter | null) {
if (events === null) return;

return events.subscribe(
(type, { id, key }: { id: number; key: string }) => {
(
type,
{
id,
key,
data,
error,
}: { id: number; key: string; data?: any; error?: any }
) => {
setRequestsById((currentRequestsByKey) => {
let channelKey = key;
let channelNum = 0;
Expand Down Expand Up @@ -65,6 +75,8 @@ export function useRequests(events: EventEmitter | null) {

activeRequests[id].type = "success";
activeRequests[id].endTime = new Date();
activeRequests[id].data = data;

delete activeRequests[id];
delete activeRequests[channelKey];

Expand All @@ -77,6 +89,7 @@ export function useRequests(events: EventEmitter | null) {

activeRequests[id].type = "error";
activeRequests[id].endTime = new Date();
activeRequests[id].error = error;
delete activeRequests[id];
delete activeRequests[channelKey];

Expand Down
6 changes: 6 additions & 0 deletions packages/swr-devtools/src/createSWRDevTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ export type DevToolsMessage =
payload: {
key: string;
id: number;
data: any;
};
}
| {
type: "request_error";
payload: {
key: string;
id: number;
error: any;
};
}
| {
Expand Down Expand Up @@ -186,13 +188,15 @@ export const createSWRDevtools = () => {
events.emit("request_success", {
key: unstable_serialize(args[1]),
id: requestIdRef.current,
data: convertToSerializableObject(args[0]),
});
window.postMessage(
{
type: "request_success",
payload: {
key: unstable_serialize(args[1]),
id: requestIdRef.current,
data: convertToSerializableObject(args[0]),
},
},
"*"
Expand All @@ -203,13 +207,15 @@ export const createSWRDevtools = () => {
events.emit("request_error", {
key: unstable_serialize(args[1]),
id: requestIdRef.current,
error: convertToSerializableObject(args[0]),
});
window.postMessage(
{
type: "request_error",
payload: {
key: unstable_serialize(args[1]),
id: requestIdRef.current,
error: convertToSerializableObject(args[0]),
},
},
"*"
Expand Down