Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
8bad36271a | |
|
5706377a31 |
147
app.py
|
@ -6,6 +6,7 @@ from werkzeug.security import check_password_hash
|
||||||
from PIL import Image, UnidentifiedImageError
|
from PIL import Image, UnidentifiedImageError
|
||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
from watchdog.events import FileSystemEventHandler
|
from watchdog.events import FileSystemEventHandler
|
||||||
|
from os.path import realpath, join
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@ -16,10 +17,9 @@ with open('db/keys.json', 'r') as f:
|
||||||
app.config['SECRET_KEY'] = config['key']
|
app.config['SECRET_KEY'] = config['key']
|
||||||
socketio = SocketIO(app)
|
socketio = SocketIO(app)
|
||||||
|
|
||||||
app.config['UPLOAD_FOLDER'] = 'images' # Folder to store images
|
app.config['UPLOAD_FOLDER'] = '/home/kenny/workspace/Image_Gen_Server/output/expo_postprocessed' # Folder to store images
|
||||||
app.config['DUMP_FOLDER'] = 'dump_images'
|
app.config['DUMP_FOLDER'] = '/home/kenny/workspace/ComfyUI-halloween/output' # Folder to store dump images
|
||||||
app.config['CACHE_FOLDER'] = 'cache' # Folder to store cached resized images
|
app.config['CACHE_FOLDER'] = 'cache' # Folder to store cached resized images
|
||||||
app.config['DUMP_CACHE_FOLDER'] = 'dump_cache'
|
|
||||||
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'}
|
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'}
|
||||||
|
|
||||||
USERNAME = config['login_info']['username']
|
USERNAME = config['login_info']['username']
|
||||||
|
@ -45,78 +45,24 @@ def resize_image(image_path, cache_path, size=(800, 450)):
|
||||||
img = img.convert("RGB")
|
img = img.convert("RGB")
|
||||||
img.save(cache_path, format="JPEG")
|
img.save(cache_path, format="JPEG")
|
||||||
|
|
||||||
def delete_non_existing_cache():
|
|
||||||
cache_folder = app.config['CACHE_FOLDER']
|
|
||||||
upload_folder = app.config['UPLOAD_FOLDER']
|
|
||||||
dump_cache_folder = app.config['DUMP_CACHE_FOLDER']
|
|
||||||
dump_folder = app.config['DUMP_FOLDER']
|
|
||||||
|
|
||||||
images = os.listdir(cache_folder)
|
|
||||||
for image in images:
|
|
||||||
image_path_upload = os.path.join(upload_folder, image)
|
|
||||||
cache_path = os.path.join(cache_folder, image)
|
|
||||||
|
|
||||||
if not os.path.exists(image_path_upload):
|
|
||||||
if os.path.exists(cache_path):
|
|
||||||
os.remove(cache_path)
|
|
||||||
|
|
||||||
dump_images = os.listdir(dump_cache_folder)
|
|
||||||
for image in dump_images:
|
|
||||||
image_path_dump = os.path.join(dump_folder, image)
|
|
||||||
dump_cache_path = os.path.join(dump_cache_folder, image)
|
|
||||||
|
|
||||||
if not os.path.exists(image_path_dump):
|
|
||||||
if os.path.exists(dump_cache_path):
|
|
||||||
os.remove(dump_cache_path)
|
|
||||||
|
|
||||||
def create_cache():
|
def create_cache():
|
||||||
images = os.listdir(app.config['UPLOAD_FOLDER'])
|
|
||||||
cached_images = []
|
cached_images = []
|
||||||
|
|
||||||
if not os.path.exists(app.config['CACHE_FOLDER']):
|
if not os.path.exists(app.config['CACHE_FOLDER']):
|
||||||
os.makedirs(app.config['CACHE_FOLDER'])
|
os.makedirs(app.config['CACHE_FOLDER'])
|
||||||
|
|
||||||
caches_path = set([os.path.join(app.config['CACHE_FOLDER'], image) for image in os.listdir(app.config['CACHE_FOLDER'])])
|
for image in os.listdir(app.config['UPLOAD_FOLDER']):
|
||||||
images_path = set([os.path.join(app.config['UPLOAD_FOLDER'], image) for image in images])
|
image_path = os.path.join(app.config['UPLOAD_FOLDER'], image)
|
||||||
|
cache_path = os.path.join(app.config['CACHE_FOLDER'], image)
|
||||||
|
|
||||||
# get the images that are not cached
|
if not os.path.exists(cache_path) and is_image_valid(image_path):
|
||||||
uncached_images = images_path - caches_path
|
|
||||||
for image_path in uncached_images:
|
|
||||||
if is_image_valid(image_path):
|
|
||||||
cache_path = os.path.join(app.config['CACHE_FOLDER'], os.path.basename(image_path))
|
|
||||||
resize_image(image_path, cache_path)
|
resize_image(image_path, cache_path)
|
||||||
cached_images.append(os.path.basename(image_path))
|
|
||||||
|
if is_image_valid(image_path):
|
||||||
|
cached_images.append(image)
|
||||||
|
|
||||||
return cached_images
|
return cached_images
|
||||||
|
|
||||||
def create_dump_cache():
|
|
||||||
images = os.listdir(app.config['DUMP_FOLDER'])
|
|
||||||
cached_images = []
|
|
||||||
|
|
||||||
if not os.path.exists(app.config['DUMP_CACHE_FOLDER']):
|
|
||||||
os.makedirs(app.config['DUMP_CACHE_FOLDER'])
|
|
||||||
|
|
||||||
caches_path = set([os.path.join(app.config['DUMP_CACHE_FOLDER'], image) for image in os.listdir(app.config['DUMP_CACHE_FOLDER'])])
|
|
||||||
images_path = set([os.path.join(app.config['DUMP_FOLDER'], image) for image in images])
|
|
||||||
|
|
||||||
# get the images that are not cached
|
|
||||||
uncached_images = images_path - caches_path
|
|
||||||
for image_path in uncached_images:
|
|
||||||
if is_image_valid(image_path):
|
|
||||||
cache_path = os.path.join(app.config['DUMP_CACHE_FOLDER'], os.path.basename(image_path))
|
|
||||||
resize_image(image_path, cache_path)
|
|
||||||
cached_images.append(os.path.basename(image_path))
|
|
||||||
|
|
||||||
return cached_images
|
|
||||||
|
|
||||||
def update_cache():
|
|
||||||
create_cache()
|
|
||||||
delete_non_existing_cache()
|
|
||||||
|
|
||||||
def update_dump_cache():
|
|
||||||
create_dump_cache()
|
|
||||||
delete_non_existing_cache()
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
@ -145,7 +91,6 @@ def gallery():
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
cached_images = create_cache()
|
cached_images = create_cache()
|
||||||
cached_images.sort()
|
|
||||||
batches = []
|
batches = []
|
||||||
current_batch = []
|
current_batch = []
|
||||||
current_batch_number = None
|
current_batch_number = None
|
||||||
|
@ -167,9 +112,6 @@ def gallery():
|
||||||
|
|
||||||
if current_batch:
|
if current_batch:
|
||||||
batches.append(current_batch)
|
batches.append(current_batch)
|
||||||
|
|
||||||
batches = batches[::-1]
|
|
||||||
|
|
||||||
if unstructured_images:
|
if unstructured_images:
|
||||||
batches.append(unstructured_images)
|
batches.append(unstructured_images)
|
||||||
|
|
||||||
|
@ -185,17 +127,6 @@ def uploaded_file(filename):
|
||||||
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
|
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
|
||||||
else:
|
else:
|
||||||
return "Invalid image", 404
|
return "Invalid image", 404
|
||||||
|
|
||||||
@app.route('/dump_images/<filename>')
|
|
||||||
def uploaded_dump_file(filename):
|
|
||||||
if not session.get('logged_in'):
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
image_path = os.path.join(app.config['DUMP_FOLDER'], filename)
|
|
||||||
if is_image_valid(image_path):
|
|
||||||
return send_from_directory(app.config['DUMP_FOLDER'], filename)
|
|
||||||
else:
|
|
||||||
return "Invalid image", 404
|
|
||||||
|
|
||||||
@app.route('/cached/<filename>')
|
@app.route('/cached/<filename>')
|
||||||
def cached_file(filename):
|
def cached_file(filename):
|
||||||
|
@ -208,14 +139,14 @@ def cached_file(filename):
|
||||||
else:
|
else:
|
||||||
return "Invalid image", 404
|
return "Invalid image", 404
|
||||||
|
|
||||||
@app.route('/dump_cached/<filename>')
|
@app.route('/dump/<filename>')
|
||||||
def dump_cached_file(filename):
|
def dump_file(filename):
|
||||||
if not session.get('logged_in'):
|
if not session.get('logged_in'):
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
image_path = os.path.join(app.config['DUMP_CACHE_FOLDER'], filename)
|
image_path = os.path.join(app.config['DUMP_FOLDER'], filename)
|
||||||
if is_image_valid(image_path):
|
if is_image_valid(image_path):
|
||||||
return send_from_directory(app.config['DUMP_CACHE_FOLDER'], filename)
|
return send_from_directory(app.config['DUMP_FOLDER'], filename)
|
||||||
else:
|
else:
|
||||||
return "Invalid image", 404
|
return "Invalid image", 404
|
||||||
|
|
||||||
|
@ -224,8 +155,11 @@ def api_images():
|
||||||
if not session.get('logged_in'):
|
if not session.get('logged_in'):
|
||||||
return jsonify([])
|
return jsonify([])
|
||||||
|
|
||||||
images = sorted(os.listdir(app.config['UPLOAD_FOLDER']), reverse=True)
|
images = sorted(
|
||||||
|
os.listdir(app.config['UPLOAD_FOLDER']),
|
||||||
|
key=lambda x: os.path.getctime(os.path.join(app.config['UPLOAD_FOLDER'], x)),
|
||||||
|
reverse=True
|
||||||
|
)
|
||||||
valid_images = [img for img in images if is_image_valid(os.path.join(app.config['UPLOAD_FOLDER'], img))]
|
valid_images = [img for img in images if is_image_valid(os.path.join(app.config['UPLOAD_FOLDER'], img))]
|
||||||
return jsonify(valid_images)
|
return jsonify(valid_images)
|
||||||
|
|
||||||
|
@ -234,55 +168,48 @@ def dump():
|
||||||
if not session.get('logged_in'):
|
if not session.get('logged_in'):
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
cached_images = create_dump_cache()
|
#cached_images = create_cache()
|
||||||
cached_images.sort(reverse=True)
|
dump_folder = app.config['DUMP_FOLDER'] # Folder to store dump images
|
||||||
|
images = sorted(
|
||||||
valid_images = [img for img in cached_images if is_image_valid(os.path.join(app.config['DUMP_FOLDER'], img))]
|
os.listdir(dump_folder),
|
||||||
|
key=lambda x: os.path.getctime(os.path.join(dump_folder, x)),
|
||||||
|
reverse=True
|
||||||
|
)
|
||||||
|
valid_images = [img for img in images if is_image_valid(os.path.join(dump_folder, img))]
|
||||||
|
print(valid_images)
|
||||||
return render_template('dump.html', images=valid_images)
|
return render_template('dump.html', images=valid_images)
|
||||||
|
|
||||||
def emit_gallery_update():
|
def emit_gallery_update():
|
||||||
socketio.emit('update_gallery')
|
socketio.emit('update_gallery')
|
||||||
|
|
||||||
def emit_dump_update():
|
|
||||||
socketio.emit('update_dump')
|
|
||||||
|
|
||||||
class Watcher(FileSystemEventHandler):
|
class Watcher(FileSystemEventHandler):
|
||||||
def on_created(self, event):
|
def on_modified(self, event):
|
||||||
if not event.is_directory and event.src_path.startswith(app.config['UPLOAD_FOLDER']):
|
if not event.is_directory and event.src_path.startswith(app.config['UPLOAD_FOLDER']):
|
||||||
print(f"File created: {event.src_path}")
|
create_cache()
|
||||||
update_cache()
|
|
||||||
emit_gallery_update()
|
emit_gallery_update()
|
||||||
|
|
||||||
if not event.is_directory and event.src_path.startswith(app.config['DUMP_FOLDER']):
|
def on_created(self, event):
|
||||||
print(f"Dump file created: {event.src_path}")
|
if not event.is_directory and event.src_path.startswith(app.config['UPLOAD_FOLDER']):
|
||||||
update_dump_cache()
|
create_cache()
|
||||||
emit_dump_update()
|
emit_gallery_update()
|
||||||
|
|
||||||
def on_deleted(self, event):
|
def on_deleted(self, event):
|
||||||
if not event.is_directory and event.src_path.startswith(app.config['UPLOAD_FOLDER']):
|
if not event.is_directory and event.src_path.startswith(app.config['UPLOAD_FOLDER']):
|
||||||
print(f"File deleted: {event.src_path}")
|
create_cache()
|
||||||
update_cache()
|
|
||||||
emit_gallery_update()
|
emit_gallery_update()
|
||||||
|
|
||||||
if not event.is_directory and event.src_path.startswith(app.config['DUMP_FOLDER']):
|
|
||||||
print(f"Dump file deleted: {event.src_path}")
|
|
||||||
update_dump_cache()
|
|
||||||
emit_dump_update()
|
|
||||||
|
|
||||||
@socketio.on('connect')
|
@socketio.on('connect')
|
||||||
def handle_connect():
|
def handle_connect():
|
||||||
if not session.get('logged_in'):
|
if not session.get('logged_in'):
|
||||||
disconnect()
|
disconnect()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
event_handler = Watcher()
|
|
||||||
observer = Observer()
|
observer = Observer()
|
||||||
observer.schedule(event_handler, path=app.config['UPLOAD_FOLDER'], recursive=False)
|
observer.schedule(Watcher(), path=app.config['UPLOAD_FOLDER'], recursive=False)
|
||||||
observer.schedule(event_handler, path=app.config['DUMP_FOLDER'], recursive=False)
|
|
||||||
observer.start()
|
observer.start()
|
||||||
try:
|
try:
|
||||||
context = ('cert.pem', 'key.pem') # Replace with your self-signed certificate and key files
|
context = ('cert.pem', 'key.pem') # Replace with your self-signed certificate and key files
|
||||||
socketio.run(app, debug=True, ssl_context=context)
|
socketio.run(app, debug=True, ssl_context=context)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
observer.stop()
|
observer.stop()
|
||||||
observer.join()
|
observer.join()
|
||||||
|
|
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 4.7 MiB |
Before Width: | Height: | Size: 6.6 MiB |
Before Width: | Height: | Size: 4.7 MiB |
Before Width: | Height: | Size: 6.1 MiB |
Before Width: | Height: | Size: 6.3 MiB |
Before Width: | Height: | Size: 6.6 MiB |
Before Width: | Height: | Size: 6.4 MiB |
Before Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 4.7 MiB |
After Width: | Height: | Size: 15 MiB |
After Width: | Height: | Size: 2.8 MiB |
After Width: | Height: | Size: 322 KiB |
After Width: | Height: | Size: 12 MiB |
|
@ -1,4 +0,0 @@
|
||||||
Flask
|
|
||||||
requests
|
|
||||||
Pillow
|
|
||||||
duckduckgo_search
|
|
|
@ -16,7 +16,6 @@ form h1 {
|
||||||
}
|
}
|
||||||
form {
|
form {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
margin: 20px;
|
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
|
|
@ -1,24 +1,9 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Pumpkin Gallery🎃</title>
|
<title>Pumpkin Gallery🎃</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='gallery_styles.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='gallery_styles.css') }}">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script>
|
|
||||||
<style>
|
|
||||||
.gallery-container {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gallery-container img {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
|
@ -26,41 +11,22 @@
|
||||||
<a href="{{ url_for('dump') }}" class="button">🎃🎃🎃</a>
|
<a href="{{ url_for('dump') }}" class="button">🎃🎃🎃</a>
|
||||||
</div>
|
</div>
|
||||||
<h1>Pumpkin Gallery🎃</h1>
|
<h1>Pumpkin Gallery🎃</h1>
|
||||||
<div class="gallery-container">
|
<div class="gallery-container" style="flex-direction: row; flex-wrap: wrap;">
|
||||||
{% for image in images %}
|
{% for image in images %}
|
||||||
<a href="#" data-original="{{ url_for('uploaded_dump_file', filename=image) }}" target="_blank">
|
<a href="{{ url_for('dump_file', filename=image) }}" data-original="{{ url_for('dump_file', filename=image) }}" target="_blank" style="flex: 1 0 25%;">
|
||||||
<img class="responsive-img" src="{{ url_for('dump_cached_file', filename=image) }}" alt="{{ image }}">
|
<img class="responsive-img loaded" src="{{ url_for('dump_file', filename=image) }}" alt="{{ image }}" style="max-width:33vw;">
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
|
const images = document.querySelectorAll('.gallery-container a');
|
||||||
|
images.forEach(image => {
|
||||||
socket.on('update_dump', function() {
|
image.addEventListener('click', (event) => {
|
||||||
location.reload();
|
event.preventDefault();
|
||||||
});
|
const original = image.getAttribute('data-original');
|
||||||
|
window.open(original, '_blank');
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
});
|
||||||
var images = document.querySelectorAll('.responsive-img');
|
});
|
||||||
images.forEach(function(img) {
|
|
||||||
img.addEventListener('load', function() {
|
|
||||||
img.classList.add('loaded');
|
|
||||||
});
|
|
||||||
if (img.complete) {
|
|
||||||
img.classList.add('loaded');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var links = document.querySelectorAll('.gallery-container a');
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var originalUrl = link.getAttribute('data-original');
|
|
||||||
window.open(originalUrl, '_blank');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Fencing Gallery🤺</title>
|
<title>Fencing Gallery🤺</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='gallery_styles.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='gallery_styles.css') }}">
|
||||||
|
@ -36,8 +35,111 @@
|
||||||
<script>
|
<script>
|
||||||
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
|
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
|
||||||
|
|
||||||
|
function parseImageName(image) {
|
||||||
|
var parts = image.split('_');
|
||||||
|
if (parts.length === 2) {
|
||||||
|
var batchNumber = parseInt(parts[0], 10);
|
||||||
|
var index = parseInt(parts[1].split('.')[0], 10);
|
||||||
|
return { batchNumber: batchNumber, index: index };
|
||||||
|
}
|
||||||
|
return { batchNumber: 0, index: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeNonExistentImages(existingImages, images) {
|
||||||
|
var galleryContainer = document.getElementById('gallery-container');
|
||||||
|
existingImages.forEach(function(image) {
|
||||||
|
if (!images.includes(image)) {
|
||||||
|
var imgElement = galleryContainer.querySelector(`img[alt="${image}"]`);
|
||||||
|
if (imgElement) {
|
||||||
|
imgElement.parentElement.classList.add('removed');
|
||||||
|
setTimeout(() => {
|
||||||
|
imgElement.parentElement.remove();
|
||||||
|
}, 500); // Match the duration of the fadeOut animation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewImages(existingImages, images) {
|
||||||
|
var galleryContainer = document.getElementById('gallery-container');
|
||||||
|
var currentBatchContainer = null;
|
||||||
|
var currentBatchNumber = null;
|
||||||
|
|
||||||
|
images.forEach(function(image) {
|
||||||
|
if (!existingImages.includes(image)) {
|
||||||
|
var parsedImage = parseImageName(image);
|
||||||
|
var batchNumber = parsedImage.batchNumber;
|
||||||
|
var index = parsedImage.index;
|
||||||
|
|
||||||
|
if (currentBatchNumber !== batchNumber) {
|
||||||
|
currentBatchNumber = batchNumber;
|
||||||
|
currentBatchContainer = document.querySelector(`.batch-${batchNumber}`);
|
||||||
|
if (!currentBatchContainer) {
|
||||||
|
currentBatchContainer = document.createElement('div');
|
||||||
|
currentBatchContainer.className = `batch-container batch-${batchNumber}`;
|
||||||
|
galleryContainer.appendChild(currentBatchContainer);
|
||||||
|
|
||||||
|
if (galleryContainer.children.length > 1) {
|
||||||
|
var divider = document.createElement('hr');
|
||||||
|
galleryContainer.insertBefore(divider, currentBatchContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var anchor = document.createElement('a');
|
||||||
|
anchor.href = '#';
|
||||||
|
anchor.setAttribute('data-original', `/images/${image}`);
|
||||||
|
anchor.target = '_blank';
|
||||||
|
anchor.classList.add('added');
|
||||||
|
|
||||||
|
var img = document.createElement('img');
|
||||||
|
img.className = `responsive-img index-${index}`;
|
||||||
|
img.alt = image;
|
||||||
|
img.src = `/cached/${image}`;
|
||||||
|
|
||||||
|
anchor.appendChild(img);
|
||||||
|
|
||||||
|
// Insert the image in the correct location based on the index
|
||||||
|
var inserted = false;
|
||||||
|
var children = currentBatchContainer.children;
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
var childIndex = parseInt(children[i].querySelector('img').className.split('index-')[1], 10);
|
||||||
|
if (index < childIndex) {
|
||||||
|
currentBatchContainer.insertBefore(anchor, children[i]);
|
||||||
|
inserted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inserted) {
|
||||||
|
currentBatchContainer.appendChild(anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
img.addEventListener('load', function() {
|
||||||
|
img.classList.add('loaded');
|
||||||
|
});
|
||||||
|
if (img.complete) {
|
||||||
|
img.classList.add('loaded');
|
||||||
|
}
|
||||||
|
|
||||||
|
anchor.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var originalUrl = anchor.getAttribute('data-original');
|
||||||
|
window.open(originalUrl, '_blank');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
socket.on('update_gallery', function() {
|
socket.on('update_gallery', function() {
|
||||||
location.reload();
|
fetch('/api/images')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(images => {
|
||||||
|
var galleryContainer = document.getElementById('gallery-container');
|
||||||
|
var existingImages = Array.from(galleryContainer.getElementsByTagName('img')).map(img => img.alt);
|
||||||
|
|
||||||
|
removeNonExistentImages(existingImages, images);
|
||||||
|
addNewImages(existingImages, images);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Login</title>
|
<title>Login</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='login_styles.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='login_styles.css') }}">
|
||||||
|
|