Skip to content

Commit edc4650

Browse files
authored
Add flexlayout (#22)
1 parent 1528c89 commit edc4650

13 files changed

+231
-46
lines changed

.pnp.cjs

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.
Binary file not shown.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"@types/chrome": "^0.0.171",
1212
"@types/node": "^17.0.0",
1313
"@types/react": "17.0.26",
14+
"flexlayout-react": "^0.7.3",
1415
"jotai": "^1.4.8",
1516
"next": "11.1.2",
1617
"normalize.css": "^8.0.1",

src/pages/_app.page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { AppProps } from "next/app";
22
import "normalize.css/normalize.css";
33
import "open-color/open-color.css";
44
import "./_app.scss";
5+
import "flexlayout-react/style/dark.scss";
56

67
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
78
return <Component {...pageProps} />;

src/pages/_app.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@
2727
}
2828
}
2929

30+
#__next {
31+
height: 100%;
32+
}
33+
3034
body {
3135
color: var(--pb-fg);
36+
background: var(--pb-bg);
3237
max-height: 100vh;
3338
}
3439

src/pages/index.module.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.main-panel {
22
display: flex;
3+
height: 100%;
34
}
45

56
.side-page {
@@ -22,12 +23,13 @@
2223
}
2324

2425
.main-page {
26+
display: flex;
27+
flex-direction: column;
2528
flex: 1;
2629
}
2730

2831
.request-list {
29-
display: flex;
30-
flex-direction: column;
32+
height: 100%;
3133

3234
background-color: var(--oc-gray-2);
3335
border-right: 1px solid var(--pb-sep);

src/pages/index.page.tsx

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import type { NextPage } from "next";
2-
import { useEffect } from "react";
2+
import { useEffect, useRef } from "react";
33
import { useAtom } from "jotai";
44
import { useUpdateAtom } from "jotai/utils";
55
import style from "./index.module.scss";
66
import Events from "../Events";
77
import {
8+
requestsAtom,
89
updateRequestAtom,
910
updateRequestErrorAtom,
1011
updateRequestPayloadAtom,
@@ -21,9 +22,54 @@ import Settings from "./index/Settings";
2122
import Experimental from "./index/Experimental";
2223
import SidePage from "./index/SidePage";
2324
import { sidePageStatusAtom } from "./index/atoms/page";
25+
import * as FlexLayout from "flexlayout-react";
26+
27+
const json: FlexLayout.IJsonModel = {
28+
global: {
29+
borderEnableDrop: false,
30+
},
31+
borders: [
32+
{
33+
type: "border",
34+
location: "left",
35+
selected: 0,
36+
children: [
37+
{
38+
type: "tab",
39+
enableDrag: false,
40+
enableClose: false,
41+
name: "Requests",
42+
component: "RequestList",
43+
},
44+
],
45+
},
46+
],
47+
layout: {
48+
type: "row",
49+
weight: 100,
50+
children: [
51+
{
52+
id: "RequestDetail",
53+
type: "tabset",
54+
weight: 50,
55+
children: [
56+
{
57+
type: "tab",
58+
enableClose: false,
59+
name: "Detail",
60+
component: "RequestDetail",
61+
},
62+
],
63+
},
64+
],
65+
},
66+
};
67+
const model = FlexLayout.Model.fromJson(json);
2468

2569
const Page: NextPage = () => {
70+
const layoutRef = useRef<FlexLayout.Layout>(null);
2671
const [isSidePageOpened] = useAtom(sidePageStatusAtom);
72+
const [requests] = useAtom(requestsAtom);
2773
useDevtoolsCommunicationLogic();
2874
return (
2975
<div className={style["main-panel"]}>
@@ -37,11 +83,38 @@ const Page: NextPage = () => {
3783
<Settings />
3884
{process.env.NODE_ENV === "development" && <Experimental />}
3985
</div>
40-
<div className={style["request-page"]}>
41-
<div className={style["request-list"]}>
42-
<RequestList />
43-
</div>
44-
<RequestDetail />
86+
<div style={{ position: "relative", flex: 1 }}>
87+
<FlexLayout.Layout
88+
ref={layoutRef}
89+
model={model}
90+
factory={(node) => {
91+
const component = node.getComponent();
92+
switch (component) {
93+
case "RequestList": {
94+
return (
95+
<div className={style["request-list"]}>
96+
<RequestList
97+
onRequestDragMouseDown={(key, name) => {
98+
layoutRef.current?.addTabWithDragAndDrop(name, {
99+
id: key,
100+
component: "RequestDetail",
101+
name,
102+
});
103+
}}
104+
/>
105+
</div>
106+
);
107+
}
108+
case "RequestDetail": {
109+
const id = node.getId();
110+
if (id) {
111+
return <RequestDetail requestAtom={requests[id]} />;
112+
}
113+
return <RequestDetail />;
114+
}
115+
}
116+
}}
117+
/>
45118
</div>
46119
</div>
47120
</div>

src/pages/index/RequestDetail/index.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.request-detail {
2+
height: 100%;
23
@media (prefers-color-scheme: dark) {
34
background-color: var(--oc-gray-9);
45
}

src/pages/index/RequestDetail/index.tsx

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import { memo } from "react";
2-
import { useAtom } from "jotai";
2+
import { Atom, useAtom } from "jotai";
33
import { selectedRequestAtom } from "../atoms/ui";
4+
import { Request } from "../atoms/request";
45
import style from "./index.module.scss";
56
import Tabs from "../../../components/Tabs";
67
import JsonView from "../../../components/JsonView";
78

8-
interface RequestDetailProps {}
9-
const RequestDetail: React.FC<RequestDetailProps> = () => {
10-
const [selectedRequest] = useAtom(selectedRequestAtom);
9+
interface RequestDetailProps {
10+
requestAtom?: Atom<Request | undefined>;
11+
}
12+
const RequestDetail: React.FC<RequestDetailProps> = ({
13+
requestAtom = selectedRequestAtom,
14+
}) => {
15+
const [selectedRequest] = useAtom(requestAtom);
16+
console.log(selectedRequest);
1117
if (!selectedRequest) {
1218
return <div className={style["request-detail"]}></div>;
1319
}
@@ -17,11 +23,13 @@ const RequestDetail: React.FC<RequestDetailProps> = () => {
1723
tabs={{
1824
request: {
1925
label: () => "Request",
20-
Component: RequestDetailRequest,
26+
Component: () => <RequestDetailRequest requestAtom={requestAtom} />,
2127
},
2228
response: {
2329
label: () => "Response",
24-
Component: RequestDetailResponse,
30+
Component: () => (
31+
<RequestDetailResponse requestAtom={requestAtom} />
32+
),
2533
},
2634
}}
2735
/>
@@ -30,8 +38,10 @@ const RequestDetail: React.FC<RequestDetailProps> = () => {
3038
};
3139
export default memo(RequestDetail);
3240

33-
const RequestDetailRequest: React.FC = () => {
34-
const [selectedRequest] = useAtom(selectedRequestAtom);
41+
const RequestDetailRequest: React.FC<RequestDetailProps> = ({
42+
requestAtom = selectedRequestAtom,
43+
}) => {
44+
const [selectedRequest] = useAtom(requestAtom);
3545
if (!selectedRequest) return null;
3646
const [requestPayloads] = useAtom(selectedRequest.requestPayloadsAtom);
3747
const { requestError } = selectedRequest;
@@ -59,8 +69,10 @@ const RequestDetailRequest: React.FC = () => {
5969
);
6070
};
6171

62-
const RequestDetailResponse: React.FC = () => {
63-
const [selectedRequest] = useAtom(selectedRequestAtom);
72+
const RequestDetailResponse: React.FC<RequestDetailProps> = ({
73+
requestAtom = selectedRequestAtom,
74+
}) => {
75+
const [selectedRequest] = useAtom(requestAtom);
6476
if (!selectedRequest) return null;
6577
const { headerJson, trailerJson, responseError } = selectedRequest;
6678
const [responsePayloads] = useAtom(selectedRequest.responsePayloadsAtom);

src/pages/index/RequestList/index.module.scss

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,48 @@
2626
text-overflow: ellipsis;
2727
}
2828

29-
.list-status {
29+
.list-right {
3030
flex-shrink: 0;
31-
position: relative;
32-
color: var(--pb-fg-active);
31+
display: flex;
32+
flex-direction: row;
3333

34-
.payload-circle {
35-
background-color: var(--oc-green-8);
36-
}
34+
.list-status {
35+
flex-shrink: 0;
36+
position: relative;
37+
color: var(--pb-fg-active);
3738

38-
.error-circle {
39-
background-color: var(--oc-red-8);
40-
}
39+
.payload-circle {
40+
background-color: var(--oc-green-8);
41+
}
4142

42-
.payload-circle,
43-
.error-circle {
44-
margin-left: 0.25em;
43+
.error-circle {
44+
background-color: var(--oc-red-8);
45+
}
4546

46-
position: relative;
47-
display: flex;
48-
align-items: center;
49-
justify-content: center;
50-
width: 1em;
51-
height: 1em;
52-
border-radius: 50%;
47+
.payload-circle,
48+
.error-circle {
49+
margin-left: 0.25em;
50+
51+
position: relative;
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
width: 1em;
56+
height: 1em;
57+
border-radius: 50%;
58+
}
59+
}
60+
61+
.drag-area {
62+
margin-left: 0.5em;
63+
width: 6px;
64+
height: 23px;
65+
background-color: currentColor;
66+
opacity: 0.3;
67+
margin-top: -1px;
68+
border: 3px solid;
69+
border-radius: 999px;
70+
cursor: grab;
5371
}
5472
}
5573
}

0 commit comments

Comments
 (0)