summaryrefslogtreecommitdiffstats
path: root/src/components/Content
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <tom@vanderlee.io>2022-02-12 11:33:52 +0100
committerGravatar Tom van der Lee <tom@vanderlee.io>2022-02-12 11:33:52 +0100
commit871a85d9343cf49646d13dc455c062efadcb959a (patch)
tree7d36b14b237719901d71d58c88f74b87b875ee61 /src/components/Content
parent7c48533571e9f9d3731a59433a56cc8d6e008123 (diff)
downloadclient-871a85d9343cf49646d13dc455c062efadcb959a.tar.gz
client-871a85d9343cf49646d13dc455c062efadcb959a.tar.bz2
client-871a85d9343cf49646d13dc455c062efadcb959a.zip
Beatified codev1.3.0
Diffstat (limited to 'src/components/Content')
-rw-r--r--src/components/Content/Content.tsx167
1 files changed, 94 insertions, 73 deletions
diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx
index c7a5f58..56a802f 100644
--- a/src/components/Content/Content.tsx
+++ b/src/components/Content/Content.tsx
@@ -1,120 +1,141 @@
1import * as React from "react"; 1import * as React from "react";
2import {Dispatch, SetStateAction, useContext, useMemo} from "react"; 2import { Dispatch, SetStateAction, useContext, useMemo } from "react";
3import {RequestPayload, ResponsePayload, Headers} from "~hooks/useRequests"; 3import { RequestPayload, ResponsePayload, Headers } from "~hooks/useRequests";
4import ReactJson from 'react-json-view'; 4import ReactJson from "react-json-view";
5import styles from './Content.module.scss'; 5import styles from "./Content.module.scss";
6import {Button, Col, Container, Row} from "react-bootstrap"; 6import { Button, Col, Container, Row } from "react-bootstrap";
7import {DarkModeContext} from "../../contexts/DarkMode"; 7import { DarkModeContext } from "../../contexts/DarkMode";
8 8
9function getHeader(headers: Headers, key: string, unit?: string): string | null { 9function getHeader(
10 headers: Headers,
11 key: string,
12 unit?: string
13): string | null {
10 try { 14 try {
11 const [_, value] = headers.find(([headerKey]) => headerKey.toLowerCase() === key.toLowerCase()) 15 const [_, value] = headers.find(
12 return unit !== undefined 16 ([headerKey]) => headerKey.toLowerCase() === key.toLowerCase()
13 ? `${value}${unit}` 17 );
14 : value 18 return unit !== undefined ? `${value}${unit}` : value;
15 } catch { 19 } catch {
16 return null; 20 return null;
17 } 21 }
18} 22}
19 23
20interface ContentProps { 24interface ContentProps {
21 data: RequestPayload | ResponsePayload 25 data: RequestPayload | ResponsePayload;
22 setRaw: Dispatch<SetStateAction<boolean>> 26 setRaw: Dispatch<SetStateAction<boolean>>;
23 raw?: boolean 27 raw?: boolean;
24} 28}
25 29
26export default function Content({ raw, setRaw, data }: ContentProps): JSX.Element { 30export default function Content({
31 raw,
32 setRaw,
33 data,
34}: ContentProps): JSX.Element {
27 return ( 35 return (
28 <div className={styles.content}> 36 <div className={styles.content}>
29 <Container fluid className="border-bottom"> 37 <Container fluid className="border-bottom">
30 <Row className="py-3"> 38 <Row className="py-3">
31 <Col className="form-check form-switch ms-3"> 39 <Col className="form-check form-switch ms-3">
32 <input className="form-check-input" id='raw' type='checkbox' checked={raw} role="switch" onChange={() => setRaw(!raw)}/> 40 <input
33 <label htmlFor='raw' className="form-check-label">Raw</label> 41 className="form-check-input"
34 </Col> 42 id="raw"
43 type="checkbox"
44 checked={raw}
45 role="switch"
46 onChange={() => setRaw(!raw)}
47 />
48 <label htmlFor="raw" className="form-check-label">
49 Raw
50 </label>
51 </Col>
35 <Col xs="auto"> 52 <Col xs="auto">
36 { 53 {[
37 [ 54 getHeader(data.headers, "content-length", "bytes"),
38 getHeader(data.headers, 'content-length', 'bytes'), 55 getHeader(data.headers, "content-type"),
39 getHeader(data.headers, 'content-type'), 56 ]
40 ].filter(x => x !== null).join('; ') 57 .filter((x) => x !== null)
41 } 58 .join("; ")}
42 </Col> 59 </Col>
43 </Row> 60 </Row>
44 </Container> 61 </Container>
45 <Row className={styles.body}> 62 <Row className={styles.body}>
46 {(() => { 63 {(() => {
47 try { 64 try {
48 return ContentBody({ data, raw }) 65 return ContentBody({ data, raw });
49 } catch { 66 } catch {
50 return ( 67 return (
51 <div className={styles.renderError}> 68 <div className={styles.renderError}>
52 <p>Body could not be rendered</p> 69 <p>Body could not be rendered</p>
53 <Button variant="link" onClick={() => setRaw(true)}>View raw</Button> 70 <Button variant="link" onClick={() => setRaw(true)}>
71 View raw
72 </Button>
54 </div> 73 </div>
55 ) 74 );
56 } 75 }
57 })()} 76 })()}
58 </Row> 77 </Row>
59 </div > 78 </div>
60 ) 79 );
61}; 80}
62
63function ContentBody({ data, raw = false }: Omit<ContentProps, 'setRaw'>) {
64 const { darkMode } = useContext(DarkModeContext);
65 const contentType = useMemo(() => {
66 if (raw) {
67 return '';
68 }
69
70 const type = getHeader(data.headers, 'content-type');
71 return type.toLowerCase().split(';')[0];
72 }, [data, raw]);
73 81
82function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) {
83 const { darkMode } = useContext(DarkModeContext);
84 const contentType = useMemo(() => {
74 if (raw) { 85 if (raw) {
75 return ( 86 return "";
76 <pre className="mb-0">
77 <code>
78 {atob(data.body)}
79 </code>
80 </pre>
81 )
82 } 87 }
83 88
84 if (['application/pdf', 'text/html'].includes(contentType)) { 89 const type = getHeader(data.headers, "content-type");
85 return <iframe 90 return type.toLowerCase().split(";")[0];
91 }, [data, raw]);
92
93 if (raw) {
94 return (
95 <pre className="mb-0">
96 <code>{atob(data.body)}</code>
97 </pre>
98 );
99 }
100
101 if (["application/pdf", "text/html"].includes(contentType)) {
102 return (
103 <iframe
86 className="bg-white" 104 className="bg-white"
87 src={`data:${contentType};base64,${data.body}`} 105 src={`data:${contentType};base64,${data.body}`}
88 srcDoc={contentType === 'text/html' ? atob(data.body) : undefined} 106 srcDoc={contentType === "text/html" ? atob(data.body) : undefined}
89 loading='lazy' 107 loading="lazy"
90 sandbox='' 108 sandbox=""
91 /> 109 />
92 } 110 );
111 }
93 112
94 if (contentType.startsWith('application/json')) { 113 if (contentType.startsWith("application/json")) {
95 return <ReactJson 114 return (
115 <ReactJson
96 src={JSON.parse(atob(data.body))} 116 src={JSON.parse(atob(data.body))}
97 theme={darkMode ? "monokai" : undefined} 117 theme={darkMode ? "monokai" : undefined}
98 style={{ 118 style={{
99 padding: '1em', 119 padding: "1em",
100 width: '100%', 120 width: "100%",
101 height: '100%', 121 height: "100%",
102 overflowY: 'auto', 122 overflowY: "auto",
103 }} 123 }}
104 /> 124 />
105 } 125 );
126 }
106 127
107 if (contentType.startsWith('audio')) { 128 if (contentType.startsWith("audio")) {
108 return <audio src={`data:${contentType};base64,${data.body}`} /> 129 return <audio src={`data:${contentType};base64,${data.body}`} />;
109 } 130 }
110 131
111 if (contentType.startsWith('video')) { 132 if (contentType.startsWith("video")) {
112 return <video src={`data:${contentType};base64,${data.body}`} /> 133 return <video src={`data:${contentType};base64,${data.body}`} />;
113 } 134 }
114 135
115 if (contentType.startsWith('image')) { 136 if (contentType.startsWith("image")) {
116 return <img src={`data:${contentType};base64,${data.body}`} alt=''/> 137 return <img src={`data:${contentType};base64,${data.body}`} alt="" />;
117 } 138 }
118 139