half-drop-demo / index.html
Sean Powell
Update submit button to say "Generate".
d07eaa9
<!DOCTYPE html>
<html>
<head>
<title>React API Request Form</title>
<script src="https://cdn.tailwindcss.com"></script>
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
function App() {
const [apiEndpoint, setApiEndpoint] = React.useState('https://cvs65it9x6ibiiep.us-east-1.aws.endpoints.huggingface.cloud');
const [huggingFaceToken, setHuggingFaceToken] = React.useState('');
const [prompt, setPrompt] = React.useState('');
const [desiredOutputWidth, setDesiredOutputWidth] = React.useState('512');
const [text2ImgInferenceSteps, setText2ImgInferenceSteps] = React.useState('50');
const [img2imgInferenceSteps, setImg2imgInferenceSteps] = React.useState('50');
const [Text2ImgGuidanceScale, setText2ImgGuidanceScale] = React.useState('7.14');
const [img2ImgStrength, setImg2ImgStrength] = React.useState('0.6');
const [error, setError] = React.useState('');
const [loading, setLoading] = React.useState(false);
const [imageSrc, setImageSrc] = React.useState(null);
const [loadingText, setLoadingText] = React.useState("Loading");
const [previewMode, setPreviewMode] = React.useState("Half-Drop");
React.useEffect(() => {
let interval;
if (loading) {
interval = setInterval(() => {
setLoadingText(prev => prev.length < 10 ? prev + "." : "Loading");
}, 500); // Update every 500 milliseconds
}
return () => clearInterval(interval);
}, [loading]);
const sendRequest = (event) => {
event.preventDefault();
setError('');
setLoading(true);
fetch(apiEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${huggingFaceToken}`
},
body: JSON.stringify({
inputs: prompt,
desired_output_width: desiredOutputWidth,
text2img_inference_steps: text2ImgInferenceSteps,
img2img_inference_steps: img2imgInferenceSteps,
text2img_guidance_scale: Text2ImgGuidanceScale,
img2img_strength: img2ImgStrength
})
})
.then(response => response.json())
.then(data => {
if (data.error) {
setError(data.error)
} else {
setImageSrc('data:image/jpeg;base64,' + data.image);
}
})
.catch(error => {
console.error('Error:', error);
}).finally(() => {
setLoading(false);
});
};
return (
<div className="grid grid-cols-2 h-screen">
<form onSubmit={sendRequest} className="grid cols-1 max-w-6xl bg-gray-100 h-full p-10 overflow-scroll">
<img src="./pipeline.png"/>
{error ? <div className="bg-red-200 py-2 px-3 rounded-md mb-4">
<strong className="text-bold">Error: </strong>
{error}
</div> : null}
<label className="block text-sm font-medium text-gray-700 cols-1">Inference Endpoint URL:</label>
<input
type="text"
value={apiEndpoint}
onChange={(e) => setApiEndpoint(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700 cols-1">Hugging Face Token:</label>
<p className="text-xs">Without "Bearer " prefix, e.g.
"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":</p>
<input
type="text"
value={huggingFaceToken}
onChange={(e) => setHuggingFaceToken(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700">Prompt:</label>
<input
type="text"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700">Desired Output Width:</label>
<p className="text-xs">The desired width of the final half-drop. Because of rounding during the
process,
the generator will try to get as close to this as possible, but may be off by a few pixels.</p>
<input
type="number"
value={desiredOutputWidth}
onChange={(e) => setDesiredOutputWidth(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700">Text2Img Inference Steps:</label>
<p className="text-xs">The number of steps to take when generating the original image.</p>
<input
type="number"
value={text2ImgInferenceSteps}
onChange={(e) => setText2ImgInferenceSteps(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700">Img2Img Inference Steps:</label>
<p className="text-xs">The number of steps to take when converting the extracted diamond into a
tile.</p>
<input
type="number"
value={img2imgInferenceSteps}
onChange={(e) => setImg2imgInferenceSteps(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700">Text2Img Guidance Scale:</label>
<p className="text-xs">Guidance scale for the original image generation. The pipeline default is
5.</p>
<input
type="number"
value={Text2ImgGuidanceScale}
onChange={(e) => setText2ImgGuidanceScale(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<label className="block text-sm font-medium text-gray-700">Img2Img Strength:</label>
<p className="text-xs">Strength to use when converting the diamond into a repeatable tile, i.e. how
much
it can vary from the original generation. Pipeline default is</p>
<input
type="number"
value={img2ImgStrength}
onChange={(e) => setImg2ImgStrength(e.target.value)}
className="mb-6 p-2 border border-gray-300 rounded"
/>
<input
type="submit"
value="Generate"
className="mt-2 p-2 bg-blue-500 text-white rounded hover:bg-blue-700"
/>
</form>
<div className="p-10 overflow-scroll">
{loading && <p className="mb-8">{loadingText}</p>}
{imageSrc && (
<>
<label htmlFor="pattern-dropdown" className="mr-2">Pattern:</label>
<select
id="pattern-dropdown"
value={previewMode}
onChange={(e) => setPreviewMode(e.target.value)}
className="border border-gray-300 rounded mb-10"
>
<option value="Half Drop">Half-Drop</option>
<option value="Half Drop Tiled">Half-Drop Tiled</option>
</select>
{previewMode !== "Half Drop Tiled" && <img src={imageSrc} alt="Response"/>}
{previewMode === "Half Drop Tiled" && <div className="grid grid-cols-3 h-full">
<div className="flex items-center justify-center">
<img src={imageSrc} alt="Response"/>
</div>
<div className="flex flex-col items-center justify-center">
<img src={imageSrc} alt="Response"/>
<img src={imageSrc} alt="Response"/>
</div>
<div className="flex items-center justify-center">
<img src={imageSrc} alt="Response"/>
</div>
</div>}
</>
)}
</div>
</div>
);
}
ReactDOM.render(<App/>, document.getElementById('app'));
</script>
</body>
</html>