Fix image ICC profile getting lost on compression

Fix setup not holding all required modules
Add temporary theme to login and upload page
Other random bug fixes
This commit is contained in:
Michał 2023-01-17 22:13:52 +00:00
parent 4efd9a04ee
commit 0414cda5d3
14 changed files with 509 additions and 243 deletions

View file

@ -5,21 +5,13 @@ print("""
| |_| | | | | | |_| | |__| __/ (_| \\__ \\
\\___/|_| |_|_|\\__, |_____\\___|\\__, |___/
|___/ |___/
Created by Fluffy Bean - Version 140123
Created by Fluffy Bean - Version 170123
""")
# Import base packages
import time
import sys
import os
import yaml
# Import flask
from flask import *
from werkzeug.utils import secure_filename
# Import dotenv
from flask import Flask, render_template
from dotenv import load_dotenv
import yaml
import os
def create_app(test_config=None):
# create and configure the app
@ -27,6 +19,7 @@ def create_app(test_config=None):
# Get environment variables
load_dotenv(os.path.join(app.root_path, 'user', '.env'))
print("Loaded env")
# Get config file
with open(os.path.join(app.root_path, 'user', 'conf.yml'), 'r') as f:

View file

@ -24,11 +24,13 @@ def uploads(file, quality):
img = Image.open(os.path.join(current_app.config['UPLOAD_FOLDER'], secure_filename(file)))
img_ext = os.path.splitext(secure_filename(file))[-1].lower().replace('.', '')
img_ext = set_ext[img_ext]
img_icc = img.info.get("icc_profile") # Get ICC profile as it alters colours
# Resize image and orientate correctly
img.thumbnail((quality, quality), Image.LANCZOS)
img = ImageOps.exif_transpose(img)
img.save(buff, img_ext)
img.save(buff, img_ext, icc_profile=img_icc)
img.close()
# Seek to beginning of buffer and return
buff.seek(0)

View file

@ -25,7 +25,7 @@ def image(id):
# Get exif data from image
try:
file = Image.open(os.path.join(current_app.config['UPLOAD_FOLDER'], 'original', image['file_name']))
file = Image.open(os.path.join(current_app.config['UPLOAD_FOLDER'], image['file_name']))
raw_exif = file.getexif()
human_exif = {}

View file

@ -1,24 +1,43 @@
{% extends 'layout.html' %}
{% block header %}
<img src="{{ url_for('static', filename='images/leaves.jpg') }}" alt="leaves" onload="imgFade(this)" style="display: none;"/>
<img src="{{ url_for('static', filename='images/background.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
{% endblock %}
{% block content %}
<div class="app">
<h1>Login</h1>
<div id="login" class="login">
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Log In">
</form>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
<div class="login box-ui">
<div class="box-ui-header">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -2 24 24" fill="currentColor">
<path d="M3 0h10a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm2 1h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm0 12h2a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm0-4h6a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm0-4h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2z"></path>
</svg>
<h2>Login</h2>
</div>
<div class="box-ui-content">
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
<form method="post" class="nice-form">
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" fill="currentColor">
<path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-14a4 4 0 0 1 4 4v2a4 4 0 1 1-8 0V8a4 4 0 0 1 4-4zm0 2a2 2 0 0 0-2 2v2a2 2 0 1 0 4 0V8a2 2 0 0 0-2-2zM5.91 16.876a8.033 8.033 0 0 1-1.58-1.232 5.57 5.57 0 0 1 2.204-1.574 1 1 0 1 1 .733 1.86c-.532.21-.993.538-1.358.946zm8.144.022a3.652 3.652 0 0 0-1.41-.964 1 1 0 1 1 .712-1.868 5.65 5.65 0 0 1 2.284 1.607 8.032 8.032 0 0 1-1.586 1.225z"></path>
</svg>
<input name="username" id="username" required>
</span>
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -2 24 24" fill="currentColor">
<path d="M2 12v6h10v-6H2zm10-2a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2V5a5 5 0 1 1 10 0v5zm-2 0V5a3 3 0 1 0-6 0v5h6zm-3 7a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"></path>
</svg>
<input type="password" name="password" id="password" required>
</span>
<input class="form-button" type="submit" value="Log In">
</form>
<a class="form-button faded" href="{{ url_for('auth.register') }}">Register</a>
</div>
</div>
</div>
{% endblock %}

View file

@ -1,24 +1,43 @@
{% extends 'layout.html' %}
{% block header %}
<img src="{{ url_for('static', filename='images/leaves.jpg') }}" alt="leaves" onload="imgFade(this)" style="display: none;"/>
<img src="{{ url_for('static', filename='images/background.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
{% endblock %}
{% block content %}
<div class="app">
<h1>register</h1>
<div id="register" class="register">
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Register">
</form>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
<div class="register box-ui">
<div class="box-ui-header">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -2 24 24" fill="currentColor">
<path d="M3 0h10a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm2 1h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm0 12h2a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm0-4h6a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm0-4h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2z"></path>
</svg>
<h2>Register</h2>
</div>
<div class="box-ui-content">
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
<form method="post" class="nice-form">
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" fill="currentColor">
<path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-14a4 4 0 0 1 4 4v2a4 4 0 1 1-8 0V8a4 4 0 0 1 4-4zm0 2a2 2 0 0 0-2 2v2a2 2 0 1 0 4 0V8a2 2 0 0 0-2-2zM5.91 16.876a8.033 8.033 0 0 1-1.58-1.232 5.57 5.57 0 0 1 2.204-1.574 1 1 0 1 1 .733 1.86c-.532.21-.993.538-1.358.946zm8.144.022a3.652 3.652 0 0 0-1.41-.964 1 1 0 1 1 .712-1.868 5.65 5.65 0 0 1 2.284 1.607 8.032 8.032 0 0 1-1.586 1.225z"></path>
</svg>
<input name="username" id="username" required>
</span>
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -2 24 24" fill="currentColor">
<path d="M2 12v6h10v-6H2zm10-2a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2V5a5 5 0 1 1 10 0v5zm-2 0V5a3 3 0 1 0-6 0v5h6zm-3 7a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"></path>
</svg>
<input type="password" name="password" id="password" required>
</span>
<input class="form-button" type="submit" value="Register">
</form>
<a class="form-button faded" href="{{ url_for('auth.login') }}">Login</a>
</div>
</div>
</div>
{% endblock %}

View file

@ -1,7 +1,7 @@
{% extends 'layout.html' %}
{% block header %}
<img src="{{ url_for('static', filename='images/background.svg') }}" onload="imgFade(this)" style="display: none;"/>
<img src="{{ url_for('static', filename='images/background.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
{% endblock %}
{% block content %}

View file

@ -8,7 +8,7 @@
<div class="image__fullscreen">
<img
src=""
onload="imgFade(this)"
onload="imgFade(this);"
style="opacity:0;"
/>
</div>
@ -20,6 +20,8 @@
src="/api/uploads/{{ image['file_name'] }}/1000"
onload="imgFade(this)" style="opacity:0;"
onerror="this.src='/static/images/error.png'"
width="{{ file['width'] }}"
height="{{ file['height'] }}"
/>
</div>
<div class="img-tools">
@ -122,29 +124,23 @@
{% endif %}
</div>
<script>
/*
const url = new URL(window.location);
if (url.searchParams.get('i') == 'full') {
$('.image__fullscreen').addClass('image__fullscreen--active');
$('.image__fullscreen img').attr('src', '/api/uploads/{{ image['file_name'] }}/0');
} else {
$('.image__fullscreen').removeClass('image__fullscreen--active');
}
*/
$('.image__fullscreen').click(function() {
$('.image__fullscreen').removeClass('image__fullscreen--active');
//window.history.replaceState({}, '', `${url}`);
});
$('#img-fullscreen').click(function() {
$('.image__fullscreen').addClass('image__fullscreen--active');
$('.image__fullscreen img').attr('src', '/api/uploads/{{ image['file_name'] }}/0');
//window.history.replaceState({}, '', url+'?i=full');
if ($('.image__fullscreen img').attr('src') == '') {
$('.image__fullscreen img').attr('src', '/api/uploads/{{ image['file_name'] }}/0');
}
});
$('#img-share').click(function() {
//navigator.clipboard.writeText(window.location.href);
addNotification("Copied link!", 4);
try {
navigator.clipboard.writeText(window.location.href);
addNotification("Copied link!", 4);
} catch (err) {
addNotification("Failed to copy link! Are you on HTTP?", 2);
}
});
$('#img-info').click(function() {

View file

@ -12,7 +12,7 @@
<a class="gallery__item" href="/image/{{ image['id'] }}">
<div class="gallery__item-info">
<p>{{ image['id'] }}</p>
<h2>{{ image['file_name'] }}</h2>
<h2>{{ image['created_at'] }}</h2>
</div>
<span class="gallery__item-filter"></span>
<img

View file

@ -26,27 +26,38 @@
<span>Groups</span>
</a>
<a href="{{url_for('gallery.upload')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" width="24" fill="currentColor">
<path d="M8 3.414v5.642a1 1 0 1 1-2 0V3.414L4.879 4.536A1 1 0 0 1 3.464 3.12L6.293.293a1 1 0 0 1 1.414 0l2.829 2.828A1 1 0 1 1 9.12 4.536L8 3.414zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path>
</svg>
<span>Upload</span>
</a>
{% if g.user %}
<a href="{{url_for('gallery.upload')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" width="24" fill="currentColor">
<path d="M8 3.414v5.642a1 1 0 1 1-2 0V3.414L4.879 4.536A1 1 0 0 1 3.464 3.12L6.293.293a1 1 0 0 1 1.414 0l2.829 2.828A1 1 0 1 1 9.12 4.536L8 3.414zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path>
</svg>
<span>Upload</span>
</a>
{% endif %}
</div>
<div>
<a href="{{url_for('gallery.profile')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor">
<path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-14a4 4 0 0 1 4 4v2a4 4 0 1 1-8 0V8a4 4 0 0 1 4-4zm0 2a2 2 0 0 0-2 2v2a2 2 0 1 0 4 0V8a2 2 0 0 0-2-2zM5.91 16.876a8.033 8.033 0 0 1-1.58-1.232 5.57 5.57 0 0 1 2.204-1.574 1 1 0 1 1 .733 1.86c-.532.21-.993.538-1.358.946zm8.144.022a3.652 3.652 0 0 0-1.41-.964 1 1 0 1 1 .712-1.868 5.65 5.65 0 0 1 2.284 1.607 8.032 8.032 0 0 1-1.586 1.225z"></path>
</svg>
<span>Profile</span>
</a>
<div>
{% if g.user %}
<a href="{{url_for('gallery.profile')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor">
<path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-14a4 4 0 0 1 4 4v2a4 4 0 1 1-8 0V8a4 4 0 0 1 4-4zm0 2a2 2 0 0 0-2 2v2a2 2 0 1 0 4 0V8a2 2 0 0 0-2-2zM5.91 16.876a8.033 8.033 0 0 1-1.58-1.232 5.57 5.57 0 0 1 2.204-1.574 1 1 0 1 1 .733 1.86c-.532.21-.993.538-1.358.946zm8.144.022a3.652 3.652 0 0 0-1.41-.964 1 1 0 1 1 .712-1.868 5.65 5.65 0 0 1 2.284 1.607 8.032 8.032 0 0 1-1.586 1.225z"></path>
</svg>
<span>Profile</span>
</a>
<a href="{{url_for('gallery.settings')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -2 24 24" width="24" fill="currentColor">
<path d="M9.815 3.094a3.467 3.467 0 0 1-2.78-1.09l-.084-.001a3.467 3.467 0 0 1-2.781 1.09 3.477 3.477 0 0 1-1.727 2.51 3.471 3.471 0 0 1 0 2.794 3.477 3.477 0 0 1 1.727 2.51 3.467 3.467 0 0 1 2.78 1.09h.084a3.467 3.467 0 0 1 2.78-1.09 3.477 3.477 0 0 1 1.727-2.51 3.471 3.471 0 0 1 0-2.794 3.477 3.477 0 0 1-1.726-2.51zM14 5.714a1.474 1.474 0 0 0 0 2.572l-.502 1.684a1.473 1.473 0 0 0-1.553 2.14l-1.443 1.122A1.473 1.473 0 0 0 8.143 14l-2.304-.006a1.473 1.473 0 0 0-2.352-.765l-1.442-1.131A1.473 1.473 0 0 0 .5 9.968L0 8.278a1.474 1.474 0 0 0 0-2.555l.5-1.69a1.473 1.473 0 0 0 1.545-2.13L3.487.77A1.473 1.473 0 0 0 5.84.005L8.143 0a1.473 1.473 0 0 0 2.358.768l1.444 1.122a1.473 1.473 0 0 0 1.553 2.14L14 5.714zm-5.812 9.198a7.943 7.943 0 0 0 2.342-.73 3.468 3.468 0 0 1-.087.215 3.477 3.477 0 0 1 1.727 2.51 3.467 3.467 0 0 1 2.78 1.09h.084a3.467 3.467 0 0 1 2.78-1.09 3.477 3.477 0 0 1 1.727-2.51 3.471 3.471 0 0 1 0-2.794 3.477 3.477 0 0 1-1.726-2.51 3.467 3.467 0 0 1-2.78-1.09h-.084l-.015.016a8.077 8.077 0 0 0 .002-2.016L16.144 6a1.473 1.473 0 0 0 2.358.768l1.444 1.122a1.473 1.473 0 0 0 1.553 2.14L22 11.714a1.474 1.474 0 0 0 0 2.572l-.502 1.684a1.473 1.473 0 0 0-1.553 2.14l-1.443 1.122a1.473 1.473 0 0 0-2.359.768l-2.304-.006a1.473 1.473 0 0 0-2.352-.765l-1.442-1.131a1.473 1.473 0 0 0-1.545-2.13l-.312-1.056zM7 10a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 8a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path>
</svg>
<span>Settings</span>
</a>
<a href="{{url_for('gallery.settings')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -2 24 24" width="24" fill="currentColor">
<path d="M9.815 3.094a3.467 3.467 0 0 1-2.78-1.09l-.084-.001a3.467 3.467 0 0 1-2.781 1.09 3.477 3.477 0 0 1-1.727 2.51 3.471 3.471 0 0 1 0 2.794 3.477 3.477 0 0 1 1.727 2.51 3.467 3.467 0 0 1 2.78 1.09h.084a3.467 3.467 0 0 1 2.78-1.09 3.477 3.477 0 0 1 1.727-2.51 3.471 3.471 0 0 1 0-2.794 3.477 3.477 0 0 1-1.726-2.51zM14 5.714a1.474 1.474 0 0 0 0 2.572l-.502 1.684a1.473 1.473 0 0 0-1.553 2.14l-1.443 1.122A1.473 1.473 0 0 0 8.143 14l-2.304-.006a1.473 1.473 0 0 0-2.352-.765l-1.442-1.131A1.473 1.473 0 0 0 .5 9.968L0 8.278a1.474 1.474 0 0 0 0-2.555l.5-1.69a1.473 1.473 0 0 0 1.545-2.13L3.487.77A1.473 1.473 0 0 0 5.84.005L8.143 0a1.473 1.473 0 0 0 2.358.768l1.444 1.122a1.473 1.473 0 0 0 1.553 2.14L14 5.714zm-5.812 9.198a7.943 7.943 0 0 0 2.342-.73 3.468 3.468 0 0 1-.087.215 3.477 3.477 0 0 1 1.727 2.51 3.467 3.467 0 0 1 2.78 1.09h.084a3.467 3.467 0 0 1 2.78-1.09 3.477 3.477 0 0 1 1.727-2.51 3.471 3.471 0 0 1 0-2.794 3.477 3.477 0 0 1-1.726-2.51 3.467 3.467 0 0 1-2.78-1.09h-.084l-.015.016a8.077 8.077 0 0 0 .002-2.016L16.144 6a1.473 1.473 0 0 0 2.358.768l1.444 1.122a1.473 1.473 0 0 0 1.553 2.14L22 11.714a1.474 1.474 0 0 0 0 2.572l-.502 1.684a1.473 1.473 0 0 0-1.553 2.14l-1.443 1.122a1.473 1.473 0 0 0-2.359.768l-2.304-.006a1.473 1.473 0 0 0-2.352-.765l-1.442-1.131a1.473 1.473 0 0 0-1.545-2.13l-.312-1.056zM7 10a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 8a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path>
</svg>
<span>Settings</span>
</a>
{% else %}
<a href="{{url_for('auth.login')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -3 24 24" fill="currentColor">
<path d="M6.641 9.828H1a1 1 0 1 1 0-2h5.641l-1.12-1.12a1 1 0 0 1 1.413-1.415L9.763 8.12a.997.997 0 0 1 0 1.415l-2.829 2.828A1 1 0 0 1 5.52 10.95l1.121-1.122zM13 0a1 1 0 0 1 1 1v16a1 1 0 0 1-2 0V1a1 1 0 0 1 1-1z"></path>
</svg>
<span>Register</span>
</a>
{% endif %}
</div>
</nav>
<main>
@ -85,6 +96,7 @@
function imgFade(obj) {
$(obj).animate({opacity: 1}, 500);
$(obj).parent().css('background', 'transparent');
}
function addNotification(text='Sample notification', type=4) {
@ -144,17 +156,16 @@
// Append notification to container
container.appendChild(div);
// Remove notification after 6.9 seconds
// Remove notification after 5 seconds
setTimeout(function() {
if (div.parentNode) {
div.style.opacity = 0;
div.style.transform = 'translateX(100%)';
div.classList.add('sniffle__notification--hide');
setTimeout(function() {
container.removeChild(div);
}, 500);
}
}, 2500);
}, 5000);
}
</script>
</body>

View file

@ -6,31 +6,46 @@
{% block content %}
<div class="app">
<h1>Upload!!!!!</h1>
<div id="upload" class="upload">
<form method="post" enctype="multipart/form-data" id="uploadForm">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" width="24" fill="currentColor">
<path d="M8 3.414v5.642a1 1 0 1 1-2 0V3.414L4.879 4.536A1 1 0 0 1 3.464 3.12L6.293.293a1 1 0 0 1 1.414 0l2.829 2.828A1 1 0 1 1 9.12 4.536L8 3.414zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path>
</svg>
<input type="file" name="file" id="file" class="input-file"/>
<div class="upload box-ui">
<div class="box-ui-header">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -2 24 24" fill="currentColor">
<path d="M3 0h10a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm2 1h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm0 12h2a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm0-4h6a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm0-4h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2z"></path>
</svg>
<h2>Upload!!!!!!!</h2>
</div>
<div class="box-ui-content">
<form method="post" class="nice-form" id="uploadForm">
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" width="24" fill="currentColor">
<path d="M8 3.414v5.642a1 1 0 1 1-2 0V3.414L4.879 4.536A1 1 0 0 1 3.464 3.12L6.293.293a1 1 0 0 1 1.414 0l2.829 2.828A1 1 0 1 1 9.12 4.536L8 3.414zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path>
</svg>
<input type="file" name="file" id="file" class="input-file"/>
</span>
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -2 24 24" width="24" fill="currentColor">
<path d="M14 8.322V2H2v12h3.576l3.97-5.292A3 3 0 0 1 14 8.322zm0 3.753l-1.188-2.066a1 1 0 0 0-1.667-.101L8.076 14H14v-1.925zM14 16H2v2h12v-2zM2 0h12a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm4 9a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path>
</svg>
<input type="text" name="alt" placeholder="alt" id="alt"/>
</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -2 24 24" width="24" fill="currentColor">
<path d="M14 8.322V2H2v12h3.576l3.97-5.292A3 3 0 0 1 14 8.322zm0 3.753l-1.188-2.066a1 1 0 0 0-1.667-.101L8.076 14H14v-1.925zM14 16H2v2h12v-2zM2 0h12a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm4 9a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path>
</svg>
<input type="text" name="alt" placeholder="alt" id="alt"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor">
<path d="M5.72 14.456l1.761-.508 10.603-10.73a.456.456 0 0 0-.003-.64l-.635-.642a.443.443 0 0 0-.632-.003L6.239 12.635l-.52 1.82zM18.703.664l.635.643c.876.887.884 2.318.016 3.196L8.428 15.561l-3.764 1.084a.901.901 0 0 1-1.11-.623.915.915 0 0 1-.002-.506l1.095-3.84L15.544.647a2.215 2.215 0 0 1 3.159.016zM7.184 1.817c.496 0 .898.407.898.909a.903.903 0 0 1-.898.909H3.592c-.992 0-1.796.814-1.796 1.817v10.906c0 1.004.804 1.818 1.796 1.818h10.776c.992 0 1.797-.814 1.797-1.818v-3.635c0-.502.402-.909.898-.909s.898.407.898.91v3.634c0 2.008-1.609 3.636-3.593 3.636H3.592C1.608 19.994 0 18.366 0 16.358V5.452c0-2.007 1.608-3.635 3.592-3.635h3.592z"></path>
</svg>
<input type="text" name="description" placeholder="description" id="description"/>
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor">
<path d="M5.72 14.456l1.761-.508 10.603-10.73a.456.456 0 0 0-.003-.64l-.635-.642a.443.443 0 0 0-.632-.003L6.239 12.635l-.52 1.82zM18.703.664l.635.643c.876.887.884 2.318.016 3.196L8.428 15.561l-3.764 1.084a.901.901 0 0 1-1.11-.623.915.915 0 0 1-.002-.506l1.095-3.84L15.544.647a2.215 2.215 0 0 1 3.159.016zM7.184 1.817c.496 0 .898.407.898.909a.903.903 0 0 1-.898.909H3.592c-.992 0-1.796.814-1.796 1.817v10.906c0 1.004.804 1.818 1.796 1.818h10.776c.992 0 1.797-.814 1.797-1.818v-3.635c0-.502.402-.909.898-.909s.898.407.898.91v3.634c0 2.008-1.609 3.636-3.593 3.636H3.592C1.608 19.994 0 18.366 0 16.358V5.452c0-2.007 1.608-3.635 3.592-3.635h3.592z"></path>
</svg>
<input type="text" name="description" placeholder="description" id="description"/>
</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3 24 24" width="24" fill="currentColor">
<path d="M11.586 15.071L13 13.657l1.414 1.414 6.165-6.165 1.09-3.552-2.484-2.483-1.079.336-1.598-1.598L18.591.96a2 2 0 0 1 2.008.496l2.483 2.483a2 2 0 0 1 .498 2L22.345 9.97l-7.93 7.93-2.83-2.828zM14.236.75l2.482 2.483a2 2 0 0 1 .498 2l-1.235 4.028-7.93 7.931-7.78-7.778L8.17 1.516 12.227.254a2 2 0 0 1 2.008.496zM3.1 9.414l4.95 4.95 6.164-6.165 1.09-3.552-2.484-2.483-3.585 1.115L3.1 9.414zm7.424-2.475a1.5 1.5 0 1 1 2.121-2.121 1.5 1.5 0 0 1-2.12 2.121zm6.886 1.022l.782-2.878c.45.152.755.325.917.518a1.5 1.5 0 0 1-.185 2.113c-.29.244-.795.326-1.514.247z"></path>
</svg>
<input type="text" name="tags" placeholder="tags" id="tags"/>
<input type="submit" value="Upload" name="submit" id="submit"/>
</form>
<span class="form-box">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3 24 24" width="24" fill="currentColor">
<path d="M11.586 15.071L13 13.657l1.414 1.414 6.165-6.165 1.09-3.552-2.484-2.483-1.079.336-1.598-1.598L18.591.96a2 2 0 0 1 2.008.496l2.483 2.483a2 2 0 0 1 .498 2L22.345 9.97l-7.93 7.93-2.83-2.828zM14.236.75l2.482 2.483a2 2 0 0 1 .498 2l-1.235 4.028-7.93 7.931-7.78-7.778L8.17 1.516 12.227.254a2 2 0 0 1 2.008.496zM3.1 9.414l4.95 4.95 6.164-6.165 1.09-3.552-2.484-2.483-3.585 1.115L3.1 9.414zm7.424-2.475a1.5 1.5 0 1 1 2.121-2.121 1.5 1.5 0 0 1-2.12 2.121zm6.886 1.022l.782-2.878c.45.152.755.325.917.518a1.5 1.5 0 0 1-.185 2.113c-.29.244-.795.326-1.514.247z"></path>
</svg>
<input type="text" name="tags" placeholder="tags" id="tags"/>
</span>
<input class="form-button" type="submit" value="Upload" name="submit" id="submit"/>
</form>
</div>
</div>
</div>
<script>

View file

@ -4,6 +4,7 @@
@import 'ui/reset';
@import 'ui/nav';
@import 'ui/main';
@import 'ui/gallery';
@import 'ui/notification';
@import 'buttons/img-tool';
@ -69,19 +70,177 @@
*/
}
@keyframes imgLoading {
0% {
background-position: 0% 50%;
.box-ui {
margin: 0 auto;
padding: 0;
width: 100%;
height: 100%;
max-width: 621px;
position: relative;
display: flex;
flex-direction: column;
background-color: $black200;
border-radius: $rad;
}
.box-ui-header {
margin: 0;
padding: 0.5rem;
width: 100%;
height: 2.5rem;
display: flex;
justify-content: start;
align-items: center;
gap: 0.5rem;
background-color: $black300;
border-radius: $rad $rad 0 0;
svg {
margin: 0;
padding: 0;
width: 1.25rem;
height: 1.25rem;
fill: $green;
}
50% {
background-position: 100% 50%;
}
h2 {
margin: 0;
padding: 0;
100% {
background-position: 0% 50%;
font-family: $font-header;
font-size: 1.25rem;
font-stretch: ultra-expanded;
font-weight: 600;
color: $green;
text-overflow: ellipsis;
overflow: hidden;
}
}
.box-ui-content {
margin: 0;
padding: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
p {
margin: 0;
padding: 0;
font-family: $font-body;
font-size: 1rem;
font-weight: 500;
color: $white100;
text-overflow: ellipsis;
overflow: hidden;
}
}
.nice-form {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-box {
margin: 0;
padding: 0;
width: 100%;
height: 2rem;
display: flex;
flex-direction: row;
svg {
margin: 0;
padding: 0.3rem;
width: 2rem;
height: 2rem;
background-color: $black300;
color: $white100;
border: 1px solid $black400;
border-radius: $rad 0 0 $rad;
border-right: none;
}
input {
margin: 0;
padding: 0.5rem;
width: 100%;
height: 2rem;
font-family: $font-body;
font-size: 1rem;
font-weight: 500;
color: $white100;
background-color: $black200;
border: 1px solid $black400;
border-radius: 0 $rad $rad 0;
border-left: none;
&:focus {
outline: none;
~ svg {
color: $green;
background-color: $black200;
}
}
&::placeholder {
color: $white100;
}
}
}
.form-button {
margin: 0;
padding: 0;
width: 100%;
height: 2rem;
display: flex;
justify-content: center;
align-items: center;
font-family: $font-body;
font-size: 1rem;
font-weight: 500;
text-align: center;
text-decoration: none;
color: $white100;
background-color: $black300;
border: 1px solid $black400;
border-radius: $rad;
&:hover {
cursor: pointer;
color: $green;
}
}
.faded {
background-color: $black200;
border-color: $black200;
}
.err-warning {
min-height: 100vh;
@ -114,129 +273,6 @@
}
}
.gallery {
margin: 0;
padding: 0;
width: 100%;
display: grid;
grid-template-columns: auto auto auto auto auto auto;
gap: 0.5rem;
.gallery__item {
margin: 0;
padding: 0;
height: auto;
position: relative;
background: linear-gradient(-45deg, $black100, $black400 40%, $black100);
background-size: 400% 400%;
border-radius: $rad;
animation: imgLoading 10s ease infinite;
box-sizing: border-box;
overflow: hidden;
&:after {
content: "";
display: block;
padding-bottom: 100%;
}
.gallery__item-info {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: absolute;
left: 0;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: flex-end;
background-image: linear-gradient(to bottom, #00000000, rgba($black100, 0.8));
z-index: +1;
opacity: 0; // hide
transform: scale(1.05); // scale up
transition: all 0.5s cubic-bezier(.79, .14, .15, .86);
h2 {
margin: 0;
padding: 0 1rem 0.5rem;
font-family: $font-header;
font-size: 1rem;
font-stretch: ultra-expanded;
font-weight: 600;
color: $green;
text-overflow: ellipsis;
overflow: hidden;
opacity: 0; // hide
transition: all 0.2s ease-in-out;
}
p {
margin: 0;
padding: 0 1rem 0.5rem;
font-family: $font-body;
font-size: 0.8rem;
font-weight: 500;
color: $white100;
text-overflow: ellipsis;
overflow: hidden;
opacity: 0; // hide
transition: all 0.2s ease-in-out;
}
&:hover {
opacity: 1;
transform: scale(1);
h2,
p {
opacity: 1;
}
}
}
.gallery__item-image {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
object-fit: cover;
object-position: center;
border-radius: $rad;
}
}
}
.image__fullscreen {
margin: 0;
padding: 0 0 0 3.5rem;
@ -293,6 +329,8 @@
width: 100%;
height: auto;
max-width: 100%;
max-height: 69vh;
position: sticky;
top: 0;
@ -300,6 +338,10 @@
display: flex;
overflow: hidden;
background: linear-gradient(-45deg, $black100, $black400 40%, $black100);
background-size: 400% 400%;
border-radius: $rad;
animation: imgLoading 10s ease infinite;
border-radius: $rad;
box-sizing: border-box;
@ -308,8 +350,9 @@
margin: auto;
padding: 0;
width: auto;
height: auto;
max-width: 100%;
height: 100%;
max-height: 69vh;
background-color: $black200;
@ -341,7 +384,7 @@
padding: 0.5rem;
width: 100%;
height: 2rem;
height: 2.5rem;
display: flex;
justify-content: start;

View file

@ -0,0 +1,161 @@
@keyframes imgLoading {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.gallery {
margin: 0;
padding: 0;
width: 100%;
display: grid;
grid-template-columns: auto auto auto auto auto auto auto auto;
gap: 0.5rem;
}
@media (max-width: 1550px) {
.gallery {
grid-template-columns: auto auto auto auto auto auto auto;
}
}
@media (max-width: 1300px) {
.gallery {
grid-template-columns: auto auto auto auto auto auto;
}
}
@media (max-width: 1050px) {
.gallery {
grid-template-columns: auto auto auto auto auto;
}
}
@media (max-width: 800px) {
.gallery {
grid-template-columns: auto auto auto auto;
}
}
@media (max-width: 550px) {
.gallery {
grid-template-columns: auto auto auto;
}
}
.gallery__item {
margin: 0;
padding: 0;
height: auto;
position: relative;
background: linear-gradient(-45deg, $black100, $black400, $black100);
background-size: 400% 400%;
border-radius: $rad;
animation: imgLoading 10s ease infinite;
box-sizing: border-box;
overflow: hidden;
&:after {
content: "";
display: block;
padding-bottom: 100%;
}
}
.gallery__item-info {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: absolute;
left: 0;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: flex-end;
background-image: linear-gradient(to bottom, #00000000, rgba($black100, 0.8));
z-index: +1;
opacity: 0; // hide
transform: scale(1.05); // scale up
transition: all 0.5s cubic-bezier(.79, .14, .15, .86);
h2 {
margin: 0;
padding: 0 1rem 0.5rem;
font-family: $font-header;
font-size: 1rem;
font-stretch: ultra-expanded;
font-weight: 600;
color: $green;
text-overflow: ellipsis;
overflow: hidden;
opacity: 0; // hide
transition: all 0.2s ease-in-out;
}
p {
margin: 0;
padding: 0 1rem 0.5rem;
font-family: $font-body;
font-size: 0.8rem;
font-weight: 500;
color: $white100;
text-overflow: ellipsis;
overflow: hidden;
opacity: 0; // hide
transition: all 0.2s ease-in-out;
}
&:hover {
opacity: 1;
transform: scale(1);
h2,
p {
opacity: 1;
}
}
}
.gallery__item-image {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
object-fit: cover;
object-position: center;
background-color: $black200;
border-radius: $rad;
}

View file

@ -43,7 +43,7 @@
box-sizing: border-box;
overflow: hidden;
transition: all 0.5s ease-in-out;
transition: all 0.25s ease-in-out;
}
.sniffle__notification-icon {
margin: 0;
@ -94,7 +94,7 @@
background-color: $white100;
animation: sniffle 2.5s linear;
animation: sniffle 4.9s linear;
}
.sniffle__notification--success {
color: $green;
@ -123,4 +123,9 @@
.sniffle__notification-time {
background-color: $blue;
}
}
.sniffle__notification--hide {
opacity: 0;
transform: translateX(100%);
}

View file

@ -2,13 +2,15 @@ from setuptools import find_packages, setup
setup(
name='onlylegs',
version='140123',
version='170123',
packages=find_packages(),
include_package_data=True,
install_requires=[
'flask',
'libsass',
'dotenv',
'Pillow',
'python-dotenv',
'pillow',
'colorthief',
'pyyaml',
],
)