Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: improve API testing feature #7311

Merged
merged 1 commit into from
May 14, 2024
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,98 @@
"use client"

import React, { useEffect, useState } from "react"
import { ApiRunnerParamInput, ApiRunnerParamInputProps } from "../Default"
import clsx from "clsx"
import setObjValue from "@/utils/set-obj-value"
import { Button } from "../../../.."
import { Minus, Plus } from "@medusajs/icons"

export const ApiRunnerParamArrayInput = ({
paramName,
paramValue,
objPath,
setValue,
}: ApiRunnerParamInputProps) => {
const [itemsValue, setItemsValue] = useState<typeof paramValue>(paramValue)

useEffect(() => {
setValue((prev: unknown) => {
return typeof prev === "object"
? setObjValue({
obj: { ...prev },
value: itemsValue,
path: `${objPath.length ? `${objPath}.` : ""}${paramName}`,
})
: itemsValue
})
}, [itemsValue])

if (!Array.isArray(paramValue)) {
return (
<ApiRunnerParamInput
paramName={paramName}
paramValue={paramValue}
objPath={objPath}
setValue={setValue}
/>
)
}

return (
<fieldset
className={clsx(
"border border-medusa-border-strong rounded",
"p-docs_0.5"
)}
>
<legend className="px-docs_0.5">
<code>{paramName}</code> Array Items
</legend>
{(itemsValue as unknown[]).map((value, index) => (
<div
key={index}
className={clsx(
index > 0 &&
"flex gap-docs_0.5 items-center justify-center mt-docs_0.5"
)}
>
<ApiRunnerParamInput
paramName={`[${index}]`}
paramValue={value}
objPath={""}
setValue={setItemsValue}
/>
{index > 0 && (
<Button
buttonType="icon"
variant="secondary"
onClick={() => {
setItemsValue((prev: unknown[]) => prev.splice(index, 1))
}}
className="mt-0.5"
>
<Minus />
</Button>
)}
</div>
))}
<Button
buttonType="icon"
variant="secondary"
onClick={() => {
setItemsValue((prev: unknown[]) => [
...prev,
Array.isArray(prev[0])
? [...prev[0]]
: typeof prev[0] === "object"
? Object.assign({}, prev[0])
: prev[0],
])
}}
className="mt-0.5"
>
<Plus />
</Button>
</fieldset>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from "react"
import { InputText } from "../../../.."
import setObjValue from "../../../../utils/set-obj-value"
import { ApiRunnerParamObjectInput } from "../Object"
import { ApiRunnerParamArrayInput } from "../Array"

export type ApiRunnerParamInputProps = {
paramName: string
paramValue: unknown
objPath: string
setValue: React.Dispatch<React.SetStateAction<unknown>>
}

export const ApiRunnerParamInput = ({
paramName,
paramValue,
objPath,
setValue,
}: ApiRunnerParamInputProps) => {
if (Array.isArray(paramValue)) {
return (
<ApiRunnerParamArrayInput
paramName={paramName}
paramValue={paramValue}
objPath={objPath}
setValue={setValue}
/>
)
}
if (typeof paramValue === "object") {
return (
<ApiRunnerParamObjectInput
paramName={paramName}
paramValue={paramValue}
objPath={objPath}
setValue={setValue}
/>
)
}

return (
<InputText
name={paramName}
onChange={(e) => {
setValue((prev: unknown) => {
if (Array.isArray(prev)) {
// try to get index from param name
const splitPath = objPath.split(".")
// if param is in an object in the array, the index is
// the last item of the `objPath`. Otherwise, it's in the param name
const index = (
objPath.length > 0 ? splitPath[splitPath.length - 1] : paramName
)
.replace("[", "")
.replace("]", "")
const intIndex = parseInt(index)

// if we can't get the index from the param name or obj path
// just insert the value to the end of the array.
if (Number.isNaN(intIndex)) {
return [...prev, e.target.value]
}

// if the param is within an object, the value to be set
// is the updated value of the object. Otherwise, it's just the
// value of the item.
const transformedValue =
prev.length > 0 && typeof prev[0] === "object"
? setObjValue({
obj: { ...prev[intIndex] },
value: e.target.value,
path: paramName,
})
: e.target.value

return [
...prev.slice(0, intIndex),
transformedValue,
...prev.slice(intIndex + 1),
]
}

return typeof prev === "object"
? setObjValue({
obj: { ...prev },
value: e.target.value,
path: `${objPath.length ? `${objPath}.` : ""}${paramName}`,
})
: e.target.value
})
}}
placeholder={paramName}
value={
typeof paramValue === "string"
? (paramValue as string)
: typeof paramValue === "number"
? (paramValue as number)
: `${paramValue}`
}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react"
import { ApiRunnerParamInput, ApiRunnerParamInputProps } from "../Default"
import clsx from "clsx"

export const ApiRunnerParamObjectInput = ({
paramName,
paramValue,
objPath,
...props
}: ApiRunnerParamInputProps) => {
if (typeof paramValue !== "object") {
return (
<ApiRunnerParamInput
paramName={paramName}
paramValue={paramValue}
objPath={objPath}
{...props}
/>
)
}

return (
<fieldset
className={clsx(
"border border-medusa-border-strong rounded",
"p-docs_0.5"
)}
>
<legend className="px-docs_0.5">
<code>{paramName}</code> Properties
</legend>
{Object.entries(paramValue as Record<string, unknown>).map(
([key, value], index) => (
<ApiRunnerParamInput
paramName={key}
paramValue={value}
objPath={`${objPath.length ? `${objPath}.` : ""}${paramName}`}
key={index}
{...props}
/>
)
)}
</fieldset>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react"
import { ApiRunnerParamInput } from "./Default"

export type ApiRunnerParamInputsProps = {
data: Record<string, unknown>
title: string
baseObjPath: string
setValue: React.Dispatch<React.SetStateAction<unknown>>
}

export const ApiRunnerParamInputs = ({
data,
title,
baseObjPath,
setValue,
}: ApiRunnerParamInputsProps) => {
return (
<div className="flex flex-col gap-docs_0.5">
<span className="text-compact-medium-plus text-medusa-fg-base">
{title}
</span>
<div className="flex gap-docs_0.5">
{Object.keys(data).map((pathParam, index) => (
<ApiRunnerParamInput
paramName={pathParam}
paramValue={data[pathParam]}
objPath={baseObjPath}
setValue={setValue}
key={index}
/>
))}
</div>
</div>
)
}
Loading
Loading