UNPKG

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
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;