stable-diffusion-for-fun/templates/index.html

256 lines
12 KiB
HTML

<html lang="en">
<head>
<meta charset="utf-8">
<title>Happy Diffusion (Private Access) | 9pm</title>
<meta name="description" content="Stable Diffusion Online">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="card mb-3">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs">
<li class="nav-item">
<a class="nav-link active" href="#">Text-to-Image</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Image-to-Image</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Inpainting</a>
</li>
</ul>
</div>
<div class="card-body">
<form>
<div class="row mb-3">
<div class="col-sm-8">
<label for="apiKey" class="form-label">API Key</label>
<input type="password" class="form-control" id="apiKey" value="demo">
</div>
<div class="col-sm-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="showPreview" disabled>
<label class="form-check-label" for="showPreview">
Preview Image
</label>
</div>
</div>
</div>
<div class="form-row mb-3">
<label for="prompt" class="form-label">Prompt</label>
<input type="text" class="form-control" id="prompt" aria-describedby="promptHelp"
value="photo of cute cat, RAW photo, (high detailed skin:1.2), 8k uhd, dslr, soft lighting, high quality, film grain, Fujifilm XT3">
<div id="promptHelp" class="form-text">Less than 77 words otherwise it'll be truncated</div>
</div>
<div class="form-row mb-3">
<label for="negPrompt" class="form-label">Negative Prompt</label>
<input type="text" class="form-control" id="negPrompt" aria-describedby="negPromptHelp"
value="(deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime:1.4), text, close up, cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck">
<div id="negPromptHelp" class="form-text">Less than 77 words otherwise it'll be truncated</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="form-row col-md-6">
<label for="inputSeed">Seed</label>
<input type="number" class="form-control" id="inputSeed"
aria-describedby="inputSeedHelp" value="">
<div id="inputSeedHelp" class="form-text">Leave it empty or put 0 to use a random
seed
</div>
</div>
<div class="form-row col-md-6">
<label for="inputSteps">Steps</label>
<input type="number" class="form-control" id="inputSteps"
aria-describedby="inputStepsHelp" placeholder="default is 50">
<div id="inputStepsHelp" class="form-text">Each step is about 38s (CPU) or 0.1s
(GPU)
</div>
</div>
</div>
<div class="row">
<div class="form-row col-md-6">
<label for="inputWidth">Width</label>
<input type="number" class="form-control" id="inputWidth" placeholder="512" min="1"
max="1024">
</div>
<div class="form-row col-md-6">
<label for="inputHeight">Height</label>
<input type="number" class="form-control" id="inputHeight" placeholder="512" min="1"
max="1024">
</div>
</div>
<button id="newJob" type="submit" class="btn btn-primary">Let's Go!</button>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
Result
</div>
<div class="card-body">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center"
id="resultStatus"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="resultSeed"></li>
</ul>
</div>
<img class="card-img-bottom" id="newJobImg">
</div>
</div>
</div>
</form>
</div>
</div>
<form>
<div class="mb-3">
<label for="jobuuid" class="form-label">Job UUID</label>
<input type="jobuuid" class="form-control" id="jobuuid" aria-describedby="">
</div>
<button id="getjob" type="submit" class="btn btn-primary" disabled>Get Jobs</button>
<button id="canceljob" type="submit" class="btn btn-primary" disabled>Cancel Job</button>
</form>
<div class="mb-3" id="joblist">
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"
integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3"
crossorigin="anonymous"></script>
<script>
function waitForImage(apikeyVal, uuidValue) {
// Wait until image is done
$.ajax({
type: 'POST',
url: '/get_jobs',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({ 'api_key': apikeyVal, 'uuid': uuidValue }),
success: function (response) {
console.log(response);
if (response.jobs.length == 1) {
$('#resultStatus').html(response.jobs[0].status)
$('#resultSeed').html(response.jobs[0].seed)
if (response.jobs[0].status == "done") {
$('#newJobImg').attr('src', response.jobs[0].img);
return;
}
if (response.jobs[0].status == "failed") {
return;
}
}
setTimeout(function () { waitForImage(apikeyVal, uuidValue); }, 1000); // refresh every second
},
error: function (xhr, status, error) {
// Handle error response
console.log(xhr.responseText);
$('#resultStatus').html('failed');
}
});
}
$(document).ready(function () {
console.log("--- csrf token set ---");
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$('#newJob').click(function (e) {
e.preventDefault(); // Prevent the default form submission
// Gather input field values
var apikeyVal = $('#apiKey').val();
var promptVal = $('#prompt').val();
var negPromptVal = $('#negPrompt').val();
var seedVal = parseInt($('#inputSeed').val());
if (isNaN(seedVal)) {
seedVal = 0;
}
var stepsVal = parseInt($('#inputSteps').val());
if (isNaN(stepsVal)) {
stepsVal = 50;
}
var widthVal = parseInt($('#inputWidth').val());
if (isNaN(widthVal)) {
widthVal = 512;
}
var heightVal = parseInt($('#inputHeight').val());
if (isNaN(heightVal)) {
heightVal = 512;
}
if (promptVal == "") {
alert("needs to write a prompt!");
return;
}
if (widthVal % 8 != 0) {
alert("width must be divisible by 8!");
return;
}
if (heightVal % 8 != 0) {
alert("height must be divisible by 8!");
return;
}
// Send POST request using Ajax
$.ajax({
type: 'POST',
url: '/add_job',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({
'api_key': apikeyVal,
'prompt': promptVal,
'seed': seedVal,
'steps': stepsVal,
'width': widthVal,
'height': heightVal,
'neg_prompt': negPromptVal
}),
success: function (response) {
console.log(response);
if (response.uuid) {
$('#jobuuid').val(response.uuid);
}
$('#resultStatus').html('submitting new job..');
waitForImage(apikeyVal, response.uuid);
},
error: function (xhr, status, error) {
// Handle error response
console.log(xhr.responseText);
$('#resultStatus').html('failed');
}
});
});
});
</script>
</body>
</html>