docusaurus-theme-openapi-docs 1.1.12 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/theme/ApiDemoPanel/Authorization/auth-types.js +4 -0
- package/lib/theme/ApiDemoPanel/Authorization/index.js +125 -0
- package/lib/theme/ApiDemoPanel/Authorization/slice.js +1 -1
- package/lib/theme/ApiDemoPanel/Body/index.js +7 -6
- package/lib/theme/ApiDemoPanel/Execute/index.js +168 -0
- package/lib/theme/ApiDemoPanel/Execute/makeRequest.js +204 -0
- package/lib/theme/ApiDemoPanel/FormItem/index.js +7 -0
- package/lib/theme/ApiDemoPanel/FormItem/styles.module.css +5 -0
- package/lib/theme/ApiDemoPanel/ParamOptions/index.js +1 -1
- package/lib/theme/ApiDemoPanel/Request/index.js +78 -0
- package/lib/theme/ApiDemoPanel/Request/styles.module.css +17 -0
- package/lib/theme/ApiDemoPanel/Response/index.js +16 -12
- package/lib/theme/ApiDemoPanel/SecuritySchemes/index.js +24 -19
- package/lib/theme/ApiDemoPanel/Server/index.js +1 -0
- package/lib/theme/ApiDemoPanel/buildPostmanRequest.js +25 -3
- package/lib/theme/ApiDemoPanel/index.js +5 -13
- package/lib/theme/ApiDemoPanel/persistanceMiddleware.js +1 -1
- package/lib/theme/ApiDemoPanel/react-modal.d.ts +8 -0
- package/lib/theme/ApiItem/Layout/styles.module.css +56 -0
- package/lib/theme/ParamsItem/index.js +5 -1
- package/lib-next/theme/ApiDemoPanel/Authorization/auth-types.js +4 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/index.js +149 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/slice.js +1 -1
- package/lib-next/theme/ApiDemoPanel/Body/index.js +28 -6
- package/lib-next/theme/ApiDemoPanel/Execute/index.js +170 -0
- package/lib-next/theme/ApiDemoPanel/Execute/makeRequest.js +190 -0
- package/lib-next/theme/ApiDemoPanel/FormItem/index.js +9 -1
- package/lib-next/theme/ApiDemoPanel/FormItem/styles.module.css +5 -0
- package/lib-next/theme/ApiDemoPanel/ParamOptions/index.js +1 -1
- package/lib-next/theme/ApiDemoPanel/Request/index.js +60 -0
- package/lib-next/theme/ApiDemoPanel/Request/styles.module.css +17 -0
- package/lib-next/theme/ApiDemoPanel/Response/index.js +18 -13
- package/lib-next/theme/ApiDemoPanel/SecuritySchemes/index.js +22 -20
- package/lib-next/theme/ApiDemoPanel/Server/index.js +1 -0
- package/lib-next/theme/ApiDemoPanel/buildPostmanRequest.js +25 -3
- package/lib-next/theme/ApiDemoPanel/index.js +4 -13
- package/lib-next/theme/ApiDemoPanel/persistanceMiddleware.js +1 -1
- package/lib-next/theme/ApiDemoPanel/react-modal.d.ts +8 -0
- package/lib-next/theme/ApiItem/Layout/styles.module.css +56 -0
- package/lib-next/theme/ParamsItem/index.js +5 -1
- package/package.json +5 -4
- package/src/theme/ApiDemoPanel/Authorization/auth-types.ts +4 -0
- package/src/theme/ApiDemoPanel/Authorization/index.tsx +154 -0
- package/src/theme/ApiDemoPanel/Authorization/slice.ts +1 -1
- package/src/theme/ApiDemoPanel/Body/index.tsx +28 -6
- package/src/theme/ApiDemoPanel/Execute/index.tsx +188 -0
- package/src/theme/ApiDemoPanel/Execute/makeRequest.ts +197 -0
- package/src/theme/ApiDemoPanel/FormItem/index.tsx +11 -2
- package/src/theme/ApiDemoPanel/FormItem/styles.module.css +5 -0
- package/src/theme/ApiDemoPanel/ParamOptions/index.tsx +1 -1
- package/src/theme/ApiDemoPanel/Request/index.tsx +71 -0
- package/src/theme/ApiDemoPanel/Request/styles.module.css +17 -0
- package/src/theme/ApiDemoPanel/Response/index.tsx +19 -13
- package/src/theme/ApiDemoPanel/SecuritySchemes/index.tsx +22 -17
- package/src/theme/ApiDemoPanel/Server/index.tsx +1 -0
- package/src/theme/ApiDemoPanel/buildPostmanRequest.ts +22 -3
- package/src/theme/ApiDemoPanel/index.tsx +4 -13
- package/src/theme/ApiDemoPanel/persistanceMiddleware.ts +1 -1
- package/src/theme/ApiDemoPanel/react-modal.d.ts +8 -0
- package/src/theme/ApiItem/Layout/styles.module.css +56 -0
- package/src/theme/ParamsItem/index.js +5 -1
|
@@ -8,13 +8,11 @@ import React from "react";
|
|
|
8
8
|
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
9
9
|
import sdk from "@paloaltonetworks/postman-collection";
|
|
10
10
|
import { Provider } from "react-redux";
|
|
11
|
-
import Accept from "./Accept";
|
|
12
11
|
import { createAuth } from "./Authorization/slice";
|
|
13
|
-
import Body from "./Body";
|
|
14
12
|
import Curl from "./Curl";
|
|
15
13
|
import MethodEndpoint from "./MethodEndpoint";
|
|
16
|
-
import ParamOptions from "./ParamOptions";
|
|
17
14
|
import { createPersistanceMiddleware } from "./persistanceMiddleware";
|
|
15
|
+
import Request from "./Request";
|
|
18
16
|
import Response from "./Response";
|
|
19
17
|
import SecuritySchemes from "./SecuritySchemes";
|
|
20
18
|
import Server from "./Server";
|
|
@@ -83,18 +81,11 @@ function ApiDemoPanel({ item, infoPath }) {
|
|
|
83
81
|
<Provider store={store2}>
|
|
84
82
|
<div className={styles.apiDemoPanelContainer}>
|
|
85
83
|
<MethodEndpoint method={method} path={path} />
|
|
86
|
-
<SecuritySchemes infoPath={infoPath} />
|
|
87
|
-
<div className={styles.optionsPanel}>
|
|
88
|
-
<ParamOptions />
|
|
89
|
-
<Body
|
|
90
|
-
jsonRequestBodyExample={item.jsonRequestBodyExample}
|
|
91
|
-
requestBodyMetadata={item.requestBody}
|
|
92
|
-
/>
|
|
93
|
-
<Accept />
|
|
94
|
-
</div>
|
|
95
84
|
<Server />
|
|
96
|
-
<
|
|
85
|
+
<SecuritySchemes infoPath={infoPath} />
|
|
86
|
+
<Request item={item} />
|
|
97
87
|
<Response />
|
|
88
|
+
<Curl postman={postman} codeSamples={item["x-code-samples"] ?? []} />
|
|
98
89
|
</div>
|
|
99
90
|
</Provider>
|
|
100
91
|
);
|
|
@@ -10,7 +10,7 @@ export function createPersistanceMiddleware(options) {
|
|
|
10
10
|
const persistanceMiddleware = (storeAPI) => (next) => (action) => {
|
|
11
11
|
const result = next(action);
|
|
12
12
|
const state = storeAPI.getState();
|
|
13
|
-
const storage = createStorage(
|
|
13
|
+
const storage = createStorage("sessionStorage");
|
|
14
14
|
|
|
15
15
|
if (action.type === setAuthData.type) {
|
|
16
16
|
for (const [key, value] of Object.entries(state.auth.data)) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
declare module "react-modal";
|
|
@@ -71,6 +71,62 @@
|
|
|
71
71
|
border-top: unset !important;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
:global(.theme-api-markdown .details__demo-panel) {
|
|
75
|
+
margin-bottom: 1rem;
|
|
76
|
+
background: var(--openapi-card-background-color);
|
|
77
|
+
border-radius: var(--openapi-card-border-radius);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:global(.theme-api-markdown .details__demo-panel > summary) {
|
|
81
|
+
padding-left: 1rem;
|
|
82
|
+
padding-top: 1rem;
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:global(.theme-api-markdown .details__demo-panel > div > div > pre) {
|
|
87
|
+
border-top-left-radius: 0;
|
|
88
|
+
border-top-right-radius: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:global(.theme-api-markdown .details__demo-panel > summary::marker) {
|
|
92
|
+
display: none;
|
|
93
|
+
content: "";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
:global(.theme-api-markdown
|
|
97
|
+
.details__demo-panel
|
|
98
|
+
> summary::-webkit-details-marker) {
|
|
99
|
+
display: none;
|
|
100
|
+
content: "";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:global(.theme-api-markdown .details__demo-panel > pre) {
|
|
104
|
+
margin-bottom: 0;
|
|
105
|
+
padding-top: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
:global(.theme-api-markdown .details__request-summary) {
|
|
109
|
+
display: flex;
|
|
110
|
+
justify-content: space-between;
|
|
111
|
+
align-items: center;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
:global(.theme-api-markdown .details__request-summary > button) {
|
|
115
|
+
margin-bottom: 1rem;
|
|
116
|
+
margin-right: 1rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:global(.theme-api-markdown .details__response-summary) {
|
|
120
|
+
display: flex;
|
|
121
|
+
justify-content: space-between;
|
|
122
|
+
align-items: center;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
:global(.theme-api-markdown .details__response-summary > button) {
|
|
126
|
+
margin-bottom: 1rem;
|
|
127
|
+
margin-right: 1rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
74
130
|
:global(.theme-api-markdown code) {
|
|
75
131
|
max-width: 600px;
|
|
76
132
|
max-height: 500px;
|
|
@@ -53,7 +53,11 @@ function ParamsItem({
|
|
|
53
53
|
));
|
|
54
54
|
|
|
55
55
|
const renderDefaultValue = guard(
|
|
56
|
-
schema
|
|
56
|
+
schema && schema.items
|
|
57
|
+
? schema.items.default
|
|
58
|
+
: schema
|
|
59
|
+
? schema.default
|
|
60
|
+
: undefined,
|
|
57
61
|
(value) => (
|
|
58
62
|
<div>
|
|
59
63
|
<ReactMarkdown children={`**Default value:** \`${value}\``} />
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docusaurus-theme-openapi-docs",
|
|
3
3
|
"description": "OpenAPI theme for Docusaurus.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -44,19 +44,20 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@docusaurus/theme-common": "^2.0.1",
|
|
46
46
|
"@mdx-js/react": "^1.6.21",
|
|
47
|
-
"@paloaltonetworks/postman-code-generators": "^1.1.
|
|
47
|
+
"@paloaltonetworks/postman-code-generators": "^1.1.12",
|
|
48
48
|
"@paloaltonetworks/postman-collection": "^4.1.0",
|
|
49
49
|
"@reduxjs/toolkit": "^1.7.1",
|
|
50
50
|
"buffer": "^6.0.3",
|
|
51
51
|
"clsx": "^1.1.1",
|
|
52
52
|
"crypto-js": "^4.1.1",
|
|
53
|
-
"docusaurus-plugin-openapi-docs": "^1.
|
|
53
|
+
"docusaurus-plugin-openapi-docs": "^1.2.0",
|
|
54
54
|
"immer": "^9.0.7",
|
|
55
55
|
"lodash": "^4.17.20",
|
|
56
56
|
"process": "^0.11.10",
|
|
57
57
|
"react-live": "^3.1.1",
|
|
58
58
|
"react-magic-dropzone": "^1.0.1",
|
|
59
59
|
"react-markdown": "^8.0.1",
|
|
60
|
+
"react-modal": "^3.15.1",
|
|
60
61
|
"react-redux": "^7.2.0",
|
|
61
62
|
"redux-devtools-extension": "^2.13.8",
|
|
62
63
|
"webpack": "^5.61.0",
|
|
@@ -69,5 +70,5 @@
|
|
|
69
70
|
"engines": {
|
|
70
71
|
"node": ">=14"
|
|
71
72
|
},
|
|
72
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "fdbc413e36c3b7c202cc31606124c0a8eb76811b"
|
|
73
74
|
}
|
|
@@ -11,6 +11,10 @@ export function getAuthDataKeys(security: { [key: string]: any }) {
|
|
|
11
11
|
return ["token"];
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
if (security.type === "oauth2") {
|
|
15
|
+
return ["token"];
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
// Basic Auth
|
|
15
19
|
if (security.type === "http" && security.scheme === "basic") {
|
|
16
20
|
return ["username", "password"];
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
|
|
10
|
+
import FormItem from "../FormItem";
|
|
11
|
+
import FormSelect from "../FormSelect";
|
|
12
|
+
import FormTextInput from "../FormTextInput";
|
|
13
|
+
import { useTypedDispatch, useTypedSelector } from "../hooks";
|
|
14
|
+
import { setAuthData, setSelectedAuth } from "./slice";
|
|
15
|
+
|
|
16
|
+
function Authorization() {
|
|
17
|
+
const data = useTypedSelector((state) => state.auth.data);
|
|
18
|
+
const options = useTypedSelector((state) => state.auth.options);
|
|
19
|
+
const selected = useTypedSelector((state) => state.auth.selected);
|
|
20
|
+
|
|
21
|
+
const dispatch = useTypedDispatch();
|
|
22
|
+
|
|
23
|
+
if (selected === undefined) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const selectedAuth = options[selected];
|
|
28
|
+
|
|
29
|
+
const optionKeys = Object.keys(options);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
{optionKeys.length > 1 && (
|
|
34
|
+
<FormItem label="Security Scheme">
|
|
35
|
+
<FormSelect
|
|
36
|
+
options={optionKeys}
|
|
37
|
+
value={selected}
|
|
38
|
+
onChange={(e) => {
|
|
39
|
+
dispatch(setSelectedAuth(e.target.value));
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
42
|
+
</FormItem>
|
|
43
|
+
)}
|
|
44
|
+
{selectedAuth.map((a) => {
|
|
45
|
+
if (a.type === "http" && a.scheme === "bearer") {
|
|
46
|
+
return (
|
|
47
|
+
<FormItem label="Bearer Token" key={a.key + "-bearer"}>
|
|
48
|
+
<FormTextInput
|
|
49
|
+
placeholder="Bearer Token"
|
|
50
|
+
value={data[a.key].token ?? ""}
|
|
51
|
+
onChange={(e) => {
|
|
52
|
+
const value = e.target.value.trim();
|
|
53
|
+
dispatch(
|
|
54
|
+
setAuthData({
|
|
55
|
+
scheme: a.key,
|
|
56
|
+
key: "token",
|
|
57
|
+
value: value ? value : undefined,
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
}}
|
|
61
|
+
/>
|
|
62
|
+
</FormItem>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (a.type === "oauth2") {
|
|
67
|
+
return (
|
|
68
|
+
<FormItem label="Bearer Token" key={a.key + "-oauth2"}>
|
|
69
|
+
<FormTextInput
|
|
70
|
+
placeholder="Bearer Token"
|
|
71
|
+
value={data[a.key].token ?? ""}
|
|
72
|
+
onChange={(e) => {
|
|
73
|
+
const value = e.target.value.trim();
|
|
74
|
+
dispatch(
|
|
75
|
+
setAuthData({
|
|
76
|
+
scheme: a.key,
|
|
77
|
+
key: "token",
|
|
78
|
+
value: value ? value : undefined,
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
</FormItem>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (a.type === "http" && a.scheme === "basic") {
|
|
88
|
+
return (
|
|
89
|
+
<React.Fragment key={a.key + "-basic"}>
|
|
90
|
+
<FormItem label="Username">
|
|
91
|
+
<FormTextInput
|
|
92
|
+
placeholder="Username"
|
|
93
|
+
value={data[a.key].username ?? ""}
|
|
94
|
+
onChange={(e) => {
|
|
95
|
+
const value = e.target.value.trim();
|
|
96
|
+
dispatch(
|
|
97
|
+
setAuthData({
|
|
98
|
+
scheme: a.key,
|
|
99
|
+
key: "username",
|
|
100
|
+
value: value ? value : undefined,
|
|
101
|
+
})
|
|
102
|
+
);
|
|
103
|
+
}}
|
|
104
|
+
/>
|
|
105
|
+
</FormItem>
|
|
106
|
+
<FormItem label="Password">
|
|
107
|
+
<FormTextInput
|
|
108
|
+
placeholder="Password"
|
|
109
|
+
password
|
|
110
|
+
value={data[a.key].password ?? ""}
|
|
111
|
+
onChange={(e) => {
|
|
112
|
+
const value = e.target.value.trim();
|
|
113
|
+
dispatch(
|
|
114
|
+
setAuthData({
|
|
115
|
+
scheme: a.key,
|
|
116
|
+
key: "password",
|
|
117
|
+
value: value ? value : undefined,
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
}}
|
|
121
|
+
/>
|
|
122
|
+
</FormItem>
|
|
123
|
+
</React.Fragment>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (a.type === "apiKey") {
|
|
128
|
+
return (
|
|
129
|
+
<FormItem label={`${a.key}`} key={a.key + "-apikey"}>
|
|
130
|
+
<FormTextInput
|
|
131
|
+
placeholder={`${a.key}`}
|
|
132
|
+
value={data[a.key].apiKey ?? ""}
|
|
133
|
+
onChange={(e) => {
|
|
134
|
+
const value = e.target.value.trim();
|
|
135
|
+
dispatch(
|
|
136
|
+
setAuthData({
|
|
137
|
+
scheme: a.key,
|
|
138
|
+
key: "apiKey",
|
|
139
|
+
value: value ? value : undefined,
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
</FormItem>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return null;
|
|
149
|
+
})}
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default Authorization;
|
|
@@ -57,7 +57,7 @@ export function createAuth({
|
|
|
57
57
|
};
|
|
58
58
|
options?: ThemeConfig["api"];
|
|
59
59
|
}): AuthState {
|
|
60
|
-
const storage = createStorage(
|
|
60
|
+
const storage = createStorage("sessionStorage");
|
|
61
61
|
|
|
62
62
|
let data: AuthState["data"] = {};
|
|
63
63
|
let options: AuthState["options"] = {};
|
|
@@ -56,6 +56,7 @@ function BodyWrap({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
56
56
|
|
|
57
57
|
function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
58
58
|
const contentType = useTypedSelector((state) => state.contentType.value);
|
|
59
|
+
const required = requestBodyMetadata?.required;
|
|
59
60
|
|
|
60
61
|
const dispatch = useTypedDispatch();
|
|
61
62
|
|
|
@@ -84,7 +85,7 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
84
85
|
|
|
85
86
|
if (schema?.format === "binary") {
|
|
86
87
|
return (
|
|
87
|
-
<FormItem label="Body">
|
|
88
|
+
<FormItem label="Body" required={required}>
|
|
88
89
|
<FormFileUpload
|
|
89
90
|
placeholder={schema.description || "Body"}
|
|
90
91
|
onChange={(file) => {
|
|
@@ -110,7 +111,7 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
110
111
|
schema?.type === "object"
|
|
111
112
|
) {
|
|
112
113
|
return (
|
|
113
|
-
<FormItem label="Body">
|
|
114
|
+
<FormItem label="Body" required={required}>
|
|
114
115
|
<div
|
|
115
116
|
style={{
|
|
116
117
|
marginTop: "calc(var(--ifm-pre-padding) / 2)",
|
|
@@ -122,7 +123,14 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
122
123
|
{Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
|
|
123
124
|
if (val.format === "binary") {
|
|
124
125
|
return (
|
|
125
|
-
<FormItem
|
|
126
|
+
<FormItem
|
|
127
|
+
key={key}
|
|
128
|
+
label={key}
|
|
129
|
+
required={
|
|
130
|
+
Array.isArray(schema.required) &&
|
|
131
|
+
schema.required.includes(key)
|
|
132
|
+
}
|
|
133
|
+
>
|
|
126
134
|
<FormFileUpload
|
|
127
135
|
placeholder={val.description || key}
|
|
128
136
|
onChange={(file) => {
|
|
@@ -147,7 +155,14 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
147
155
|
|
|
148
156
|
if (val.enum) {
|
|
149
157
|
return (
|
|
150
|
-
<FormItem
|
|
158
|
+
<FormItem
|
|
159
|
+
key={key}
|
|
160
|
+
label={key}
|
|
161
|
+
required={
|
|
162
|
+
Array.isArray(schema.required) &&
|
|
163
|
+
schema.required.includes(key)
|
|
164
|
+
}
|
|
165
|
+
>
|
|
151
166
|
<FormSelect
|
|
152
167
|
options={["---", ...val.enum]}
|
|
153
168
|
onChange={(e) => {
|
|
@@ -169,7 +184,14 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
169
184
|
}
|
|
170
185
|
// TODO: support all the other types.
|
|
171
186
|
return (
|
|
172
|
-
<FormItem
|
|
187
|
+
<FormItem
|
|
188
|
+
key={key}
|
|
189
|
+
label={key}
|
|
190
|
+
required={
|
|
191
|
+
Array.isArray(schema.required) &&
|
|
192
|
+
schema.required.includes(key)
|
|
193
|
+
}
|
|
194
|
+
>
|
|
173
195
|
<FormTextInput
|
|
174
196
|
placeholder={val.description || key}
|
|
175
197
|
onChange={(e) => {
|
|
@@ -212,7 +234,7 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
|
212
234
|
}
|
|
213
235
|
|
|
214
236
|
return (
|
|
215
|
-
<FormItem label="Body">
|
|
237
|
+
<FormItem label="Body" required={required}>
|
|
216
238
|
<LiveApp action={dispatch} language={language}>
|
|
217
239
|
{exampleBodyString}
|
|
218
240
|
</LiveApp>
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
|
|
10
|
+
import sdk from "@paloaltonetworks/postman-collection";
|
|
11
|
+
import Modal from "react-modal";
|
|
12
|
+
|
|
13
|
+
import { useTypedDispatch, useTypedSelector } from "../hooks";
|
|
14
|
+
import { Param } from "../ParamOptions/slice";
|
|
15
|
+
import { setResponse } from "../Response/slice";
|
|
16
|
+
import buildPostmanRequest from "./../buildPostmanRequest";
|
|
17
|
+
import makeRequest from "./makeRequest";
|
|
18
|
+
|
|
19
|
+
function validateRequest(params: {
|
|
20
|
+
path: Param[];
|
|
21
|
+
query: Param[];
|
|
22
|
+
header: Param[];
|
|
23
|
+
cookie: Param[];
|
|
24
|
+
}) {
|
|
25
|
+
for (let paramList of Object.values(params)) {
|
|
26
|
+
for (let param of paramList) {
|
|
27
|
+
if (param.required && !param.value) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface Props {
|
|
36
|
+
postman: sdk.Request;
|
|
37
|
+
proxy?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function Execute({ postman, proxy }: Props) {
|
|
41
|
+
const pathParams = useTypedSelector((state) => state.params.path);
|
|
42
|
+
const queryParams = useTypedSelector((state) => state.params.query);
|
|
43
|
+
const cookieParams = useTypedSelector((state) => state.params.cookie);
|
|
44
|
+
const headerParams = useTypedSelector((state) => state.params.header);
|
|
45
|
+
const contentType = useTypedSelector((state) => state.contentType.value);
|
|
46
|
+
const body = useTypedSelector((state) => state.body);
|
|
47
|
+
const accept = useTypedSelector((state) => state.accept.value);
|
|
48
|
+
const server = useTypedSelector((state) => state.server.value);
|
|
49
|
+
const params = useTypedSelector((state) => state.params);
|
|
50
|
+
const auth = useTypedSelector((state) => state.auth);
|
|
51
|
+
|
|
52
|
+
const isValidRequest = validateRequest(params);
|
|
53
|
+
|
|
54
|
+
const dispatch = useTypedDispatch();
|
|
55
|
+
|
|
56
|
+
const postmanRequest = buildPostmanRequest(postman, {
|
|
57
|
+
queryParams,
|
|
58
|
+
pathParams,
|
|
59
|
+
cookieParams,
|
|
60
|
+
contentType,
|
|
61
|
+
accept,
|
|
62
|
+
headerParams,
|
|
63
|
+
body,
|
|
64
|
+
server,
|
|
65
|
+
auth,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const delay = (ms: number) =>
|
|
69
|
+
new Promise((resolve) => setTimeout(resolve, ms));
|
|
70
|
+
|
|
71
|
+
function openModal() {
|
|
72
|
+
setIsOpen(true);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function closeModal() {
|
|
76
|
+
setIsOpen(false);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function acceptAgreement() {
|
|
80
|
+
setIsOpen(false);
|
|
81
|
+
setAgreementAccepted(true);
|
|
82
|
+
sessionStorage.setItem("agreement-ack", "true");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const [modalIsOpen, setIsOpen] = React.useState(false);
|
|
86
|
+
// Set the following as default value to persist to session and enable modal
|
|
87
|
+
// sessionStorage.getItem("agreement-ack") === "true"
|
|
88
|
+
const [agreementAccepted, setAgreementAccepted] = React.useState(true);
|
|
89
|
+
|
|
90
|
+
const customStyles = {
|
|
91
|
+
overlay: {
|
|
92
|
+
backdropFilter: "blur(10px)",
|
|
93
|
+
backgroundColor: "transparent",
|
|
94
|
+
},
|
|
95
|
+
content: {
|
|
96
|
+
top: "50%",
|
|
97
|
+
left: "50%",
|
|
98
|
+
right: "auto",
|
|
99
|
+
bottom: "auto",
|
|
100
|
+
marginRight: "-50%",
|
|
101
|
+
border: "none",
|
|
102
|
+
padding: "none",
|
|
103
|
+
borderRadius: "var(--openapi-card-border-radius)",
|
|
104
|
+
background: "var(--ifm-card-background-color)",
|
|
105
|
+
transform: "translate(-50%, -50%)",
|
|
106
|
+
maxWidth: "550px",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (agreementAccepted) {
|
|
111
|
+
return (
|
|
112
|
+
<button
|
|
113
|
+
className="button button--sm button--secondary"
|
|
114
|
+
disabled={!isValidRequest}
|
|
115
|
+
onClick={async () => {
|
|
116
|
+
dispatch(setResponse("Fetching..."));
|
|
117
|
+
try {
|
|
118
|
+
await delay(1200);
|
|
119
|
+
const res = await makeRequest(postmanRequest, proxy, body);
|
|
120
|
+
dispatch(setResponse(res));
|
|
121
|
+
} catch (e: any) {
|
|
122
|
+
console.log(e);
|
|
123
|
+
dispatch(setResponse("Connection failed"));
|
|
124
|
+
}
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
Send API Request
|
|
128
|
+
</button>
|
|
129
|
+
);
|
|
130
|
+
} else {
|
|
131
|
+
return (
|
|
132
|
+
<React.Fragment>
|
|
133
|
+
<button
|
|
134
|
+
className="button button--sm button--secondary"
|
|
135
|
+
onClick={openModal}
|
|
136
|
+
>
|
|
137
|
+
Send API Request
|
|
138
|
+
</button>
|
|
139
|
+
<Modal
|
|
140
|
+
isOpen={modalIsOpen}
|
|
141
|
+
onRequestClose={closeModal}
|
|
142
|
+
style={customStyles}
|
|
143
|
+
contentLabel="Terms of Use"
|
|
144
|
+
>
|
|
145
|
+
<form>
|
|
146
|
+
<div className="card">
|
|
147
|
+
<div className="card__header">
|
|
148
|
+
<h2>Terms of Use</h2>
|
|
149
|
+
<hr></hr>
|
|
150
|
+
</div>
|
|
151
|
+
<div className="card__body">
|
|
152
|
+
<p>
|
|
153
|
+
By accepting this agreement the end user acknowledges the
|
|
154
|
+
risks of performing authenticated and non-authenticated API
|
|
155
|
+
requests from the browser.
|
|
156
|
+
</p>
|
|
157
|
+
<p>
|
|
158
|
+
The end user also accepts the responsibility of safeguarding
|
|
159
|
+
API credentials and any potentially sensitive data returned by
|
|
160
|
+
the API.
|
|
161
|
+
</p>
|
|
162
|
+
<br></br>
|
|
163
|
+
</div>
|
|
164
|
+
<div className="card__footer">
|
|
165
|
+
<div className="button-group button-group--block">
|
|
166
|
+
<button
|
|
167
|
+
className="button button--sm button--outline button--success"
|
|
168
|
+
onClick={acceptAgreement}
|
|
169
|
+
>
|
|
170
|
+
AGREE
|
|
171
|
+
</button>
|
|
172
|
+
<button
|
|
173
|
+
className="button button--sm button--outline button--danger"
|
|
174
|
+
onClick={closeModal}
|
|
175
|
+
>
|
|
176
|
+
DISAGREE
|
|
177
|
+
</button>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</form>
|
|
182
|
+
</Modal>
|
|
183
|
+
</React.Fragment>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export default Execute;
|