Skip to content

Commit 353bc2e

Browse files
authored
[UI Enhancement] Refactor include status code in response (#476)
* Refactor include status code in response * Use inline styles to avoid double scrollbars * Fix linter errors * Match ApiTabs styles * Adjust dot size * Conditionally render tabs based on code
1 parent 46ecab6 commit 353bc2e

File tree

7 files changed

+126
-11
lines changed

7 files changed

+126
-11
lines changed

demo/docusaurus.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ const config = {
235235
template: "api.mustache", // Customize API MDX with mustache template
236236
downloadUrl:
237237
"https://raw.githubusercontent.com/PaloAltoNetworks/docusaurus-openapi-docs/main/demo/examples/petstore.yaml",
238-
hideSendButton: true,
238+
hideSendButton: false,
239239
},
240240
cos: {
241241
specPath: "examples/openapi-cos.json",

packages/docusaurus-theme-openapi-docs/src/theme-openapi.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ declare module "@theme/ApiDemoPanel/Response" {
213213
}
214214

215215
declare module "@theme/ApiDemoPanel/Response/slice" {
216-
export { setResponse };
216+
export { setResponse, setCode, setHeaders, clearCode, clearHeaders };
217217
export default response as Reducer<State, AnyAction>;
218218
}
219219

packages/docusaurus-theme-openapi-docs/src/theme/ApiDemoPanel/Execute/index.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ import React from "react";
1010
import sdk from "@paloaltonetworks/postman-collection";
1111
import buildPostmanRequest from "@theme/ApiDemoPanel/buildPostmanRequest";
1212
import { Param } from "@theme/ApiDemoPanel/ParamOptions/slice";
13-
import { setResponse } from "@theme/ApiDemoPanel/Response/slice";
13+
import {
14+
setResponse,
15+
setCode,
16+
clearCode,
17+
setHeaders,
18+
clearHeaders,
19+
} from "@theme/ApiDemoPanel/Response/slice";
1420
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
1521
import Modal from "react-modal";
1622

@@ -118,10 +124,15 @@ function Execute({ postman, proxy }: Props) {
118124
try {
119125
await delay(1200);
120126
const res = await makeRequest(postmanRequest, proxy, body);
121-
dispatch(setResponse(res));
127+
dispatch(setResponse(await res.text()));
128+
dispatch(setCode(res.status));
129+
res.headers &&
130+
dispatch(setHeaders(Object.fromEntries(res.headers)));
122131
} catch (e: any) {
123132
console.log(e);
124133
dispatch(setResponse("Connection failed"));
134+
dispatch(clearCode());
135+
dispatch(clearHeaders());
125136
}
126137
}}
127138
>

packages/docusaurus-theme-openapi-docs/src/theme/ApiDemoPanel/Execute/makeRequest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ async function makeRequest(
188188

189189
return await fetchWithtimeout(finalUrl, requestOptions).then(
190190
(response: any) => {
191-
return response.text();
191+
return response;
192192
}
193193
);
194194
}

packages/docusaurus-theme-openapi-docs/src/theme/ApiDemoPanel/Response/index.tsx

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77

88
import React from "react";
99

10+
import { usePrismTheme } from "@docusaurus/theme-common";
1011
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
1112
import CodeBlock from "@theme/CodeBlock";
13+
import SchemaTabs from "@theme/SchemaTabs";
14+
import TabItem from "@theme/TabItem";
15+
import clsx from "clsx";
1216

13-
import { clearResponse } from "./slice";
17+
import { clearResponse, clearCode, clearHeaders } from "./slice";
1418

1519
// TODO: We probably shouldn't attempt to format XML...
1620
function formatXml(xml: string) {
@@ -33,8 +37,18 @@ function formatXml(xml: string) {
3337
}
3438

3539
function Response() {
40+
const prismTheme = usePrismTheme();
41+
const code = useTypedSelector((state: any) => state.response.code);
42+
const headers = useTypedSelector((state: any) => state.response.headers);
3643
const response = useTypedSelector((state: any) => state.response.value);
3744
const dispatch = useTypedDispatch();
45+
const responseStatusClass =
46+
code &&
47+
(parseInt(code) >= 400
48+
? "response__status--danger"
49+
: parseInt(code) >= 200 && parseInt(code) < 300
50+
? "response__status--success"
51+
: "response__status--info");
3852

3953
if (response === undefined) {
4054
return null;
@@ -56,15 +70,52 @@ function Response() {
5670
<h4>Response</h4>
5771
<button
5872
className="button button--sm button--secondary"
59-
onClick={() => dispatch(clearResponse())}
73+
onClick={() => {
74+
dispatch(clearResponse());
75+
dispatch(clearCode());
76+
dispatch(clearHeaders());
77+
}}
6078
>
6179
Clear
6280
</button>
6381
</div>
6482
</summary>
65-
<CodeBlock language={response.startsWith("<") ? `xml` : `json`}>
66-
{prettyResponse || "No Response"}
67-
</CodeBlock>
83+
84+
<div
85+
style={{
86+
backgroundColor: prismTheme.plain.backgroundColor,
87+
paddingLeft: "1rem",
88+
paddingTop: "1rem",
89+
...((prettyResponse === "Fetching..." || !code) && {
90+
paddingBottom: "1rem",
91+
}),
92+
}}
93+
>
94+
{code && prettyResponse !== "Fetching..." ? (
95+
<SchemaTabs className={clsx(responseStatusClass)} lazy>
96+
{/* @ts-ignore */}
97+
<TabItem label={` ${code}`} value="body" default>
98+
<CodeBlock
99+
className="response__status-code"
100+
language={response.startsWith("<") ? `xml` : `json`}
101+
>
102+
{prettyResponse || "No Response"}
103+
</CodeBlock>
104+
</TabItem>
105+
{/* @ts-ignore */}
106+
<TabItem label="Headers" value="headers">
107+
<CodeBlock
108+
className="response__status-headers"
109+
language={response.startsWith("<") ? `xml` : `json`}
110+
>
111+
{JSON.stringify(headers, undefined, 2)}
112+
</CodeBlock>
113+
</TabItem>
114+
</SchemaTabs>
115+
) : (
116+
prettyResponse || "No Response"
117+
)}
118+
</div>
68119
</details>
69120
);
70121
}

packages/docusaurus-theme-openapi-docs/src/theme/ApiDemoPanel/Response/slice.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
99

1010
export interface State {
1111
value?: string;
12+
code?: string;
13+
headers?: string;
1214
}
1315

1416
const initialState: State = {} as any;
@@ -20,12 +22,31 @@ export const slice = createSlice({
2022
setResponse: (state, action: PayloadAction<string>) => {
2123
state.value = action.payload;
2224
},
25+
setCode: (state, action: PayloadAction<string>) => {
26+
state.code = action.payload;
27+
},
28+
setHeaders: (state, action: PayloadAction<string>) => {
29+
state.headers = action.payload;
30+
},
2331
clearResponse: (state) => {
2432
state.value = undefined;
2533
},
34+
clearCode: (state) => {
35+
state.code = undefined;
36+
},
37+
clearHeaders: (state) => {
38+
state.headers = undefined;
39+
},
2640
},
2741
});
2842

29-
export const { setResponse, clearResponse } = slice.actions;
43+
export const {
44+
setResponse,
45+
clearResponse,
46+
setCode,
47+
clearCode,
48+
setHeaders,
49+
clearHeaders,
50+
} = slice.actions;
3051

3152
export default slice.reducer;

packages/docusaurus-theme-openapi-docs/src/theme/styles.css

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,35 @@ div:has(> ul.openapi-tabs__security-schemes) {
574574
/* div:has(> ul.openapi-tabs__discriminator) {
575575
margin-left: -1px !important;
576576
} */
577+
578+
.response__status--danger > :first-child > span:before {
579+
content: "\2B24";
580+
color: var(--ifm-color-danger);
581+
font-size: 8px;
582+
vertical-align: 15%;
583+
display: inline-block;
584+
}
585+
586+
.response__status--success > :first-child > span:before {
587+
content: "\2B24";
588+
color: var(--ifm-color-success);
589+
font-size: 8px;
590+
vertical-align: 15%;
591+
display: inline-block;
592+
}
593+
594+
.response__status--info > :first-child > span:before {
595+
content: "\2B24";
596+
color: var(--ifm-color-info);
597+
font-size: 8px;
598+
vertical-align: 15%;
599+
display: inline-block;
600+
}
601+
602+
.response__status-code {
603+
margin-left: -1rem;
604+
}
605+
606+
.response__status-headers {
607+
margin-left: -1rem;
608+
}

0 commit comments

Comments
 (0)