Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* ============================================================================
* Copyright (c) Palo Alto Networks
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* ========================================================================== */

import React, { useState } from "react";
import FormFileUpload from "@theme/ApiExplorer/FormFileUpload";
import { useTypedDispatch } from "@theme/ApiItem/hooks";
import { FileContent, setFileArrayFormBody } from "../slice";

interface FileArrayFormItemProps {
id: string;
description: string | undefined;
}

export default function FileArrayFormBodyItem({
id,
description,
}: FileArrayFormItemProps): React.JSX.Element {
const dispatch = useTypedDispatch();
const [fileItems, setFileItems] = useState<
Map<number, FileContent["value"] | undefined>
>(new Map([[0, undefined]]));

const handleFileChange = (index: number, file: any) => {
const newItems = new Map(fileItems);

if (file === undefined) {
newItems.delete(index);

setFileItems(newItems);

dispatch(
setFileArrayFormBody({
key: id,
value: [...newItems.values()].filter((item) => item !== undefined),
})
);
return;
}

let maxIndex = 0;

newItems.keys().forEach((item) => {
maxIndex = item > maxIndex ? item : maxIndex;
});
newItems.set(index, {
src: `/path/to/${file.name}`,
content: file,
});
newItems.set(index + 1, undefined);

setFileItems(newItems);

dispatch(
setFileArrayFormBody({
key: id,
value: [...newItems.values()].filter((item) => item !== undefined),
})
);
};

return (
<div>
{[...fileItems.keys()].map((index) => (
<div key={index}>
<FormFileUpload
placeholder={description || id}
onChange={(file: any) => handleFileChange(index, file)}
/>
</div>
))}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* ============================================================================
* Copyright (c) Palo Alto Networks
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* ========================================================================== */

import React from "react";
import FormFileUpload from "@theme/ApiExplorer/FormFileUpload";
import FormSelect from "@theme/ApiExplorer/FormSelect";
import FormTextInput from "@theme/ApiExplorer/FormTextInput";
import LiveApp from "@theme/ApiExplorer/LiveEditor";
import { useTypedDispatch } from "@theme/ApiItem/hooks";
import { SchemaObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
import { clearFormBodyKey, setFileFormBody, setStringFormBody } from "../slice";
import FileArrayFormBodyItem from "../FileArrayFormBodyItem";

interface FormBodyItemProps {
schemaObject: SchemaObject;
id: string;
schema: SchemaObject;
}

export default function FormBodyItem({
schemaObject,
id,
schema,
}: FormBodyItemProps): React.JSX.Element {
const dispatch = useTypedDispatch();

if (
schemaObject.type === "array" &&
schemaObject.items?.format === "binary"
) {
return (
<FileArrayFormBodyItem id={id} description={schemaObject.description} />
);
}

if (schemaObject.format === "binary") {
return (
<FormFileUpload
placeholder={schemaObject.description || id}
onChange={(file: any) => {
if (file === undefined) {
dispatch(clearFormBodyKey(id));
return;
}
dispatch(
setFileFormBody({
key: id,
value: {
src: `/path/to/${file.name}`,
content: file,
},
})
);
}}
/>
);
}

if (
schemaObject.type === "object" &&
(schemaObject.example || schemaObject.examples)
) {
const objectExample = JSON.stringify(
schemaObject.example ?? schemaObject.examples[0],
null,
2
);

return (
<LiveApp
action={(code: string) =>
dispatch(setStringFormBody({ key: id, value: code }))
}
>
{objectExample}
</LiveApp>
);
}

if (
schemaObject.enum &&
schemaObject.enum.every((value) => typeof value === "string")
) {
return (
<FormSelect
options={["---", ...schemaObject.enum]}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
const val = e.target.value;
if (val === "---") {
dispatch(clearFormBodyKey(id));
} else {
dispatch(
setStringFormBody({
key: id,
value: val,
})
);
}
}}
/>
);
}
// TODO: support all the other types.
return (
<FormTextInput
paramName={id}
isRequired={
Array.isArray(schema.required) && schema.required.includes(id)
}
placeholder={schemaObject.description || id}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
dispatch(setStringFormBody({ key: id, value: e.target.value }));
}}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import { translate } from "@docusaurus/Translate";
import json2xml from "@theme/ApiExplorer/Body/json2xml";
import FormFileUpload from "@theme/ApiExplorer/FormFileUpload";
import FormItem from "@theme/ApiExplorer/FormItem";
import FormSelect from "@theme/ApiExplorer/FormSelect";
import FormTextInput from "@theme/ApiExplorer/FormTextInput";
import LiveApp from "@theme/ApiExplorer/LiveEditor";
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
import Markdown from "@theme/Markdown";
Expand All @@ -23,13 +21,8 @@ import { OPENAPI_BODY, OPENAPI_REQUEST } from "@theme/translationIds";
import { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
import format from "xml-formatter";

import {
clearFormBodyKey,
clearRawBody,
setFileFormBody,
setFileRawBody,
setStringFormBody,
} from "./slice";
import { clearRawBody, setFileRawBody, setStringRawBody } from "./slice";
import FormBodyItem from "./FormBodyItem";

export interface Props {
jsonRequestBodyExample: string;
Expand Down Expand Up @@ -128,96 +121,23 @@ function Body({
) {
return (
<FormItem className="openapi-explorer__form-item-body-container">
<div>
{Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
if (val.format === "binary") {
return (
<FormItem
key={key}
label={key}
required={
Array.isArray(schema.required) &&
schema.required.includes(key)
}
>
<FormFileUpload
placeholder={val.description || key}
onChange={(file: any) => {
if (file === undefined) {
dispatch(clearFormBodyKey(key));
return;
}
dispatch(
setFileFormBody({
key: key,
value: {
src: `/path/to/${file.name}`,
content: file,
},
})
);
}}
/>
</FormItem>
);
}

if (val.enum) {
return (
<FormItem
key={key}
label={key}
required={
Array.isArray(schema.required) &&
schema.required.includes(key)
}
>
<FormSelect
options={["---", ...val.enum]}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
const val = e.target.value;
if (val === "---") {
dispatch(clearFormBodyKey(key));
} else {
dispatch(
setStringFormBody({
key: key,
value: val,
})
);
}
}}
/>
</FormItem>
);
}
// TODO: support all the other types.
return (
<FormItem
key={key}
label={key}
required={
Array.isArray(schema.required) &&
schema.required.includes(key)
}
>
<FormTextInput
paramName={key}
isRequired={
Array.isArray(schema.required) &&
schema.required.includes(key)
}
placeholder={val.description || key}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
dispatch(
setStringFormBody({ key: key, value: e.target.value })
);
}}
/>
</FormItem>
);
})}
</div>
{Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
return (
<FormItem
key={key}
label={key}
required={
Array.isArray(schema.required) && schema.required.includes(key)
}
>
<FormBodyItem
schemaObject={val}
id={key}
schema={schema}
></FormBodyItem>
</FormItem>
);
})}
</FormItem>
);
}
Expand Down Expand Up @@ -315,7 +235,11 @@ function Body({
value="Example (from schema)"
default
>
<LiveApp action={dispatch} language={language} required={required}>
<LiveApp
action={(code: string) => dispatch(setStringRawBody(code))}
language={language}
required={required}
>
{defaultBody}
</LiveApp>
</TabItem>
Expand All @@ -324,7 +248,7 @@ function Body({
{example.summary && <Markdown>{example.summary}</Markdown>}
{exampleBody && (
<LiveApp
action={dispatch}
action={(code: string) => dispatch(setStringRawBody(code))}
language={language}
required={required}
>
Expand All @@ -350,7 +274,11 @@ function Body({
value="Example (from schema)"
default
>
<LiveApp action={dispatch} language={language} required={required}>
<LiveApp
action={(code: string) => dispatch(setStringRawBody(code))}
language={language}
required={required}
>
{defaultBody}
</LiveApp>
</TabItem>
Expand All @@ -364,7 +292,10 @@ function Body({
>
{example.summary && <Markdown>{example.summary}</Markdown>}
{example.body && (
<LiveApp action={dispatch} language={language}>
<LiveApp
action={(code: string) => dispatch(setStringRawBody(code))}
language={language}
>
{example.body}
</LiveApp>
)}
Expand All @@ -378,7 +309,11 @@ function Body({

return (
<FormItem>
<LiveApp action={dispatch} language={language} required={required}>
<LiveApp
action={(code: string) => dispatch(setStringRawBody(code))}
language={language}
required={required}
>
{defaultBody}
</LiveApp>
</FormItem>
Expand Down
Loading
Loading