This commit is contained in:
parent
a5bf267763
commit
b246410e11
|
@ -1,5 +1,7 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import KeyValuePair from "./KeyValuePair";
|
import KeyValuePair from "./KeyValuePair";
|
||||||
|
import KeyValuePair2 from "./KeyValuePair2";
|
||||||
|
|
||||||
import JsonEditor from "./Editors";
|
import JsonEditor from "./Editors";
|
||||||
import { FaPaperPlane } from "react-icons/fa6";
|
import { FaPaperPlane } from "react-icons/fa6";
|
||||||
import { IoMdDownload } from "react-icons/io";
|
import { IoMdDownload } from "react-icons/io";
|
||||||
|
@ -19,6 +21,7 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
||||||
const [headers, setHeaders] = useState(
|
const [headers, setHeaders] = useState(
|
||||||
content?.header ?? [{ key: "", value: "" }]
|
content?.header ?? [{ key: "", value: "" }]
|
||||||
);
|
);
|
||||||
|
const [formData, setformData] = useState(content?.form_data ?? [{ key: "", value: "" }]);
|
||||||
const [jsonBody, setJsonBody] = useState(content ?? {});
|
const [jsonBody, setJsonBody] = useState(content ?? {});
|
||||||
const [activeTab, setActiveTab] = useState("query-params");
|
const [activeTab, setActiveTab] = useState("query-params");
|
||||||
|
|
||||||
|
@ -39,27 +42,72 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
||||||
setHeaders([...headers, { key: "", value: "" }]);
|
setHeaders([...headers, { key: "", value: "" }]);
|
||||||
setisSaved(false);
|
setisSaved(false);
|
||||||
};
|
};
|
||||||
|
const handleAddFormData = () => {
|
||||||
|
setformData([...formData, { key: "", value: "" }]);
|
||||||
|
setisSaved(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
// e.preventDefault();
|
||||||
|
// const params = queryParams.reduce((acc, { key, value }) => {
|
||||||
|
// if (key) acc[key] = value;
|
||||||
|
// return acc;
|
||||||
|
// }, {} as Record<string, string>);
|
||||||
|
|
||||||
|
// const headerObj = headers.reduce((acc, { key, value }) => {
|
||||||
|
// if (key) acc[key] = value;
|
||||||
|
// return acc;
|
||||||
|
// }, {} as Record<string, string>);
|
||||||
|
|
||||||
|
// onSubmit({
|
||||||
|
// method,
|
||||||
|
// url,
|
||||||
|
// params,
|
||||||
|
// headers: headerObj,
|
||||||
|
// data: jsonBody,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Reduce query parameters and headers to objects
|
||||||
const params = queryParams.reduce((acc, { key, value }) => {
|
const params = queryParams.reduce((acc, { key, value }) => {
|
||||||
if (key) acc[key] = value;
|
if (key) acc[key] = value;
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<string, string>);
|
}, {} as Record<string, string>);
|
||||||
|
|
||||||
const headerObj = headers.reduce((acc, { key, value }) => {
|
const headerObj = headers.reduce((acc, { key, value }) => {
|
||||||
if (key) acc[key] = value;
|
if (key) acc[key] = value;
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<string, string>);
|
}, {} as Record<string, string>);
|
||||||
|
|
||||||
|
// If formData is not empty, convert it to FormData
|
||||||
|
let data: Record<string, any> | FormData;
|
||||||
|
if (formData.length > 0) {
|
||||||
|
data = new FormData();
|
||||||
|
formData.forEach(({ key, value }) => {
|
||||||
|
if (key) {
|
||||||
|
if (value instanceof File) {
|
||||||
|
data.append(key, value); // Append file
|
||||||
|
} else {
|
||||||
|
data.append(key, value); // Append text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = jsonBody; // If formData is empty, use jsonBody
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call onSubmit with the appropriate data
|
||||||
onSubmit({
|
onSubmit({
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
params,
|
params,
|
||||||
headers: headerObj,
|
headers: headerObj,
|
||||||
data: jsonBody,
|
data,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleRequestEditorChange = (value: string) => {
|
const handleRequestEditorChange = (value: string) => {
|
||||||
setJsonBody(value);
|
setJsonBody(value);
|
||||||
|
@ -188,6 +236,19 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
||||||
JSON
|
JSON
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li className="nav-item p-2" role="presentation">
|
||||||
|
<button
|
||||||
|
className={`nav-link ${
|
||||||
|
activeTab === "form"
|
||||||
|
? "text-[black] border-solid border-[black]"
|
||||||
|
: "text-[grey]"
|
||||||
|
}`}
|
||||||
|
id="form-tab"
|
||||||
|
onClick={() => setActiveTab("form")}
|
||||||
|
>
|
||||||
|
Form
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className="tab-content p-3 border-top-0 border">
|
<div className="tab-content p-3 border-top-0 border">
|
||||||
|
@ -256,6 +317,32 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{activeTab === "form" && (
|
||||||
|
<div
|
||||||
|
className="tab-pane fade show active h-auto overflow-hidden"
|
||||||
|
id="json"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="json-tab"
|
||||||
|
>
|
||||||
|
{formData.map((header, index) => (
|
||||||
|
<KeyValuePair2
|
||||||
|
key={index}
|
||||||
|
index={index}
|
||||||
|
pair={header}
|
||||||
|
setPairs={setformData}
|
||||||
|
pairs={formData}
|
||||||
|
setisSaved={setisSaved}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleAddFormData}
|
||||||
|
className="mt-2 btn btn-outline-success border-solid border-[green] text-[green]"
|
||||||
|
>
|
||||||
|
Add Form
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { FaCloudUploadAlt } from "react-icons/fa";
|
||||||
|
import { FaArrowDown, FaXmark } from "react-icons/fa6";
|
||||||
|
|
||||||
|
interface KeyValuePairProps {
|
||||||
|
index: number;
|
||||||
|
pair: { key: string; value: string | File[]; type: "text" | "[]" };
|
||||||
|
setPairs: React.Dispatch<
|
||||||
|
React.SetStateAction<
|
||||||
|
{ key: string; value: string | File[]; type: "text" | "file" }[]
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
pairs: { key: string; value: string | File[]; type: "text" | "file" }[];
|
||||||
|
setisSaved: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const KeyValuePair: React.FC<KeyValuePairProps> = ({
|
||||||
|
index,
|
||||||
|
pair,
|
||||||
|
setPairs,
|
||||||
|
pairs,
|
||||||
|
setisSaved,
|
||||||
|
}) => {
|
||||||
|
const [type, settype] = useState("text");
|
||||||
|
const handleKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newPairs = [...pairs];
|
||||||
|
newPairs[index] = { ...newPairs[index], key: e.target.value };
|
||||||
|
setPairs(newPairs);
|
||||||
|
setisSaved(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleValueChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newPairs = [...pairs];
|
||||||
|
if (type === "text") {
|
||||||
|
newPairs[index] = { ...newPairs[index], value: e.target.value };
|
||||||
|
} else if (type === "file" && e.target.files) {
|
||||||
|
const files = Array.from(e.target.files); // Support multiple files
|
||||||
|
newPairs[index] = { ...newPairs[index], value: files };
|
||||||
|
}
|
||||||
|
setPairs(newPairs);
|
||||||
|
setisSaved(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
const newPairs = [...pairs];
|
||||||
|
settype(e.target.value);
|
||||||
|
newPairs[index] = {
|
||||||
|
...newPairs[index],
|
||||||
|
type: e.target.value,
|
||||||
|
value: "",
|
||||||
|
};
|
||||||
|
setPairs(newPairs);
|
||||||
|
setisSaved(false);
|
||||||
|
};
|
||||||
|
const handleRemoveFile = (fileToRemove: File) => {
|
||||||
|
const newPairs = [...pairs];
|
||||||
|
const updatedFiles = (newPairs[index].value as File[]).filter(
|
||||||
|
(file) => file !== fileToRemove
|
||||||
|
);
|
||||||
|
newPairs[index] = { ...newPairs[index], value: updatedFiles };
|
||||||
|
setPairs(newPairs);
|
||||||
|
setisSaved(false);
|
||||||
|
};
|
||||||
|
const handleRemove = () => {
|
||||||
|
const newPairs = pairs.filter((_, i) => i !== index);
|
||||||
|
setPairs(newPairs);
|
||||||
|
setisSaved(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileClick = () => {
|
||||||
|
const fileInput = document.getElementById(`file-input-${index}`);
|
||||||
|
if (fileInput) {
|
||||||
|
fileInput.click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="flex items-center mb-2 w-full justify-between">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-input flex-grow mr-2 max-w-[200px]"
|
||||||
|
placeholder="Key"
|
||||||
|
value={pair.key}
|
||||||
|
onChange={handleKeyChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<select
|
||||||
|
className="form-select flex w-[100px] mr-2"
|
||||||
|
value={pair.type}
|
||||||
|
onChange={handleTypeChange}
|
||||||
|
>
|
||||||
|
<option value="text">Text</option>
|
||||||
|
<option value="file">File</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
{type === "text" ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-input flex-grow mr-2"
|
||||||
|
placeholder="Value"
|
||||||
|
value={pair.value as string}
|
||||||
|
onChange={handleValueChange}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center min-w-[150px]">
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id={`file-input-${index}`}
|
||||||
|
className="hidden"
|
||||||
|
onChange={handleValueChange}
|
||||||
|
multiple={true} // Updated to boolean for JSX
|
||||||
|
/>
|
||||||
|
<label htmlFor={`file-input-${index}`}>
|
||||||
|
<button
|
||||||
|
onClick={handleFileClick}
|
||||||
|
type="button"
|
||||||
|
className="btn p-2 flex items-center"
|
||||||
|
>
|
||||||
|
<FaCloudUploadAlt />
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
{Array.isArray(pair.value) && pair.value.length > 0 && (
|
||||||
|
<div className="flex flex-wrap ml-2">
|
||||||
|
{pair.value.map((file, idx) => (
|
||||||
|
<div key={idx} className="flex items-center mb-1 border-[#eee] border px-1 rounded-md ">
|
||||||
|
<span className="mr-2 text-[13px]">{file.name}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-danger text-red-400 border-none shadow-none p-1 "
|
||||||
|
onClick={() => handleRemoveFile(file)}
|
||||||
|
>
|
||||||
|
<FaXmark/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-danger text-red-400 border-red-400 p-1 px-3 ml-2"
|
||||||
|
onClick={handleRemove}
|
||||||
|
>
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KeyValuePair;
|
Loading…
Reference in New Issue