Merge pull request from Hakorr/main

Modifier Thumbnail Feature
This commit is contained in:
cmdr2
2022-09-23 18:44:32 +05:30
committed by GitHub
413 changed files with 3123 additions and 325 deletions
ui
index.htmlmodifiers.jsonserver.py
static
modifier-thumbnails
artist
artstation
by_agnes_lawrence_pelton
by_akihito_yoshida
by_alex_grey
by_alexander_jansson
by_alphonse_mucha
by_andy_warhol
by_artgerm
by_asaf_hanuka
by_aubrey_beardsley
by_banksy
by_beeple
by_ben_enwonwu
by_bob_eggleton
by_caravaggio_michelangelo_merisi
by_caspar_david_friedrich
by_chris_foss
by_claude_monet
by_dan_mumford
by_david_mann
by_diego_vela_zquez
by_disney_animation_studios
by_e_douard_manet
by_esao_andrews
by_frida_kahlo
by_gediminas_pranckevicius
by_georgia_o_keeffe
by_greg_rutkowski
by_gustave_dore_
by_gustave_klimt
by_h_r_giger
by_hayao_miyazaki
by_henri_matisse
by_hp_lovecraft
by_ivan_shishkin
by_jack_kirby
by_jackson_pollock
by_james_jean
by_jim_burns
by_johannes_vermeer
by_john_william_waterhouse
by_katsushika_hokusai
by_kim_tschang_yeul
by_ko_young_hoon
by_leonardo_da_vinci
by_lisa_frank
by_m_c_escher
by_mahmoud_sai_d
by_makoto_shinkai
by_marc_simonetti
by_mark_brooks
by_michelangelo
by_pablo_picasso
by_paul_klee
by_peter_mohrbacher
by_pierre-auguste_renoir
by_pixar_animation_studios
by_rembrandt
by_richard_dadd
by_rossdraws
by_salvador_dali_
by_sam_does_arts
by_sandro_botticelli
by_ted_nasmith
by_ten_hundred
by_thomas_kinkade
by_tivadar_csontva_ry_kosztka
by_victo_ngai
by_vincent_di_fate
by_vincent_van_gogh
by_wes_anderson
by_wlop
by_yoshitaka_amano
camera
carving_and_etching
cgi_rendering
cgi_software
color
drawing_style
emotions
pen
visual_style
16-bit
2d
8-bit
anaglyph
anime
art_nouveau
baroque
bauhaus
cartoon
cgi
comic_book
concept_art
constructivist
cubist
dadaist
digital_art
expressionist
fantasy
fauvist
figurative
geometric
graphic_novel
hard_edge_painting
hydrodipped
impressionistic
lithography
manga
minimalist
modern_art
mosaic
mural
naive
neoclassical
photo
realistic
rococo
romantic
street_art
stuckist
surrealist
symbolist
visual_novel
watercolor

@ -200,33 +200,6 @@
margin: 0; margin: 0;
padding: 2px 0; padding: 2px 0;
} }
.prompt-modifier-tag {
border: 1px solid rgb(10, 0, 24);
border-radius: 4px;
padding: 0pt 3pt;
margin-right: 2pt;
cursor: pointer;
display: inline;
background: rgb(163, 163, 163);
color: black;
line-height: 25pt;
float: left;
font-size: 9pt;
}
.prompt-modifier-tag:hover {
background: black;
color: white;
}
#editor-modifiers-entries .prompt-modifier-tag {
background: #110f0f;
color: rgb(212, 212, 212);
margin-bottom: 4pt;
font-size: 10pt;
}
#editor-modifiers-entries .prompt-modifier-tag:hover {
background: rgb(163, 163, 163);
color: black;
}
#editor-modifiers .editor-modifiers-leaf { #editor-modifiers .editor-modifiers-leaf {
padding-top: 10pt; padding-top: 10pt;
padding-bottom: 10pt; padding-bottom: 10pt;
@ -271,6 +244,221 @@
height: 23px; height: 23px;
transform: translateY(25%); transform: translateY(25%);
} }
.modifier-card {
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
transition: 0.1s;
border-radius: 7px;
margin: 3pt 3pt;
float: left;
width: 8em;
height: 11.5em;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 8em 3.5em;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"modifier-card-image-container"
"modifier-card-container";
border: 2px solid rgba(255, 255, 255, .05);
cursor: pointer;
}
.modifier-card-size_5 {
width: 18em;
grid-template-rows: 18em 3.5em;
height: 21.5em;
}
.modifier-card-size_5 .modifier-card-image-overlay {
font-size: 8em;
}
.modifier-card-size_4 {
width: 14em;
grid-template-rows: 14em 3.5em;
height: 17.5em;
}
.modifier-card-size_4 .modifier-card-image-overlay {
font-size: 7em;
}
.modifier-card-size_3 {
width: 11em;
grid-template-rows: 11em 3.5em;
height: 14.5em;
}
.modifier-card-size_3 .modifier-card-image-overlay {
font-size: 6em;
}
.modifier-card-size_2 {
width: 10em;
grid-template-rows: 10em 3.5em;
height: 13.5em;
}
.modifier-card-size_2 .modifier-card-image-overlay {
font-size: 6em;
}
.modifier-card-size_1 {
width: 9em;
grid-template-rows: 9em 3.5em;
height: 12.5em;
}
.modifier-card-size_1 .modifier-card-image-overlay {
font-size: 5em;
}
.modifier-card-size_-1 {
width: 7em;
grid-template-rows: 7em 3.5em;
height: 10.5em;
}
.modifier-card-size_-1 .modifier-card-image-overlay {
font-size: 4em;
}
.modifier-card-size_-2 {
width: 6em;
grid-template-rows: 6em 3.5em;
height: 9.5em;
}
.modifier-card-size_-2 .modifier-card-image-overlay {
font-size: 3em;
}
.modifier-card-size_-3 {
width: 5em;
grid-template-rows: 5em 3.5em;
height: 8.5em;
}
.modifier-card-size_-3 .modifier-card-image-overlay {
font-size: 3em;
}
.modifier-card-size_-3 p {
font-size: 0.8em;
}
.modifier-card-tiny {
width: 6em;
height: 9.5em;
grid-template-rows: 6em 3.5em;
}
.modifier-card-tiny p {
font-size: 0.7em;
}
.modifier-card:hover {
transform: scale(1.05);
box-shadow: 0 5px 16px 5px rgba(0, 0, 0, 0.25);
}
.modifier-card-image-container {
border-radius: 5px 5px 0 0;
width: inherit;
height: 100%;
background-color: rgba(0, 0, 0, .2);
grid-area: modifier-card-image-container;
position: relative;
display: flex;
align-items: center;
justify-content: center;
color: rgb(255 255 255 / 8%);
}
.modifier-card-image-container img {
width: inherit;
height: 100%;
border-radius: 5px 5px 0 0;
}
.modifier-card-image-container * {
position: absolute;
}
.modifier-card-container {
text-align: center;
background-color: rgba(0,0,0,0.5);
border-radius: 0 0 5px 5px;
display: flex;
justify-content: center;
align-items: center;
grid-area: modifier-card-container;
font-weight: 100;
font-size: .9em;
width: inherit;
}
.modifier-card-label {
padding: 4px;
word-break: break-word;
}
.modifier-card-image-overlay {
width: inherit;
height: inherit;
background-color: rgb(0 0 0 / 50%);
z-index: 2;
position: absolute;
border-radius: 5px 5px 0 0;
opacity: 0;
font-size: 5em;
font-weight: 900;
color: rgb(255 255 255 / 50%);
display: flex;
align-items: center;
justify-content: center;
}
.modifier-card-overlay {
width: inherit;
height: inherit;
position: absolute;
z-index: 3;
}
.modifier-card:hover > .modifier-card-image-container .modifier-card-image-overlay {
opacity: 1;
}
.modifier-card:hover > .modifier-card-image-container img {
filter: blur(.1em);
}
.modifier-card:active {
transform: scale(0.95);
box-shadow: 0 5px 16px 5px rgba(0, 0, 0, 0.5);
}
#preview-image {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.modifier-card-active {
border: 2px solid rgb(179 82 255 / 94%);
box-shadow: 0 0px 10px 0 rgb(170 0 229 / 58%);
}
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltip-text {
visibility: hidden;
width: 120px;
background: rgb(101,97,181);
background: linear-gradient(180deg, rgba(101,97,181,1) 0%, rgba(47,45,85,1) 100%);
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
top: 105%;
left: 39%;
margin-left: -60px;
opacity: 0;
transition: opacity 0.3s;
border: 2px solid rgb(90 100 177 / 94%);
box-shadow: 0px 10px 20px 5px rgb(11 0 58 / 55%);
width: 10em;
}
.tooltip .tooltip-text::after {
content: "";
position: absolute;
top: -0.9em;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent rgb(90 100 177 / 94%) transparent;
}
.tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
#modifier-card-size-slider {
width: 6em;
margin-bottom: 0.5em;
}
</style> </style>
</html> </html>
<body> <body>
@ -300,8 +488,7 @@
<div id="editor-inputs-tags-container" class="row"> <div id="editor-inputs-tags-container" class="row">
<label>Tags: <small>(click a tag to remove it)</small></label> <label>Tags: <small>(click a tag to remove it)</small></label>
<div id="editor-inputs-tags-list"> <div id="editor-inputs-tags-list"></div>
</div>
</div> </div>
<button id="makeImage">Make Image</button> <button id="makeImage">Make Image</button>
@ -389,6 +576,15 @@
<div id="editor-modifiers" class="panel-box"> <div id="editor-modifiers" class="panel-box">
<h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4> <h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4>
<div id="editor-modifiers-entries" class="collapsible-content"> <div id="editor-modifiers-entries" class="collapsible-content">
<label for="preview-image">Preview:</label>
<select id="preview-image" name="preview-image" value="portrait">
<option value="portrait" selected="">Portrait</option>
<option value="landscape">Landscape</option>
</select>
<div>
<label for="modifier-card-size-slider">Card Size:</label>
<input id="modifier-card-size-slider" name="modifier-card-size-slider" value="0" type="range" min="-3" max="5">
</div>
</div> </div>
</div> </div>
</div> </div>
@ -478,6 +674,12 @@ let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list') let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container') let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
let previewImageField = document.querySelector('#preview-image')
previewImageField.onchange = () => changePreviewImages(previewImageField.value);
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value);
let previewPrompt = document.querySelector('#preview-prompt') let previewPrompt = document.querySelector('#preview-prompt')
let showConfigToggle = document.querySelector('#configToggleBtn') let showConfigToggle = document.querySelector('#configToggleBtn')
@ -494,9 +696,13 @@ let modifiersPanelHandle = document.querySelector("#editor-modifiers .collapsibl
let serverStatus = 'offline' let serverStatus = 'offline'
let activeTags = [] let activeTags = []
let modifiers = []
let lastPromptUsed = '' let lastPromptUsed = ''
let taskStopped = true let taskStopped = true
const modifierThumbnailPath = 'static/modifier-thumbnails';
const activeCardClass = 'modifier-card-active';
function getLocalStorageItem(key, fallback) { function getLocalStorageItem(key, fallback) {
let item = localStorage.getItem(key) let item = localStorage.getItem(key)
if (item === null) { if (item === null) {
@ -580,12 +786,12 @@ function setStatus(statusType, msg, msgType) {
// msg = '<span style="color: red">' + msg + '<span>' // msg = '<span style="color: red">' + msg + '<span>'
serverStatusColor.style.backgroundColor = 'red' serverStatusColor.style.backgroundColor = 'red'
serverStatusMsg.style.color = 'red' serverStatusMsg.style.color = 'red'
serverStatusMsg.innerHTML = 'Stable Diffusion has stopped' serverStatusMsg.innerText = 'Stable Diffusion has stopped'
} else if (msgType == 'success') { } else if (msgType == 'success') {
// msg = '<span style="color: green">' + msg + '<span>' // msg = '<span style="color: green">' + msg + '<span>'
serverStatusColor.style.backgroundColor = 'green' serverStatusColor.style.backgroundColor = 'green'
serverStatusMsg.style.color = 'green' serverStatusMsg.style.color = 'green'
serverStatusMsg.innerHTML = 'Stable Diffusion is ready' serverStatusMsg.innerText = 'Stable Diffusion is ready'
serverStatus = 'online' serverStatus = 'online'
} }
} }
@ -596,7 +802,7 @@ function logMsg(msg, level) {
} else if (level === 'warn') { } else if (level === 'warn') {
outputMsg.innerHTML = '<span style="color: orange">Warning: ' + msg + '</span>' outputMsg.innerHTML = '<span style="color: orange">Warning: ' + msg + '</span>'
} else { } else {
outputMsg.innerHTML = msg outputMsg.innerText = msg
} }
console.log(level, msg) console.log(level, msg)
@ -716,15 +922,15 @@ async function doMakeImage(reqBody) {
let imgSeedLabel = document.createElement('span') let imgSeedLabel = document.createElement('span')
imgSeedLabel.className = 'imgSeedLabel' imgSeedLabel.className = 'imgSeedLabel'
imgSeedLabel.innerHTML = 'Seed: ' + seed imgSeedLabel.innerText = 'Seed: ' + seed
let imgUseBtn = document.createElement('button') let imgUseBtn = document.createElement('button')
imgUseBtn.className = 'imgUseBtn' imgUseBtn.className = 'imgUseBtn'
imgUseBtn.innerHTML = 'Use as Input' imgUseBtn.innerText = 'Use as Input'
let imgSaveBtn = document.createElement('button') let imgSaveBtn = document.createElement('button')
imgSaveBtn.className = 'imgSaveBtn' imgSaveBtn.className = 'imgSaveBtn'
imgSaveBtn.innerHTML = 'Download' imgSaveBtn.innerText = 'Download'
imgItem.appendChild(img) imgItem.appendChild(img)
imgItem.appendChild(imgItemInfo) imgItem.appendChild(imgItemInfo)
@ -815,11 +1021,11 @@ async function makeImage() {
let prompt = promptField.value let prompt = promptField.value
if (activeTags.length > 0) { if (activeTags.length > 0) {
let promptTags = activeTags.join(", ") let promptTags = activeTags.map(x => x.name).join(", ");
prompt += ", " + promptTags prompt += ", " + promptTags;
} }
previewPrompt.innerHTML = prompt previewPrompt.innerText = prompt
let reqBody = { let reqBody = {
prompt: prompt, prompt: prompt,
@ -870,12 +1076,12 @@ async function makeImage() {
let success = await doMakeImage(reqBody) let success = await doMakeImage(reqBody)
if (success) { if (success) {
outputMsg.innerHTML = 'Processed batch ' + (i+1) + '/' + batchCount outputMsg.innerText = 'Processed batch ' + (i+1) + '/' + batchCount
successCount++ successCount++
} }
} }
makeImageBtn.innerHTML = 'Make Image' makeImageBtn.innerText = 'Make Image'
makeImageBtn.disabled = false makeImageBtn.disabled = false
makeImageBtn.style.display = 'block' makeImageBtn.style.display = 'block'
stopImageBtn.style.display = 'none' stopImageBtn.style.display = 'none'
@ -888,7 +1094,7 @@ async function makeImage() {
time /= 1000 time /= 1000
if (successCount === batchCount) { if (successCount === batchCount) {
outputMsg.innerHTML = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds' outputMsg.innerText = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds'
setStatus('request', 'done', 'success') setStatus('request', 'done', 'success')
} }
@ -1071,7 +1277,7 @@ async function getAppConfig() {
if (config.update_branch === 'beta') { if (config.update_branch === 'beta') {
useBetaChannelField.checked = true useBetaChannelField.checked = true
updateBranchLabel.innerHTML = "(beta)" updateBranchLabel.innerText = "(beta)"
} }
console.log('get config status response', config) console.log('get config status response', config)
@ -1202,30 +1408,33 @@ function createCollapsibles(node) {
createCollapsibles() createCollapsibles()
function refreshTagsList() { function refreshTagsList() {
editorModifierTagsList.innerHTML = '' editorModifierTagsList.innerHTML = '';
if (activeTags.length == 0) { if (activeTags.length == 0) {
editorTagsContainer.style.display = 'none' editorTagsContainer.style.display = 'none';
return return;
} else { } else {
editorTagsContainer.style.display = 'block' editorTagsContainer.style.display = 'block';
} }
activeTags.forEach(function(tag) { activeTags.forEach((tag, index) => {
let el = document.createElement('div') tag.element.querySelector('.modifier-card-image-overlay').innerText = '-';
el.className = 'prompt-modifier-tag' tag.element.classList.add('modifier-card-tiny');
el.innerHTML = tag
editorModifierTagsList.appendChild(el) editorModifierTagsList.appendChild(tag.element);
tag.element.addEventListener('click', () => {
let idx = activeTags.indexOf(tag);
el.addEventListener('click', function() {
let idx = activeTags.indexOf(tag)
if (idx !== -1) { if (idx !== -1) {
activeTags.splice(idx, 1) activeTags[idx].originElement.classList.remove(activeCardClass);
refreshTagsList() activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+';
activeTags.splice(idx, 1);
refreshTagsList();
} }
}) });
}) });
let brk = document.createElement('br') let brk = document.createElement('br')
brk.style.clear = 'both' brk.style.clear = 'both'
@ -1253,39 +1462,164 @@ async function getDiskPath() {
} }
} }
function createModifierCard(name, previews) {
const modifierCard = document.createElement('div');
modifierCard.className = 'modifier-card';
modifierCard.innerHTML = `
<div class="modifier-card-overlay"></div>
<div class="modifier-card-image-container">
<div class="modifier-card-image-overlay">+</div>
<p class="modifier-card-error-label"></p>
<img onerror="this.remove()" alt="Modifier Image" class="modifier-card-image">
</div>
<div class="modifier-card-container">
<div class="modifier-card-label"><p></p></div>
</div>`;
const image = modifierCard.querySelector('.modifier-card-image');
const errorText = modifierCard.querySelector('.modifier-card-error-label');
const label = modifierCard.querySelector('.modifier-card-label');
errorText.innerText = 'No Image';
if (typeof previews == 'object') {
image.src = previews[0]; // portrait
image.setAttribute('preview-type', 'portrait');
} else {
image.remove();
}
const maxLabelLength = 30;
const nameWithoutBy = name.replace('by ', '');
if(nameWithoutBy.length <= maxLabelLength) {
label.querySelector('p').innerText = nameWithoutBy;
} else {
const tooltipText = document.createElement('span');
tooltipText.className = 'tooltip-text';
tooltipText.innerText = name;
label.classList.add('tooltip');
label.appendChild(tooltipText);
label.querySelector('p').innerText = nameWithoutBy.substring(0, maxLabelLength) + '...';
}
return modifierCard;
}
function changePreviewImages(val) {
const previewImages = document.querySelectorAll('.modifier-card-image-container img');
let previewArr = [];
modifiers.map(x => x.modifiers).forEach(x => previewArr.push(...x.map(m => m.previews)));
previewArr = previewArr.map(x => {
let obj = {};
x.forEach(preview => {
obj[preview.name] = preview.path;
});
return obj;
});
previewImages.forEach(previewImage => {
const currentPreviewType = previewImage.getAttribute('preview-type');
const relativePreviewPath = previewImage.src.split(modifierThumbnailPath + '/').pop();
const previews = previewArr.find(preview => relativePreviewPath == preview[currentPreviewType]);
if(typeof previews == 'object') {
let preview = null;
if (val == 'portrait') {
preview = previews.portrait;
}
else if (val == 'landscape') {
preview = previews.landscape;
}
if(preview != null) {
previewImage.src = `${modifierThumbnailPath}/${preview}`;
previewImage.setAttribute('preview-type', val);
}
}
});
}
function resizeModifierCards(val) {
const cardSizePrefix = 'modifier-card-size_';
const modifierCardClass = 'modifier-card';
const modifierCards = document.querySelectorAll(`.${modifierCardClass}`);
const cardSize = n => `${cardSizePrefix}${n}`;
modifierCards.forEach(card => {
// remove existing size classes
const classes = card.className.split(' ').filter(c => !c.startsWith(cardSizePrefix));
card.className = classes.join(' ').trim();
if(val != 0)
card.classList.add(cardSize(val));
});
}
async function loadModifiers() { async function loadModifiers() {
try { try {
let res = await fetch('/modifiers.json') let res = await fetch('/modifiers.json')
if (res.status === 200) { if (res.status === 200) {
res = await res.json() res = await res.json()
res.forEach(function(m) { modifiers = res; // update global variable
let title = m[0]
let modifiers = m[1]
let titleEl = document.createElement('h5') res.forEach(modifierGroup => {
titleEl.className = 'collapsible' const title = modifierGroup.category;
titleEl.innerHTML = title const modifiers = modifierGroup.modifiers;
let modifiersEl = document.createElement('div') const titleEl = document.createElement('h5');
modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf') titleEl.className = 'collapsible';
titleEl.innerText = title;
modifiers.forEach(function(modifier) { const modifiersEl = document.createElement('div');
let tagEl = document.createElement('div') modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf');
tagEl.className = 'prompt-modifier-tag'
tagEl.innerHTML = modifier
modifiersEl.appendChild(tagEl) modifiers.forEach(modObj => {
const modifierName = modObj.modifier;
const modifierPreviews = modObj?.previews?.map(preview => `${modifierThumbnailPath}/${preview.path}`);
tagEl.addEventListener('click', function() { const modifierCard = createModifierCard(modifierName, modifierPreviews);
if (activeTags.includes(modifier)) {
return if(typeof modifierCard == 'object') {
modifiersEl.appendChild(modifierCard);
modifierCard.addEventListener('click', () => {
if (activeTags.map(x => x.name).includes(modifierName)) {
// remove modifier from active array
activeTags = activeTags.filter(x => x.name != modifierName);
modifierCard.classList.remove(activeCardClass);
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+';
} else {
// add modifier to active array
activeTags.push({
'name': modifierName,
'element': modifierCard.cloneNode(true),
'originElement': modifierCard,
'previews': modifierPreviews
});
modifierCard.classList.add(activeCardClass);
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '-';
} }
activeTags.push(modifier) refreshTagsList();
refreshTagsList() });
}) }
}) });
let brk = document.createElement('br') let brk = document.createElement('br')
brk.style.clear = 'both' brk.style.clear = 'both'
modifiersEl.appendChild(brk) modifiersEl.appendChild(brk)

File diff suppressed because it is too large Load Diff

@ -10,11 +10,14 @@ print('started in ', SCRIPT_DIR)
SD_UI_DIR = os.getenv('SD_UI_PATH', None) SD_UI_DIR = os.getenv('SD_UI_PATH', None)
sys.path.append(os.path.dirname(SD_UI_DIR)) sys.path.append(os.path.dirname(SD_UI_DIR))
STATIC_DIR = os.path.join(SD_UI_DIR, "static")
CONFIG_DIR = os.path.join(SD_UI_DIR, '..', 'scripts') CONFIG_DIR = os.path.join(SD_UI_DIR, '..', 'scripts')
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse from starlette.responses import FileResponse
from pydantic import BaseModel from pydantic import BaseModel
import logging import logging
@ -196,5 +199,7 @@ class HealthCheckLogFilter(logging.Filter):
logging.getLogger('uvicorn.access').addFilter(HealthCheckLogFilter()) logging.getLogger('uvicorn.access').addFilter(HealthCheckLogFilter())
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
# start the browser ui # start the browser ui
import webbrowser; webbrowser.open('http://localhost:9000') import webbrowser; webbrowser.open('http://localhost:9000')

Binary file not shown.

After

(image error) Size: 38 KiB

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 23 KiB

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 36 KiB

Binary file not shown.

After

(image error) Size: 33 KiB

Binary file not shown.

After

(image error) Size: 90 KiB

Binary file not shown.

After

(image error) Size: 59 KiB

Binary file not shown.

After

(image error) Size: 66 KiB

Binary file not shown.

After

(image error) Size: 66 KiB

Binary file not shown.

After

(image error) Size: 75 KiB

Binary file not shown.

After

(image error) Size: 45 KiB

Binary file not shown.

After

(image error) Size: 76 KiB

Binary file not shown.

After

(image error) Size: 41 KiB

Binary file not shown.

After

(image error) Size: 51 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 94 KiB

Binary file not shown.

After

(image error) Size: 56 KiB

Binary file not shown.

After

(image error) Size: 77 KiB

Binary file not shown.

After

(image error) Size: 44 KiB

Binary file not shown.

After

(image error) Size: 48 KiB

Binary file not shown.

After

(image error) Size: 54 KiB

Binary file not shown.

After

(image error) Size: 46 KiB

Binary file not shown.

After

(image error) Size: 31 KiB

Binary file not shown.

After

(image error) Size: 30 KiB

Binary file not shown.

After

(image error) Size: 32 KiB

Binary file not shown.

After

(image error) Size: 56 KiB

Binary file not shown.

After

(image error) Size: 52 KiB

Binary file not shown.

After

(image error) Size: 54 KiB

Binary file not shown.

After

(image error) Size: 42 KiB

Binary file not shown.

After

(image error) Size: 42 KiB

Binary file not shown.

After

(image error) Size: 33 KiB

Binary file not shown.

After

(image error) Size: 47 KiB

Binary file not shown.

After

(image error) Size: 56 KiB

Binary file not shown.

After

(image error) Size: 52 KiB

Binary file not shown.

After

(image error) Size: 62 KiB

Binary file not shown.

After

(image error) Size: 110 KiB

Binary file not shown.

After

(image error) Size: 84 KiB

Binary file not shown.

After

(image error) Size: 38 KiB

Binary file not shown.

After

(image error) Size: 38 KiB

Binary file not shown.

After

(image error) Size: 47 KiB

Binary file not shown.

After

(image error) Size: 40 KiB

Binary file not shown.

After

(image error) Size: 41 KiB

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 52 KiB

Binary file not shown.

After

(image error) Size: 44 KiB

Binary file not shown.

After

(image error) Size: 48 KiB

Binary file not shown.

After

(image error) Size: 42 KiB

Binary file not shown.

After

(image error) Size: 62 KiB

Binary file not shown.

After

(image error) Size: 50 KiB

Binary file not shown.

After

(image error) Size: 41 KiB

Binary file not shown.

After

(image error) Size: 354 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 35 KiB

Binary file not shown.

After

(image error) Size: 43 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 57 KiB

Binary file not shown.

After

(image error) Size: 87 KiB

Binary file not shown.

After

(image error) Size: 55 KiB

Binary file not shown.

After

(image error) Size: 57 KiB

Binary file not shown.

After

(image error) Size: 80 KiB

Binary file not shown.

After

(image error) Size: 60 KiB

Binary file not shown.

After

(image error) Size: 58 KiB

Binary file not shown.

After

(image error) Size: 38 KiB

Binary file not shown.

After

(image error) Size: 56 KiB

Binary file not shown.

After

(image error) Size: 43 KiB

Binary file not shown.

After

(image error) Size: 45 KiB

Binary file not shown.

After

(image error) Size: 56 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 46 KiB

Binary file not shown.

After

(image error) Size: 61 KiB

Binary file not shown.

After

(image error) Size: 50 KiB

Binary file not shown.

After

(image error) Size: 88 KiB

Binary file not shown.

After

(image error) Size: 67 KiB

Binary file not shown.

After

(image error) Size: 84 KiB

Binary file not shown.

After

(image error) Size: 60 KiB

Binary file not shown.

After

(image error) Size: 53 KiB

Binary file not shown.

After

(image error) Size: 33 KiB

Binary file not shown.

After

(image error) Size: 38 KiB

Binary file not shown.

After

(image error) Size: 420 KiB

Binary file not shown.

After

(image error) Size: 58 KiB

Binary file not shown.

After

(image error) Size: 47 KiB

Binary file not shown.

After

(image error) Size: 60 KiB

Binary file not shown.

After

(image error) Size: 51 KiB

Binary file not shown.

After

(image error) Size: 29 KiB

Binary file not shown.

After

(image error) Size: 29 KiB

Binary file not shown.

After

(image error) Size: 31 KiB

Binary file not shown.

After

(image error) Size: 31 KiB

Binary file not shown.

After

(image error) Size: 65 KiB

Binary file not shown.

After

(image error) Size: 53 KiB

Binary file not shown.

After

(image error) Size: 90 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 75 KiB

Binary file not shown.

After

(image error) Size: 54 KiB

Binary file not shown.

After

(image error) Size: 29 KiB

Binary file not shown.

After

(image error) Size: 41 KiB

Binary file not shown.

After

(image error) Size: 43 KiB

Some files were not shown because too many files have changed in this diff Show More