Yaml config files

Fixed some Sass issues
No image... image
Squished some bugs involving uploading broken files
This commit is contained in:
Michał 2023-01-11 15:25:35 +00:00
parent 978086f512
commit 5db8fa52e8
12 changed files with 193 additions and 56 deletions

2
.gitignore vendored
View file

@ -1,5 +1,7 @@
# Remove all development files
gallery/user/uploads/*
gallery/user/conf.yml
gallery/user/conf.json
gallery/static/theme/*
.idea

View file

@ -12,6 +12,7 @@ Created by Fluffy Bean - Version 110123
import time
import sys
import os
import yaml
# Import flask
from flask import *
@ -27,12 +28,18 @@ def create_app(test_config=None):
# Get environment variables
load_dotenv(os.path.join(app.root_path, 'user', '.env'))
# Get config file
with open(os.path.join(app.root_path, 'user', 'conf.yml'), 'r') as f:
conf = yaml.load(f, Loader=yaml.FullLoader)
print("Loaded config")
print(conf['upload']['allowed-extensions'])
# App configuration
app.config.from_mapping(
SECRET_KEY=os.environ.get('FLASK_SECRET'),
DATABASE=os.path.join(app.instance_path, 'gallery.sqlite'),
UPLOAD_FOLDER=os.path.join(app.root_path, 'user', 'uploads'),
ALLOWED_EXTENSIONS=os.environ.get('FLASK_EXTENSIONS'),
ALLOWED_EXTENSIONS=conf['upload']['allowed-extensions'],
)
if test_config is None:

View file

@ -5,8 +5,6 @@ from gallery.auth import login_required
from gallery.db import get_db
import os
import datetime
from PIL import Image
from PIL.ExifTags import TAGS
dt = datetime.datetime.now()
blueprint = Blueprint('gallery', __name__)
@ -41,8 +39,10 @@ def upload():
if not file:
flash('No selected file')
return abort(404)
if secure_filename(file.filename).lower().split('.')[-1] in current_app.config['ALLOWED_EXTENSIONS']:
file_name = f"GWAGWA_{dt.year}{dt.month}{dt.day}-{dt.microsecond}.{secure_filename(file.filename).lower().split('.')[-1]}"
if not secure_filename(file.filename).lower().split('.')[-1] in current_app.config['ALLOWED_EXTENSIONS']:
abort(403)
file_name = file_name = f"GWAGWA_{dt.year}{dt.month}{dt.day}-{dt.microsecond}.{secure_filename(file.filename).lower().split('.')[-1]}"
file.save(os.path.join(current_app.config['UPLOAD_FOLDER']+'/original', file_name))
db = get_db()

View file

@ -1,7 +1,6 @@
from flask import Blueprint, flash, g, redirect, render_template, request, url_for, jsonify, current_app
from werkzeug.exceptions import abort
from werkzeug.utils import secure_filename
from gallery.auth import login_required
from gallery.db import get_db
import os
import datetime
@ -63,6 +62,7 @@ def image(id):
abort(404)
# Get exif data from image
try:
file = Image.open(os.path.join(current_app.config['UPLOAD_FOLDER'], 'original', image['file_name']))
raw_exif = file.getexif()
human_exif = {}
@ -78,6 +78,9 @@ def image(id):
if len(human_exif) == 0:
human_exif = False
except:
# Cringe, no file present
human_exif = False
# All in le head
return render_template('image.html', image=image, exif=human_exif)
return render_template('image.html', image=image, exif=human_exif, file=file)

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View file

@ -5,30 +5,44 @@
{% endblock %}
{% block content %}
<div class="image__fullscreen">
<img
src="/uploads/original/{{ image['file_name'] }}"
onload="imgFade(this)" style="display:none;"
onerror="this.style.display='none'"
/>
</div>
<div class="app">
<div class="image__container">
<img
class="image__item"
src="/uploads/original/{{ image['file_name'] }}"
onload="imgFade(this)" style="display:none;"
onerror="this.src='/static/images/error.png'"
/>
</div>
<div class="img-tools">
<div>
<button class="tool-btn" id="img-download">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" fill="currentColor">
<path d="M8 6.641l1.121-1.12a1 1 0 0 1 1.415 1.413L7.707 9.763a.997.997 0 0 1-1.414 0L3.464 6.934A1 1 0 1 1 4.88 5.52L6 6.641V1a1 1 0 1 1 2 0v5.641zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path>
</svg>
</button>
<button class="tool-btn" id="img-fullscreen">
<button class="tool-btn" id="img-info">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" fill="currentColor">
<path d="M19 0a1 1 0 0 1 1 1v6a1 1 0 0 1-2 0V3.414L11.414 10 18 16.586V13a1 1 0 0 1 2 0v6a1 1 0 0 1-1 1h-6a1 1 0 0 1 0-2h3.586L10 11.414 3.414 18H7a1 1 0 0 1 0 2H1a1 1 0 0 1-1-1v-6a1 1 0 0 1 2 0v3.586L8.586 10 2 3.414V7a1 1 0 1 1-2 0V1a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H3.414L10 8.586 16.586 2H13a1 1 0 0 1 0-2h6z"></path>
<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-10a1 1 0 0 1 1 1v5a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1zm0-1a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"></path>
</svg>
<span class="tool-tip">Info</span>
</button>
</div>
<div>
<button class="tool-btn" id="img-fullscreen">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -4 24 24" fill="currentColor">
<path d="M12.586 2H11a1 1 0 0 1 0-2h4a1 1 0 0 1 1 1v4a1 1 0 0 1-2 0V3.414L9.414 8 14 12.586V11a1 1 0 0 1 2 0v4a1 1 0 0 1-1 1h-4a1 1 0 0 1 0-2h1.586L8 9.414 3.414 14H5a1 1 0 0 1 0 2H1a1 1 0 0 1-1-1v-4a1 1 0 0 1 2 0v1.586L6.586 8 2 3.414V5a1 1 0 1 1-2 0V1a1 1 0 0 1 1-1h4a1 1 0 1 1 0 2H3.414L8 6.586 12.586 2z"></path>
</svg>
<span class="tool-tip">Fullscreen</span>
</button>
<button class="tool-btn" id="img-share">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -3 24 24" fill="currentColor">
<path d="M3.19 9.345a.97.97 0 0 1 1.37 0 .966.966 0 0 1 0 1.367l-2.055 2.052a1.932 1.932 0 0 0 0 2.735 1.94 1.94 0 0 0 2.74 0l4.794-4.787a.966.966 0 0 0 0-1.367.966.966 0 0 1 0-1.368.97.97 0 0 1 1.37 0 2.898 2.898 0 0 1 0 4.103l-4.795 4.787a3.879 3.879 0 0 1-5.48 0 3.864 3.864 0 0 1 0-5.47L3.19 9.344zm11.62-.69a.97.97 0 0 1-1.37 0 .966.966 0 0 1 0-1.367l2.055-2.052a1.932 1.932 0 0 0 0-2.735 1.94 1.94 0 0 0-2.74 0L7.962 7.288a.966.966 0 0 0 0 1.367.966.966 0 0 1 0 1.368.97.97 0 0 1-1.37 0 2.898 2.898 0 0 1 0-4.103l4.795-4.787a3.879 3.879 0 0 1 5.48 0 3.864 3.864 0 0 1 0 5.47L14.81 8.656z"></path>
</svg>
<span class="tool-tip">Share</span>
</button>
</div>
{% if g.user['id'] == image['author_id'] %}
@ -37,27 +51,30 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -2 24 24" fill="currentColor">
<path d="M6 2V1a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v1h4a2 2 0 0 1 2 2v1a2 2 0 0 1-2 2h-.133l-.68 10.2a3 3 0 0 1-2.993 2.8H5.826a3 3 0 0 1-2.993-2.796L2.137 7H2a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h4zm10 2H2v1h14V4zM4.141 7l.687 10.068a1 1 0 0 0 .998.932h6.368a1 1 0 0 0 .998-.934L13.862 7h-9.72zM7 8a1 1 0 0 1 1 1v7a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1zm4 0a1 1 0 0 1 1 1v7a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1z"></path>
</svg>
<span class="tool-tip">Delete</span>
</button>
<button class="tool-btn tool-btn--evil" id="img-edit">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2.5 -2.5 24 24" fill="currentColor">
<path d="M12.238 5.472L3.2 14.51l-.591 2.016 1.975-.571 9.068-9.068-1.414-1.415zM13.78 3.93l1.414 1.414 1.318-1.318a.5.5 0 0 0 0-.707l-.708-.707a.5.5 0 0 0-.707 0L13.781 3.93zm3.439-2.732l.707.707a2.5 2.5 0 0 1 0 3.535L5.634 17.733l-4.22 1.22a1 1 0 0 1-1.237-1.241l1.248-4.255 12.26-12.26a2.5 2.5 0 0 1 3.535 0z"></path>
</svg>
</button>
<button class="tool-btn tool-btn--evil" id="img-tags">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3 24 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>
<span class="tool-tip">Edit</span>
</button>
</div>
{% endif %}
</div>
{% if image['description'] != '' %}
<div class="image__info">
<h2>Description</h2>
<p>{{ image['description'] }}</p>
</div>
{% endif %}
<div class="image__info">
<h2>Info</h2>
<p>{{ image['file_name'] }}</p>
<p>{{ image['id'] }}</p>
<p>{{ image['author_id'] }}</p>
<p>{{ image['created_at'] }}</p>
<p>{{ image['description'] }}</p>
<p>Filename: {{ image['file_name'] }}</p>
<p>Image ID: {{ image['id'] }}</p>
<p>Author: {{ image['author_id'] }}</p>
<p>Upload date: {{ image['created_at'] }}</p>
<p>Dimensions: {{ file['width'] }}x{{ file['height'] }}</p>
</div>
{% if exif is not false %}
<div class="image__info">
@ -69,14 +86,19 @@
{% endif %}
</div>
<script>
$('#img-download').click(function() {
window.location.href = '/image/{{ image['id'] }}/download';
$('.image__fullscreen').click(function() {
$('.image__fullscreen').removeClass('image__fullscreen--active');
});
$('#img-fullscreen').click(function() {
$('#img-fullscreen').click(function() {
$('.image__fullscreen').addClass('image__fullscreen--active');
});
$('#img-share').click(function() {
navigator.clipboard.writeText(window.location.href);
//navigator.clipboard.writeText(window.location.href);
console.log('Non https debug: Copied to clipboard');
});
$('#img-info').click(function() {
});
{% if g.user['id'] == image['author_id'] %}
@ -95,10 +117,6 @@
$('#img-edit').click(function() {
window.location.href = '/image/{{ image['id'] }}/edit';
});
$('#img-tags').click(function() {
window.location.href = '/image/{{ image['id'] }}/tags';
});
{% endif %}
</script>
{% endblock %}

21
gallery/user/example.yml Normal file
View file

@ -0,0 +1,21 @@
# THIS IS AN EXAMPLE CONFIG, RENAME THIS TO conf.yml TO USE
admin:
name: Real Person
username: User
email: real-email@some.place
upload:
allowed-extensions:
- png
- jpg
- jpeg
- webp
max-size: 69MB
rename: GWA_{{username}}_{{time}}
website:
name: OnlyLegs
motto: Gwa Gwa
language: english # Placeholder for future language support endevours

View file

@ -5,6 +5,8 @@
width: 2.5rem;
height: 2.5rem;
position: relative;
border: none;
background-color: transparent;
color: $white100;
@ -18,12 +20,49 @@
cursor: pointer;
color: $green;
.tool-tip {
opacity: 1;
top: -2.5rem;
//transition-delay: 0.5s;
}
}
}
.tool-btn--evil {
color: $red;
span {
background-color: $red;
}
&:hover {
color: $white100;
}
}
.tool-tip {
margin: 0;
padding: 0.5rem 0.75rem;
width: auto;
display: block;
position: absolute;
top: -1.7rem;
left: 0;
transform: translateX(calc(-50% + 1.25rem ));
font-family: $font-body;
font-size: 1rem;
font-weight: 600;
background-color: $black300;
color: $white100;
opacity: 0;
border-radius: $rad;
transition: opacity 0.2s cubic-bezier(.76,0,.17,1), top 0.2s cubic-bezier(.76,0,.17,1);
pointer-events: none;
}

View file

@ -1,9 +1,9 @@
#topButton {
margin: 0;
padding: 0.25rem;
padding: 0.5rem;
width: 3rem;
height: 3rem;
width: 2.5rem;
height: 2.5rem;
position: fixed;
bottom: 0.75rem;

View file

@ -236,6 +236,56 @@
}
.image__fullscreen {
margin: 0;
padding: 0 0 0 3.5rem;
width: 100%;
height: 100dvh;
position: fixed;
top: -100%;
left: 0;
display: flex;
opacity: 0; // hide
background-color: rgba($black100, 0.8);
backdrop-filter: blur(1rem);
z-index: 21;
box-sizing: border-box;
img {
margin: auto;
padding: 0;
width: auto;
height: auto;
max-width: calc(100% - 1rem);
max-height: calc(100% - 1rem);
object-fit: contain;
object-position: center;
transform: scale(0.8);
border-radius: $rad;
}
}
.image__fullscreen--active {
top: 0;
opacity: 1; // show
transition: opacity 0.3s cubic-bezier(.79, .14, .15, .86);
img {
transform: scale(1);
transition: transform 0.2s cubic-bezier(.68,-0.55,.27,1.55);
}
}
.image__container {
margin: 0;
padding: 0;
@ -259,15 +309,12 @@
max-width: 100%;
height: 100%;
max-height: 75vh;
background: linear-gradient(-45deg, $black100, $black400 40%, $black100);
background-size: 400% 400%;
border-radius: $rad;
animation: imgLoading 10s ease infinite;
max-height: 69vh;
object-fit: contain;
object-position: center;
border-radius: $rad;
}
}

View file

@ -47,7 +47,7 @@ main {
height: 100%;
background-image: linear-gradient(to bottom, #00000000, rgba($black100, 1));
backdrop-filter: blur(0.5rem);
backdrop-filter: blur(1rem);
z-index: +1;
}

View file

@ -18,7 +18,7 @@ nav {
color: $white100;
box-sizing: border-box;
z-index: 2;
z-index: 69;
transition: width 0.4s cubic-bezier(.76,0,.17,1), background-color 0.3s ease-in-out;
div {