leumas-universal-crud-react
Version:
Leumas Universal CRUD to a dynamic Endpoint, Setup your own Dynamic Endpoint and Use Leumas API to send to your MONGO clusters
228 lines (210 loc) • 8.3 kB
JSX
import React, { useState, useEffect } from 'react';
import useAuthUser from 'react-auth-kit/hooks/useAuthUser';
import useIsAuthenticated from 'react-auth-kit/hooks/useIsAuthenticated';
import { AtomSpinner } from 'react-epic-spinners';
import { LeumasBaseStyle } from "../../styles/baseStyles";
import { runEndpoint } from './Helpers/runEndpoint';
import { useTheme } from "../../Theme/ThemeContext";
import { getItemsByOwner } from "../UniversalCrud/UniversalCrudHelpers";
import { useParams } from "react-router-dom";
import Breadcrumbs from "../../Components/Breadcrumbs";
import SaveButton from "../UniversalCrud/SaveButton";
import CustomDropdown from "../UniversalCrud/CustomDropdown";
const lightThemeColors = {
background: '#FAFAFA',
primary: '#0077C0',
secondary: '#C7EEFF',
text: '#1D242B',
};
const darkThemeColors = {
background: '#1D242B',
primary: '#0077C0',
secondary: '#2A3B4D',
text: '#FAFAFA',
cardText: '#E0E0E0',
};
const useColors = (theme) => {
return theme === 'dark' ? darkThemeColors : lightThemeColors;
};
const SingleEndpointBuilder = ({ onResult, hideResult, hideButton, block }) => {
const isAuthenticated = useIsAuthenticated();
const isLoggedIn = isAuthenticated();
const user = useAuthUser();
const { id } = useParams();
const [endpoint, setEndpoint] = useState({
owner: user?.id,
endpoint: {
method: block?.data?.endpoint?.method || 'POST',
endpoint: block?.data?.endpoint?.endpoint || 'https://api.openai.com/v1/chat/completions',
body: JSON.stringify({
model: block?.data?.endpoint?.body?.model || "gpt-3.5-turbo",
messages: [
{ role: "user", content: "Hello, who are you?" },
{ role: "assistant", content: "I am an AI created by OpenAI." }
]
}, null, 2),
headers: block?.data?.endpoint?.headers || JSON.stringify({
'Content-Type': 'application/json',
'Authorization': `Bearer YOUR_OPENAI_API_KEY`
}, null, 2),
params: block?.data?.endpoint?.params || '{}',
}
});
const [isLoading, setIsLoading] = useState(false);
const [result, setResult] = useState(null);
const [endpoints, setEndpoints] = useState([]);
const [error, setError] = useState(null);
const { theme } = useTheme();
const colors = useColors(theme);
const [message, setMessage] = useState(null);
const [messageType, setMessageType] = useState(null);
const handleChange = (field, value) => {
setEndpoint(prev => ({
...prev,
endpoint: {
...prev.endpoint,
[field]: value
}
}));
};
const GetOwnedEndpoints = async () => {
setIsLoading(true);
try {
const response = await getItemsByOwner("Endpoint", user?.id, "LeumasAPI", user?.token);
console.log(response);
setEndpoints(response);
if (id) {
const matchedEndpoint = response.find((endpoint) => endpoint._id === id || endpoint._id === id+1 || endpoint.endpoint._id === id || endpoint.endpoint._id === id +1);
if (matchedEndpoint) {
console.log("We matched an endpoint")
console.log(matchedEndpoint)
setEndpoint(matchedEndpoint);
}
}
} catch (err) {
console.error(err);
setError("Could not fetch endpoints");
} finally {
setIsLoading(false);
}
};
useEffect(() => {
if (isLoggedIn) {
GetOwnedEndpoints();
} else {
window.location.href = "/login";
}
}, [isLoggedIn, id]);
const handleRunEndpoint = () => {
setIsLoading(true);
runEndpoint(
`${import.meta.env.VITE_REACT_APP_LEUMAS_API_ENDPOINT}/wildcards/bulk-request`,
endpoint.endpoint,
(data) => {
if (Array.isArray(data) && data.length > 0) {
const result = data[0];
setResult(result);
onResult(result);
} else {
console.log("Unexpected server response format:", data);
}
setIsLoading(false);
},
(error) => {
console.error(error);
setIsLoading(false);
}
);
};
const inputStyle = `border border-gray-300 rounded-lg px-3 py-2 w-full focus:outline-none focus:ring-2 focus:ring-${colors.primary} focus:border-transparent transition bg-transparent`;
return (
<div className="flex flex-col space-y-6 p-6" style={{ backgroundColor: colors.background, borderRadius: '15px', boxShadow: '0 4px 10px rgba(0, 0, 0, 0.1)', color: colors.text }}>
<Breadcrumbs />
<div className="flex items-center justify-center w-full rounded-lg">
<CustomDropdown
model="Endpoint"
modelArray={endpoints}
endpoint="LeumasAPI"
token={user?.token}
onSelectedChange={(data) => { window.location.href = `/endpoints/${data?._id}` }}
/>
<SaveButton
model="Endpoint"
data={endpoint}
isLoading={isLoading}
setIsLoading={setIsLoading}
setMessage={setMessage}
setMessageType={setMessageType}
onSuccess={() => alert("Saved endpoint")}
editMode={id ? true : false}
selectedItemId={id}
/>
</div>
<div className="flex flex-col space-y-4">
<div className="flex space-x-2">
<select
value={endpoint.endpoint.method}
onChange={(e) => handleChange('method', e.target.value)}
className={inputStyle}
style={{ backgroundColor: colors.secondary, color: colors.text }}
>
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
</select>
<input
type="text"
value={endpoint.endpoint.endpoint}
onChange={(e) => handleChange('endpoint', e.target.value)}
className={inputStyle}
style={{ backgroundColor: colors.secondary, color: colors.text }}
placeholder="Enter endpoint URL"
/>
</div>
<label style={{ color: colors.text }}>Headers (JSON)</label>
<textarea
value={endpoint.endpoint.headers}
onChange={(e) => handleChange('headers', e.target.value)}
className={inputStyle}
style={{ backgroundColor: colors.secondary, color: colors.text }}
placeholder="Headers (JSON)"
rows="4"
/>
<label style={{ color: colors.text }}>Params (JSON)</label>
<textarea
value={endpoint.endpoint.params}
onChange={(e) => handleChange('params', e.target.value)}
className={inputStyle}
style={{ backgroundColor: colors.secondary, color: colors.text }}
placeholder="Params (JSON)"
rows="4"
/>
</div>
<div className="flex flex-col space-y-4 mt-6">
<label style={{ color: colors.text }}>Body (JSON)</label>
<textarea
value={endpoint.endpoint.body}
onChange={(e) => handleChange('body', e.target.value)}
className={inputStyle}
style={{ backgroundColor: colors.secondary, color: colors.text, minHeight: '150px' }}
placeholder="Body (JSON)"
rows="6"
/>
</div>
{!hideButton && (
<button onClick={handleRunEndpoint} className={LeumasBaseStyle} style={{ backgroundColor: colors.primary, color: colors.text, padding: '12px 20px', fontSize: '1.2rem', borderRadius: '10px' }}>
Run Endpoint
</button>
)}
{isLoading && <AtomSpinner />}
{result && !hideResult && (
<div className="w-full border rounded-lg p-4 overflow-auto mt-4" style={{ backgroundColor: colors.secondary, color: colors.text, borderRadius: '15px', boxShadow: '0 4px 10px rgba(0, 0, 0, 0.1)' }}>
<p style={{ fontSize: '1.1rem' }}>Result:</p>
<pre className='border-blue-300 rounded-lg text-[12px]'>{JSON.stringify(result, null, 2)}</pre>
</div>
)}
</div>
);
};
export default SingleEndpointBuilder;