q6 commited on
Commit
e93b2f6
·
1 Parent(s): 89180ab

Allow deleting explorer images

Browse files
Files changed (2) hide show
  1. app.py +15 -0
  2. explorer.js +24 -0
app.py CHANGED
@@ -1928,6 +1928,21 @@ def image_download(body: DownloadRequest):
1928
  )
1929
 
1930
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1931
  def login(p):
1932
  if not valid_pass(p):
1933
  raise gr.Error("Invalid password")
 
1928
  )
1929
 
1930
 
1931
+ @api.post(
1932
+ "/api/images/delete",
1933
+ dependencies=[Depends(require_pass)],
1934
+ )
1935
+ def image_delete(body: DownloadRequest):
1936
+ paths = selected_paths(body.items)
1937
+ for path in paths.values():
1938
+ path.unlink()
1939
+ for value in body.items:
1940
+ path = (IMAGE_DIR / value).resolve()
1941
+ if path.is_dir() and not any(path.iterdir()):
1942
+ path.rmdir()
1943
+ return {"deleted": len(paths)}
1944
+
1945
+
1946
  def login(p):
1947
  if not valid_pass(p):
1948
  raise gr.Error("Invalid password")
explorer.js CHANGED
@@ -20,6 +20,7 @@ class ImageExplorer extends HTMLElement {
20
  <button class="all" type="button">Select all</button>
21
  <button class="clear" type="button">Clear</button>
22
  <button class="download primary" type="button">Download 7z</button>
 
23
  </div>
24
  <div class="status">Loading</div>
25
  <div class="content"></div>
@@ -34,6 +35,7 @@ class ImageExplorer extends HTMLElement {
34
  $(".all", this).addEventListener("click", () => this.select(true))
35
  $(".clear", this).addEventListener("click", () => this.select(false))
36
  $(".download", this).addEventListener("click", () => this.download())
 
37
  $("input[type=search]", this).addEventListener("input", event => {
38
  this.filter(event.target.value)
39
  })
@@ -179,6 +181,28 @@ class ImageExplorer extends HTMLElement {
179
  this.update()
180
  }
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  setupLightbox() {
183
  const dialog = $(".lightbox", this)
184
  const viewer = $(".viewer", dialog)
 
20
  <button class="all" type="button">Select all</button>
21
  <button class="clear" type="button">Clear</button>
22
  <button class="download primary" type="button">Download 7z</button>
23
+ <button class="delete" type="button">Delete</button>
24
  </div>
25
  <div class="status">Loading</div>
26
  <div class="content"></div>
 
35
  $(".all", this).addEventListener("click", () => this.select(true))
36
  $(".clear", this).addEventListener("click", () => this.select(false))
37
  $(".download", this).addEventListener("click", () => this.download())
38
+ $(".delete", this).addEventListener("click", () => this.delete())
39
  $("input[type=search]", this).addEventListener("input", event => {
40
  this.filter(event.target.value)
41
  })
 
181
  this.update()
182
  }
183
 
184
+ async delete() {
185
+ const items = $$(".item:checked", this).map(input => input.dataset.path)
186
+ if (!items.length || !confirm(`Delete ${items.length} selected item(s)?`)) return
187
+ const button = $(".delete", this)
188
+ button.disabled = true
189
+ $(".status", this).textContent = "Deleting"
190
+ try {
191
+ const response = await fetch(api("/api/images/delete"), {
192
+ method: "POST",
193
+ headers: { "Content-Type": "application/json" },
194
+ body: JSON.stringify({ items }),
195
+ })
196
+ if (!response.ok) throw new Error("Delete failed")
197
+ this.cache.clear()
198
+ await this.load(this.folder)
199
+ } catch (error) {
200
+ $(".status", this).textContent = error.message
201
+ } finally {
202
+ button.disabled = false
203
+ }
204
+ }
205
+
206
  setupLightbox() {
207
  const dialog = $(".lightbox", this)
208
  const viewer = $(".viewer", dialog)