From 97035a54edccf28c5a8fb026c93e5ea4b3da7cf3 Mon Sep 17 00:00:00 2001 From: JeLuF Date: Thu, 27 Jul 2023 21:56:36 +0200 Subject: [PATCH 1/4] Bucket API --- scripts/check_modules.py | 1 + ui/easydiffusion/bucket_crud.py | 5 +- ui/easydiffusion/bucket_manager.py | 76 +++++++++++++++++++++++++++++- ui/easydiffusion/bucket_models.py | 6 +-- ui/easydiffusion/bucket_schemas.py | 1 - 5 files changed, 81 insertions(+), 8 deletions(-) diff --git a/scripts/check_modules.py b/scripts/check_modules.py index 0f50e842..c2713c64 100644 --- a/scripts/check_modules.py +++ b/scripts/check_modules.py @@ -26,6 +26,7 @@ modules_to_check = { "pycloudflared": "0.2.0", "ruamel.yaml": "0.17.21", "sqlalchemy": "2.0.19", + "python-multipart": "0.0.6", # "xformers": "0.0.16", } modules_to_log = ["torch", "torchvision", "sdkit", "stable-diffusion-sdkit"] diff --git a/ui/easydiffusion/bucket_crud.py b/ui/easydiffusion/bucket_crud.py index ece14fcc..5dada176 100644 --- a/ui/easydiffusion/bucket_crud.py +++ b/ui/easydiffusion/bucket_crud.py @@ -29,8 +29,9 @@ def get_bucketfiles(db: Session, skip: int = 0, limit: int = 100): def create_bucketfile(db: Session, bucketfile: bucket_schemas.BucketFileCreate, bucket_id: int): db_bucketfile = bucket_models.BucketFile(**bucketfile.dict(), bucket_id=bucket_id) - db.add(db_bucketfile) + db.merge(db_bucketfile) db.commit() - db.refresh(db_bucketfile) + from pprint import pprint + db_bucketfile = db.query(bucket_models.BucketFile).filter(bucket_models.BucketFile.bucket_id==bucket_id, bucket_models.BucketFile.filename==bucketfile.filename).first() return db_bucketfile diff --git a/ui/easydiffusion/bucket_manager.py b/ui/easydiffusion/bucket_manager.py index 0985573f..58d0e30c 100644 --- a/ui/easydiffusion/bucket_manager.py +++ b/ui/easydiffusion/bucket_manager.py @@ -1,11 +1,31 @@ from typing import List -from fastapi import Depends, FastAPI, HTTPException +from fastapi import Depends, FastAPI, HTTPException, Response, File from sqlalchemy.orm import Session from easydiffusion import bucket_crud, bucket_models, bucket_schemas from easydiffusion.bucket_database import SessionLocal, engine +from requests.compat import urlparse + +import base64, json + +MIME_TYPES = { + "jpg": "image/jpeg", + "jpeg": "image/jpeg", + "gif": "image/gif", + "png": "image/png", + "webp": "image/webp", + "js": "text/javascript", + "htm": "text/html", + "html": "text/html", + "css": "text/css", + "json": "application/json", + "mjs": "application/json", + "yaml": "application/yaml", + "svg": "image/svg+xml", + "txt": "text/plain", +} def init(): from easydiffusion.server import server_api @@ -21,6 +41,42 @@ def init(): finally: db.close() + @server_api.get("/bucket/{obj_path:path}") + def bucket_get_object(obj_path: str, db: Session = Depends(get_db)): + filename = get_filename_from_url(obj_path) + path = get_path_from_url(obj_path) + + if filename==None: + bucket = bucket_crud.get_bucket_by_path(db, path=path) + if bucket == None: + raise HTTPException(status_code=404, detail="Bucket not found") + bucketfiles = db.query(bucket_models.BucketFile).with_entities(bucket_models.BucketFile.filename).filter(bucket_models.BucketFile.bucket_id == bucket.id).all() + bucketfiles = [ x.filename for x in bucketfiles ] + return bucketfiles + + else: + bucket_id = bucket_crud.get_bucket_by_path(db, path).id + bucketfile = db.query(bucket_models.BucketFile).filter(bucket_models.BucketFile.bucket_id == bucket_id, bucket_models.BucketFile.filename == filename).first() + + suffix = get_suffix_from_filename(filename) + + return Response(content=bucketfile.data, media_type=MIME_TYPES.get(suffix, "application/octet-stream")) + + @server_api.post("/bucket/{obj_path:path}") + def bucket_post_object(obj_path: str, file: bytes = File(), db: Session = Depends(get_db)): + filename = get_filename_from_url(obj_path) + path = get_path_from_url(obj_path) + bucket = bucket_crud.get_bucket_by_path(db, path) + + if bucket == None: + bucket_id = bucket_crud.create_bucket(db=db, bucket=bucket_schemas.BucketCreate(path=path)) + else: + bucket_id = bucket.id + + bucketfile = bucket_schemas.BucketFileCreate(filename=filename, data=file) + result = bucket_crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) + result.data = base64.encodestring(result.data) + return result @server_api.post("/buckets/", response_model=bucket_schemas.Bucket) def create_bucket(bucket: bucket_schemas.BucketCreate, db: Session = Depends(get_db)): @@ -47,7 +103,10 @@ def init(): def create_bucketfile_in_bucket( bucket_id: int, bucketfile: bucket_schemas.BucketFileCreate, db: Session = Depends(get_db) ): - return bucket_crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) + bucketfile.data = base64.decodestring(bucketfile.data) + result = bucket_crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) + result.data = base64.encodestring(result.data) + return result @server_api.get("/bucketfiles/", response_model=List[bucket_schemas.BucketFile]) @@ -55,3 +114,16 @@ def init(): bucketfiles = bucket_crud.get_bucketfiles(db, skip=skip, limit=limit) return bucketfiles + +def get_filename_from_url(url): + path = urlparse(url).path + name = path[path.rfind('/')+1:] + return name or None + +def get_path_from_url(url): + path = urlparse(url).path + path = path[0:path.rfind('/')] + return path or None + +def get_suffix_from_filename(filename): + return filename[filename.rfind('.')+1:] diff --git a/ui/easydiffusion/bucket_models.py b/ui/easydiffusion/bucket_models.py index 3ede1a36..933f8140 100644 --- a/ui/easydiffusion/bucket_models.py +++ b/ui/easydiffusion/bucket_models.py @@ -16,10 +16,10 @@ class Bucket(BucketBase): class BucketFile(BucketBase): __tablename__ = "bucketfile" - id = Column(Integer, primary_key=True, index=True) - filename = Column(String, index=True) + filename = Column(String, index=True, primary_key=True) + bucket_id = Column(Integer, ForeignKey("bucket.id"), primary_key=True) + data = Column(BLOB, index=False) - bucket_id = Column(Integer, ForeignKey("bucket.id")) bucket = relationship("Bucket", back_populates="bucketfiles") diff --git a/ui/easydiffusion/bucket_schemas.py b/ui/easydiffusion/bucket_schemas.py index 9f7e2377..68bc04e2 100644 --- a/ui/easydiffusion/bucket_schemas.py +++ b/ui/easydiffusion/bucket_schemas.py @@ -13,7 +13,6 @@ class BucketFileCreate(BucketFileBase): class BucketFile(BucketFileBase): - id: int bucket_id: int class Config: From 5f736368c8ce2d685a2ed94201adb9f0e54ad752 Mon Sep 17 00:00:00 2001 From: JeLuF Date: Thu, 27 Jul 2023 22:44:30 +0200 Subject: [PATCH 2/4] Move easydb files to its own folders --- ui/easydiffusion/bucket_crud.py | 37 ------------- ui/easydiffusion/bucket_manager.py | 54 +++++-------------- ui/easydiffusion/easydb/crud.py | 25 +++++++++ .../database.py} | 0 .../{bucket_models.py => easydb/models.py} | 2 +- .../{bucket_schemas.py => easydb/schemas.py} | 0 6 files changed, 40 insertions(+), 78 deletions(-) delete mode 100644 ui/easydiffusion/bucket_crud.py create mode 100644 ui/easydiffusion/easydb/crud.py rename ui/easydiffusion/{bucket_database.py => easydb/database.py} (100%) rename ui/easydiffusion/{bucket_models.py => easydb/models.py} (92%) rename ui/easydiffusion/{bucket_schemas.py => easydb/schemas.py} (100%) diff --git a/ui/easydiffusion/bucket_crud.py b/ui/easydiffusion/bucket_crud.py deleted file mode 100644 index 5dada176..00000000 --- a/ui/easydiffusion/bucket_crud.py +++ /dev/null @@ -1,37 +0,0 @@ -from sqlalchemy.orm import Session - -from easydiffusion import bucket_models, bucket_schemas - - -def get_bucket(db: Session, bucket_id: int): - return db.query(bucket_models.Bucket).filter(bucket_models.Bucket.id == bucket_id).first() - - -def get_bucket_by_path(db: Session, path: str): - return db.query(bucket_models.Bucket).filter(bucket_models.Bucket.path == path).first() - - -def get_buckets(db: Session, skip: int = 0, limit: int = 100): - return db.query(bucket_models.Bucket).offset(skip).limit(limit).all() - - -def create_bucket(db: Session, bucket: bucket_schemas.BucketCreate): - db_bucket = bucket_models.Bucket(path=bucket.path) - db.add(db_bucket) - db.commit() - db.refresh(db_bucket) - return db_bucket - - -def get_bucketfiles(db: Session, skip: int = 0, limit: int = 100): - return db.query(bucket_models.BucketFile).offset(skip).limit(limit).all() - - -def create_bucketfile(db: Session, bucketfile: bucket_schemas.BucketFileCreate, bucket_id: int): - db_bucketfile = bucket_models.BucketFile(**bucketfile.dict(), bucket_id=bucket_id) - db.merge(db_bucketfile) - db.commit() - from pprint import pprint - db_bucketfile = db.query(bucket_models.BucketFile).filter(bucket_models.BucketFile.bucket_id==bucket_id, bucket_models.BucketFile.filename==bucketfile.filename).first() - return db_bucketfile - diff --git a/ui/easydiffusion/bucket_manager.py b/ui/easydiffusion/bucket_manager.py index 58d0e30c..f587bc7f 100644 --- a/ui/easydiffusion/bucket_manager.py +++ b/ui/easydiffusion/bucket_manager.py @@ -3,8 +3,8 @@ from typing import List from fastapi import Depends, FastAPI, HTTPException, Response, File from sqlalchemy.orm import Session -from easydiffusion import bucket_crud, bucket_models, bucket_schemas -from easydiffusion.bucket_database import SessionLocal, engine +from easydiffusion.easydb import crud, models, schemas +from easydiffusion.easydb.database import SessionLocal, engine from requests.compat import urlparse @@ -30,7 +30,7 @@ MIME_TYPES = { def init(): from easydiffusion.server import server_api - bucket_models.BucketBase.metadata.create_all(bind=engine) + models.BucketBase.metadata.create_all(bind=engine) # Dependency @@ -47,16 +47,16 @@ def init(): path = get_path_from_url(obj_path) if filename==None: - bucket = bucket_crud.get_bucket_by_path(db, path=path) + bucket = crud.get_bucket_by_path(db, path=path) if bucket == None: raise HTTPException(status_code=404, detail="Bucket not found") - bucketfiles = db.query(bucket_models.BucketFile).with_entities(bucket_models.BucketFile.filename).filter(bucket_models.BucketFile.bucket_id == bucket.id).all() + bucketfiles = db.query(models.BucketFile).with_entities(models.BucketFile.filename).filter(models.BucketFile.bucket_id == bucket.id).all() bucketfiles = [ x.filename for x in bucketfiles ] return bucketfiles else: - bucket_id = bucket_crud.get_bucket_by_path(db, path).id - bucketfile = db.query(bucket_models.BucketFile).filter(bucket_models.BucketFile.bucket_id == bucket_id, bucket_models.BucketFile.filename == filename).first() + bucket_id = crud.get_bucket_by_path(db, path).id + bucketfile = db.query(models.BucketFile).filter(models.BucketFile.bucket_id == bucket_id, models.BucketFile.filename == filename).first() suffix = get_suffix_from_filename(filename) @@ -66,55 +66,29 @@ def init(): def bucket_post_object(obj_path: str, file: bytes = File(), db: Session = Depends(get_db)): filename = get_filename_from_url(obj_path) path = get_path_from_url(obj_path) - bucket = bucket_crud.get_bucket_by_path(db, path) + bucket = crud.get_bucket_by_path(db, path) if bucket == None: - bucket_id = bucket_crud.create_bucket(db=db, bucket=bucket_schemas.BucketCreate(path=path)) + bucket_id = crud.create_bucket(db=db, bucket=schemas.BucketCreate(path=path)) else: bucket_id = bucket.id - bucketfile = bucket_schemas.BucketFileCreate(filename=filename, data=file) - result = bucket_crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) + bucketfile = schemas.BucketFileCreate(filename=filename, data=file) + result = crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) result.data = base64.encodestring(result.data) return result - @server_api.post("/buckets/", response_model=bucket_schemas.Bucket) - def create_bucket(bucket: bucket_schemas.BucketCreate, db: Session = Depends(get_db)): - db_bucket = bucket_crud.get_bucket_by_path(db, path=bucket.path) - if db_bucket: - raise HTTPException(status_code=400, detail="Bucket already exists") - return bucket_crud.create_bucket(db=db, bucket=bucket) - @server_api.get("/buckets/", response_model=List[bucket_schemas.Bucket]) - def read_bucket(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): - buckets = bucket_crud.get_buckets(db, skip=skip, limit=limit) - return buckets - - - @server_api.get("/buckets/{bucket_id}", response_model=bucket_schemas.Bucket) - def read_bucket(bucket_id: int, db: Session = Depends(get_db)): - db_bucket = bucket_crud.get_bucket(db, bucket_id=bucket_id) - if db_bucket is None: - raise HTTPException(status_code=404, detail="Bucket not found") - return db_bucket - - - @server_api.post("/buckets/{bucket_id}/items/", response_model=bucket_schemas.BucketFile) + @server_api.post("/buckets/{bucket_id}/items/", response_model=schemas.BucketFile) def create_bucketfile_in_bucket( - bucket_id: int, bucketfile: bucket_schemas.BucketFileCreate, db: Session = Depends(get_db) + bucket_id: int, bucketfile: schemas.BucketFileCreate, db: Session = Depends(get_db) ): bucketfile.data = base64.decodestring(bucketfile.data) - result = bucket_crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) + result = crud.create_bucketfile(db=db, bucketfile=bucketfile, bucket_id=bucket_id) result.data = base64.encodestring(result.data) return result - @server_api.get("/bucketfiles/", response_model=List[bucket_schemas.BucketFile]) - def read_bucketfiles(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): - bucketfiles = bucket_crud.get_bucketfiles(db, skip=skip, limit=limit) - return bucketfiles - - def get_filename_from_url(url): path = urlparse(url).path name = path[path.rfind('/')+1:] diff --git a/ui/easydiffusion/easydb/crud.py b/ui/easydiffusion/easydb/crud.py new file mode 100644 index 00000000..7550a52a --- /dev/null +++ b/ui/easydiffusion/easydb/crud.py @@ -0,0 +1,25 @@ +from sqlalchemy.orm import Session + +from easydiffusion.easydb import models, schemas + + +def get_bucket_by_path(db: Session, path: str): + return db.query(models.Bucket).filter(models.Bucket.path == path).first() + + +def create_bucket(db: Session, bucket: schemas.BucketCreate): + db_bucket = models.Bucket(path=bucket.path) + db.add(db_bucket) + db.commit() + db.refresh(db_bucket) + return db_bucket + + +def create_bucketfile(db: Session, bucketfile: schemas.BucketFileCreate, bucket_id: int): + db_bucketfile = models.BucketFile(**bucketfile.dict(), bucket_id=bucket_id) + db.merge(db_bucketfile) + db.commit() + from pprint import pprint + db_bucketfile = db.query(models.BucketFile).filter(models.BucketFile.bucket_id==bucket_id, models.BucketFile.filename==bucketfile.filename).first() + return db_bucketfile + diff --git a/ui/easydiffusion/bucket_database.py b/ui/easydiffusion/easydb/database.py similarity index 100% rename from ui/easydiffusion/bucket_database.py rename to ui/easydiffusion/easydb/database.py diff --git a/ui/easydiffusion/bucket_models.py b/ui/easydiffusion/easydb/models.py similarity index 92% rename from ui/easydiffusion/bucket_models.py rename to ui/easydiffusion/easydb/models.py index 933f8140..04834951 100644 --- a/ui/easydiffusion/bucket_models.py +++ b/ui/easydiffusion/easydb/models.py @@ -1,7 +1,7 @@ from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, BLOB from sqlalchemy.orm import relationship -from easydiffusion.bucket_database import BucketBase +from easydiffusion.easydb.database import BucketBase class Bucket(BucketBase): diff --git a/ui/easydiffusion/bucket_schemas.py b/ui/easydiffusion/easydb/schemas.py similarity index 100% rename from ui/easydiffusion/bucket_schemas.py rename to ui/easydiffusion/easydb/schemas.py From ab37dbf98f0b176751ba66a866e23ae5a45594ef Mon Sep 17 00:00:00 2001 From: JeLuF Date: Sun, 30 Jul 2023 12:59:40 +0200 Subject: [PATCH 3/4] show images --- ui/media/images/noimg.png | Bin 0 -> 1338 bytes ui/media/js/main.js | 53 ++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 ui/media/images/noimg.png diff --git a/ui/media/images/noimg.png b/ui/media/images/noimg.png new file mode 100644 index 0000000000000000000000000000000000000000..33d7332fcbf24582eed6cdb2248bd4ee09c5ec80 GIT binary patch literal 1338 zcma)+c~}y57{`BT2AZI=W2I>xROVdz7`k#MN?zzB&$M(3J}MrC+M^Dd2W#Ht+491L z6^5G2N0$1Z>WcB3it9q2~GhpD+ zbZpUmt$`%zbws?^8aJvh7!KOzUQW)huZVb_7TRYOh;3h2iYbl0ikvz6;i7}a!|odK zRS-SMKVsVeFjcFmCl~-O>Q1e#{~xPm?ogvDa=ogyYdg!3PX;I!Rs63E;l2oJ)Wi|{1DRNF+EDDbUurnehGfal z7Ub!ilY_^o(g$++gTd&r8O+m^7X!+*oz6KSAr^u_funIQaweT)jNl>lW)y77n2U4Q z#A3Qn|CswKhPGOQYH4X%&v1Szv9Jq!ipW2;iLE!G7RM+hEusZQYoxuC%*MusNF*}v zFipIy_rQV5BF{$L6D_badV~qSNNP!?X^GS>V1UGupf|Yp^xzDhbV58?J5HpQ0I~b+ z{k)S|T#V)Fj@6muy+C^5ahpq7FFHE*DT%cMNQ((Kx;z>BMTHI!d{>&Is867=xR400 zvIK&_2Bt1cmOeZ@3~a^T4NL9T=qxn0O!ykh4&VNWoY-+rZGrL!QW@Je7HE~9&*5;M z7c}|*az?4-S0x{Rv!*z2{RRJGLqL--VMOIx86%RW{&;-AfDuuFWKX|UZvHBa9rCKVY2*m59(2_=FHhb=;Ch#AdQMPh zB*a67c-w042DP`i+F?@C6!A?d+HGIc{A8_UN%PTOA7o#Df4?e>xj7LUW?o(&ZwRF4 zHnd!A{kUIeF?$teG_6OWm8xn}r!5N)WZV5Nr263_vSo7=)j|4syBdRA^DAVqoKW~O zPaw-kkR5o4#TDEl<^SNHL|lucqrdMKN3@0$5dV(7)23O1^@z0hdktqS}7wc$JkSUSf{Pd|P?ScMV%9PP`ZvOYWeX z3R$M{y^Rw2UNv6G{lz^-@v;Msx^+0FB?;i~^Sy7(eV3kYT^T|?3yooHbA{z%!1~Ca znGb3{j@KljdM1U2y|&u^<0H1Cd-3??=A9#}gV6?{7uu?GB&U5BOgCKG!!E8K>_fWw z->tgp?~!2N-fa2%loo7#^EF+mDGEtS)PBh6Ha-rOcOHH%zjRGEIW5h-+3A9(Z1zL! zd}*#P!bScUL$El%r(T#4Y;_&G-Ex->j~ATjtnK(St|@eE_M*#BWbkMlYIb%u_73rV z$NGyG8OlyBmy1?_Y0}#Ae8HV~&a|qCHie$}3`HC2?(U9iYZRK5)qbSEL-|5AAXWUB zvA5!ApUTtC!T|-lbB^i&ygp}{s~G}-lbSC72Pgpi8-_fV4p)oNFTLMT=06?8y5rpL IVeps#2IeDOrvLx| literal 0 HcmV?d00001 diff --git a/ui/media/js/main.js b/ui/media/js/main.js index 0b936066..4b2b5dfd 100644 --- a/ui/media/js/main.js +++ b/ui/media/js/main.js @@ -508,6 +508,7 @@ function showImages(reqBody, res, outputContainer, livePreview) { { text: "Upscale", on_click: onUpscaleClick, filter: (req, img) => !req.use_upscale }, { text: "Fix Faces", on_click: onFixFacesClick, filter: (req, img) => !req.use_face_correction }, ], + { text: "Use as Thumbnail", on_click: onUseAsThumbnailClick }, ] // include the plugins @@ -632,6 +633,20 @@ function onMakeSimilarClick(req, img) { createTask(newTaskRequest) } +function onUseAsThumbnailClick(req, img) { + console.log(req) + console.log(img) + let embedding = prompt("Embedding name") + fetch(img.src) + .then(response => response.blob()) + .then(async function(blob) { + const formData = new FormData() + formData.append("file", blob) + const response = await fetch(`bucket/embeddings/${embedding}.jpg`, { method: 'POST', body: formData }); + console.log(response) + }) +} + function enqueueImageVariationTask(req, img, reqDiff) { const imageSeed = img.getAttribute("data-seed") @@ -2157,19 +2172,27 @@ document.getElementById("toggle-cloudflare-tunnel").addEventListener("click", as /* Embeddings */ +let icl = [] function updateEmbeddingsList(filter = "") { - function html(model, prefix = "", filter = "") { + function html(model, iconlist = [], prefix = "", filter = "") { filter = filter.toLowerCase() let toplevel = "" let folders = "" + console.log(iconlist) + let embIcon = Object.assign({}, ...iconlist.map( x=> ({[x.toLowerCase().split('.').slice(0,-1).join('.')]:x}))) model?.forEach((m) => { if (typeof m == "string") { - if (m.toLowerCase().search(filter) != -1) { - toplevel += ` ` + let token=m.toLowerCase() + if (token.search(filter) != -1) { + let img = '/media/images/noimg.png' + if (token in embIcon) { + img = `/bucket/embeddings/${embIcon[token]}` + } + toplevel += ` ` } } else { - let subdir = html(m[1], prefix + m[0] + "/", filter) + let subdir = html(m[1], iconlist, prefix + m[0] + "/", filter) if (subdir != "") { folders += `

${prefix}${m[0]}

` + subdir + '
' } @@ -2179,7 +2202,7 @@ function updateEmbeddingsList(filter = "") { } function onButtonClick(e) { - let text = e.target.dataset["embedding"] + let text = e.target.closest("button").dataset["embedding"] const insertIntoNegative = e.shiftKey || positiveEmbeddingText.classList.contains("displayNone") if (embeddingsModeField.value == "insert") { @@ -2214,14 +2237,18 @@ function updateEmbeddingsList(filter = "") { } // END of remove block - embeddingsList.innerHTML = warning + html(modelsOptions.embeddings, "", filter) - embeddingsList.querySelectorAll("button").forEach((b) => { - b.addEventListener("click", onButtonClick) - }) - createCollapsibles(embeddingsList) - if (filter != "") { - embeddingsExpandAll() - } + fetch("/bucket/embeddings/") + .then(response => response.json()) + .then(iconlist => { + embeddingsList.innerHTML = warning + html(modelsOptions.embeddings, iconlist, "", filter) + embeddingsList.querySelectorAll("button").forEach((b) => { + b.addEventListener("click", onButtonClick) + }) + createCollapsibles(embeddingsList) + if (filter != "") { + embeddingsExpandAll() + } + }) } function showEmbeddingDialog() { From a70a795662c8aa9a9f7de4439fa3dfcfc48fcb4a Mon Sep 17 00:00:00 2001 From: JeLuF Date: Mon, 31 Jul 2023 23:35:49 +0200 Subject: [PATCH 4/4] add croppr --- 3rd-PARTY-LICENSES | 28 ++++++++++++++++++++++++++++ ui/index.html | 31 +++++++++++++++++++++++++++++++ ui/media/css/croppr.css | 1 + ui/media/css/main.css | 26 ++++++++++++++++++++++++++ ui/media/js/croppr.js | 1 + ui/media/js/main.js | 35 ++++++++++++++++++++++++----------- 6 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 ui/media/css/croppr.css create mode 100755 ui/media/js/croppr.js diff --git a/3rd-PARTY-LICENSES b/3rd-PARTY-LICENSES index bd29393a..78bfe3bb 100644 --- a/3rd-PARTY-LICENSES +++ b/3rd-PARTY-LICENSES @@ -712,3 +712,31 @@ FileSaver.js is licensed under the MIT license: SOFTWARE. [1]: http://eligrey.com + +croppr.js +========= +https://github.com/jamesssooi/Croppr.js + +croppr.js is licensed under the MIT license: + + MIT License + + Copyright (c) 2017 James Ooi + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. diff --git a/ui/index.html b/ui/index.html index 0fcb807d..de4273aa 100644 --- a/ui/index.html +++ b/ui/index.html @@ -18,12 +18,14 @@ + +
@@ -630,6 +632,35 @@
+ +
+
+

Use as thumbnail

+ Use a pictures as thumbnail for embeddings, LORAs, etc. +
+
+ +
+
+
+
+
+ +
+
+

Use the thumbnail for …

+ +
+
+ + +
+
+
+
+