add /admin page with pic count and folder sizes
This commit is contained in:
29
Slideshow.py
29
Slideshow.py
@@ -8,7 +8,7 @@ import uuid
|
|||||||
from flask import Flask, render_template, request, redirect, url_for, Response, send_from_directory
|
from flask import Flask, render_template, request, redirect, url_for, Response, send_from_directory
|
||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
|
||||||
from db import init_db, search_images
|
from db import init_db, search_images, get_image_count
|
||||||
|
|
||||||
app = Flask(__name__, static_folder='Pictures', static_url_path='/pictures')
|
app = Flask(__name__, static_folder='Pictures', static_url_path='/pictures')
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_prefix=1)
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_prefix=1)
|
||||||
@@ -72,6 +72,33 @@ def slideshow():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/admin')
|
||||||
|
def admin():
|
||||||
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
pictures_dir = os.path.join(base_dir, 'Pictures')
|
||||||
|
previews_dir = os.path.join(base_dir, 'Previews')
|
||||||
|
|
||||||
|
def folder_size(path):
|
||||||
|
total = 0
|
||||||
|
for dirpath, _, filenames in os.walk(path):
|
||||||
|
for f in filenames:
|
||||||
|
fp = os.path.join(dirpath, f)
|
||||||
|
if not os.path.islink(fp):
|
||||||
|
total += os.path.getsize(fp)
|
||||||
|
return total
|
||||||
|
|
||||||
|
def fmt_size(n):
|
||||||
|
if n >= 1_073_741_824:
|
||||||
|
return f'{n / 1_073_741_824:.2f} GB'
|
||||||
|
return f'{n / 1_048_576:.1f} MB'
|
||||||
|
|
||||||
|
return render_template('admin.html',
|
||||||
|
pic_count=get_image_count(),
|
||||||
|
pics_size=fmt_size(folder_size(pictures_dir)),
|
||||||
|
previews_size=fmt_size(folder_size(previews_dir)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/download', methods=['POST'])
|
@app.route('/download', methods=['POST'])
|
||||||
def download():
|
def download():
|
||||||
tags = request.form.get('tags', '').strip()
|
tags = request.form.get('tags', '').strip()
|
||||||
|
|||||||
5
db.py
5
db.py
@@ -54,6 +54,11 @@ def insert_image(post_id, site, filename, tags, file_url, post_url, preview_file
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_count():
|
||||||
|
with get_conn() as c:
|
||||||
|
return c.execute('SELECT COUNT(*) FROM images').fetchone()[0]
|
||||||
|
|
||||||
|
|
||||||
def search_images(tag_query):
|
def search_images(tag_query):
|
||||||
terms = tag_query.split() if tag_query.strip() else []
|
terms = tag_query.split() if tag_query.strip() else []
|
||||||
with get_conn() as c:
|
with get_conn() as c:
|
||||||
|
|||||||
83
templates/admin.html
Normal file
83
templates/admin.html
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>admin</title>
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body {
|
||||||
|
background: #111;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 60px 20px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #888;
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
.stats {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 420px;
|
||||||
|
}
|
||||||
|
.stat-card {
|
||||||
|
background: #1a1a1a;
|
||||||
|
border: 1px solid #2a2a2a;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px 28px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.stat-label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #666;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
}
|
||||||
|
.stat-value {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
a.back {
|
||||||
|
margin-top: 48px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #555;
|
||||||
|
text-decoration: none;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
a.back:hover { color: #999; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>admin</h1>
|
||||||
|
<div class="stats">
|
||||||
|
<div class="stat-card">
|
||||||
|
<span class="stat-label">images in db</span>
|
||||||
|
<span class="stat-value">{{ pic_count }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<span class="stat-label">pictures folder</span>
|
||||||
|
<span class="stat-value">{{ pics_size }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<span class="stat-label">previews folder</span>
|
||||||
|
<span class="stat-value">{{ previews_size }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="back" href="/">← back to slideshow</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user