summaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <tom@vanderlee.io>2021-12-30 09:51:00 +0100
committerGravatar Tom van der Lee <tom@vanderlee.io>2022-01-11 00:00:22 +0100
commitbcb77d979d817e1e609adb4d007bbbcc3f61efbd (patch)
tree093c5a2914ee0f6e1ec559b3b98725190fee7285 /src/components
downloadclient-1.0.0.tar.gz
client-1.0.0.tar.bz2
client-1.0.0.zip
Prepare for githubv1.0.0
Diffstat (limited to 'src/components')
-rw-r--r--src/components/App/App.module.scss55
-rw-r--r--src/components/App/App.tsx68
-rw-r--r--src/components/Content/Content.module.scss51
-rw-r--r--src/components/Content/Content.tsx100
-rw-r--r--src/components/Details/Details.module.scss84
-rw-r--r--src/components/Details/Details.tsx148
-rw-r--r--src/components/RequestSummary/RequestSummary.module.scss24
-rw-r--r--src/components/RequestSummary/RequestSummary.tsx33
8 files changed, 563 insertions, 0 deletions
diff --git a/src/components/App/App.module.scss b/src/components/App/App.module.scss
new file mode 100644
index 0000000..2036eb9
--- /dev/null
+++ b/src/components/App/App.module.scss
@@ -0,0 +1,55 @@
1.app {
2 display: flex;
3 flex-flow: column nowrap;
4 grid-template-rows: auto 1fr;
5 height: 100vh;
6 overflow: hidden;
7}
8
9.main {
10 display: flex;
11 flex-flow: row nowrap;
12 flex-grow: 1;
13 overflow: hidden;
14}
15
16.header {
17 font-size: 1.2em;
18 display: flex;
19 flex-flow: row nowrap;
20 align-items: center;
21 justify-content: space-between;
22 background: black;
23 color: white;
24 padding: 1em;
25
26 a {
27 color: white;
28 }
29}
30
31.sidebar {
32 width: calc((6 / 16) * 100%);
33 height: 100%;
34 grid-area: sidebar;
35 border-right: 1px solid black;
36 overflow-y: auto;
37
38 li {
39 border-bottom: 1px solid gray;
40 }
41}
42
43.details {
44 width: calc((10 / 16) * 100%);
45 overflow: hidden;
46 height: 100%;
47}
48
49.noRequest, .noRequestSelected {
50 width: 100%;
51 height: 100%;
52 display: flex;
53 justify-content: center;
54 align-items: center;
55}
diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx
new file mode 100644
index 0000000..3a7fe9b
--- /dev/null
+++ b/src/components/App/App.tsx
@@ -0,0 +1,68 @@
1import * as React from "react";
2import useRequests, {RequestResponse} from "../../hooks/useRequests";
3import {useEffect, useMemo, useState} from "react";
4
5import styles from './App.module.scss';
6import Details from "../Details/Details";
7import RequestSummary from "../RequestSummary/RequestSummary";
8import {getHost} from "../../utils";
9
10interface Config {
11 url: string
12}
13
14export default function App() {
15 const [config, setConfig]= useState<Config | null>(null)
16 useEffect(() => {
17 fetch(`http://${getHost()}/config/`)
18 .then(response => response.json() as Promise<Config>)
19 .then(setConfig)
20 }, [])
21
22 const requests = useRequests();
23 const [selectedRequestIndex, setSelectedRequestIndex] = useState<number | null>(null);
24 const selectedRequest = useMemo<RequestResponse | null>(() => (
25 selectedRequestIndex === null
26 ? null
27 : requests[selectedRequestIndex]
28 ), [selectedRequestIndex, requests]);
29
30 return config && (
31 <div className={styles.app}>
32 <header className={styles.header}>
33 TTUN
34 <a href={config.url} target="_blank">{config.url}</a>
35 </header>
36 <main className={styles.main}>
37 <ul className={styles.sidebar}>
38 {
39 requests.length > 0
40 ? requests.slice(0).reverse().map((requestResponse, index) => (
41 <li onClick={() => setSelectedRequestIndex(requests.length - index - 1)} key={`request-${index}`}>
42 <RequestSummary requestResponse={requestResponse} />
43 </li>
44 ))
45 : (
46 <div className={styles.noRequest}>
47 <p>No requests</p>
48 </div>
49 )
50 }
51 </ul>
52
53 <div className={styles.details}>
54 {
55 selectedRequest !== null
56 ? (
57 <Details requestResponse={selectedRequest} />
58 ) : (
59 <div className={styles.noRequestSelected}>
60 <p>Select a request to inspect it</p>
61 </div>
62 )
63 }
64 </div>
65 </main>
66 </div>
67 );
68}
diff --git a/src/components/Content/Content.module.scss b/src/components/Content/Content.module.scss
new file mode 100644
index 0000000..8908516
--- /dev/null
+++ b/src/components/Content/Content.module.scss
@@ -0,0 +1,51 @@
1.content {
2 width: 100%;
3 height: 100%;
4 display: flex;
5 flex-flow: column nowrap;
6 overflow: hidden;
7}
8
9.header {
10 flex-shrink: 0;
11 flex-grow: 0;
12 width: 100%;
13 display: flex;
14 padding: 0.5em;
15 background-color: black;
16 color: white;
17}
18
19.body {
20 flex-grow: 1;
21 flex-shrink: 1;
22 overflow-y: auto;
23
24 pre {
25 width: 100%;
26 height: 100%;
27 padding: 1em;
28 font-family: monospace;
29 overflow: auto;
30 }
31
32 iframe {
33 height: 100%;
34 width: 100%;
35 }
36}
37
38.renderError {
39 width: 100%;
40 height: 100%;
41 display: flex;
42 flex-flow: column nowrap;
43 justify-content: center;
44 align-items: center;
45
46 a {
47 margin-top: 1em;
48 text-decoration: underline;
49 color: blue;
50 }
51}
diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx
new file mode 100644
index 0000000..a7b5949
--- /dev/null
+++ b/src/components/Content/Content.tsx
@@ -0,0 +1,100 @@
1import styles from "~components/Details/Details.module.scss";
2import * as React from "react";
3import classNames from "classnames";
4import {RequestPayload, ResponsePayload} from "~hooks/useRequests";
5import {
6 Dispatch,
7 forwardRef, SetStateAction,
8 useEffect,
9 useImperativeHandle,
10 useMemo,
11 useRef,
12 useState
13} from "react";
14import ReactJson from 'react-json-view';
15import styles from './Content.module.scss';
16
17interface ContentProps {
18 data: RequestPayload | ResponsePayload
19 setRaw: Dispatch<SetStateAction<boolean>>
20 raw?: boolean
21}
22
23export default function Content({ raw, setRaw, ...props }: ContentProps): JSX.Element {
24 return (
25 <div className={styles.content}>
26 <div className={styles.header}>
27 <input id='raw' type='checkbox' checked={raw} onChange={() => setRaw(!raw)}/>
28 <label htmlFor='raw'>Raw</label>
29 </div>
30 <div className={styles.body}>
31 {(() => {
32 try {
33 return ContentBody({ ...props, raw })
34 } catch {
35 return (
36 <div className={styles.renderError}>
37 <p>Body could not be rendered</p>
38 <a onClick={() => setRaw(true)}>View raw</a>
39 </div>
40 )
41 }
42 })()}
43 </div>
44 </div>
45 )
46};
47
48function ContentBody({ data, raw = false }: Omit<ContentProps, 'setRaw'>) {