Merge pull request #23 from Fluffy-Bean/unstable

Unstable
This commit is contained in:
Michał 2023-04-19 19:11:57 +01:00 committed by GitHub
commit aea9ebb12f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 232 additions and 156 deletions

View file

@ -1,8 +1,5 @@
version = 1 version = 1
[[analyzers]]
name = "sql"
[[analyzers]] [[analyzers]]
name = "python" name = "python"

4
.gitignore vendored
View file

@ -1,5 +1,5 @@
gallery/static/.webassets-cache onlylegs/static/.webassets-cache
gallery/static/gen onlylegs/static/gen
instance/ instance/
migrations/ migrations/

View file

@ -16,11 +16,11 @@ from flask import Flask, render_template, abort
from werkzeug.exceptions import HTTPException from werkzeug.exceptions import HTTPException
from werkzeug.security import generate_password_hash from werkzeug.security import generate_password_hash
from gallery.extensions import db, migrate, login_manager, assets, compress, cache from onlylegs.extensions import db, migrate, login_manager, assets, compress, cache
from gallery.views import index, image, group, settings, profile from onlylegs.views import index, image, group, settings, profile
from gallery.models import User from onlylegs import api
from gallery import api from onlylegs import auth
from gallery import auth from onlylegs.models import User
INSTACE_DIR = os.path.join(platformdirs.user_config_dir("onlylegs"), "instance") INSTACE_DIR = os.path.join(platformdirs.user_config_dir("onlylegs"), "instance")
@ -78,21 +78,21 @@ def create_app(): # pylint: disable=R0914
# can also set session_protection to "strong" # can also set session_protection to "strong"
# this would protect against session hijacking # this would protect against session hijacking
login_manager.init_app(app) login_manager.init_app(app)
login_manager.login_view = "gallery.index" login_manager.login_view = "onlylegs.index"
@login_manager.user_loader @login_manager.user_loader
def load_user(user_id): def load_user(user_id): # skipcq: PTC-W0065
return User.query.filter_by(alt_id=user_id).first() return User.query.filter_by(alt_id=user_id).first()
@login_manager.unauthorized_handler @login_manager.unauthorized_handler
def unauthorized(): def unauthorized(): # skipcq: PTC-W0065
error = 401 error = 401
msg = "You are not authorized to view this page!!!!" msg = "You are not authorized to view this page!!!!"
return render_template("error.html", error=error, msg=msg), error return render_template("error.html", error=error, msg=msg), error
# ERROR HANDLERS # ERROR HANDLERS
@app.errorhandler(Exception) @app.errorhandler(Exception)
def error_page(err): # noqa def error_page(err): # skipcq: PTC-W0065
""" """
Error handlers, if the error is not a HTTP error, return 500 Error handlers, if the error is not a HTTP error, return 500
""" """
@ -106,7 +106,7 @@ def create_app(): # pylint: disable=R0914
# ASSETS # ASSETS
assets.init_app(app) assets.init_app(app)
scripts = Bundle("js/*.js", filters="jsmin", output="gen/js.js", depends="js/*.js") scripts = Bundle("js/*.js", output="gen/js.js", depends="js/*.js") # filter jsmin is broken :c
styles = Bundle( styles = Bundle(
"sass/*.sass", "sass/*.sass",
filters="libsass, cssmin", filters="libsass, cssmin",

View file

@ -13,10 +13,10 @@ from flask_login import login_required, current_user
from colorthief import ColorThief from colorthief import ColorThief
from gallery.extensions import db from onlylegs.extensions import db
from gallery.models import Post, Group, GroupJunction from onlylegs.models import Post, Group, GroupJunction
from gallery.utils import metadata as mt from onlylegs.utils import metadata as mt
from gallery.utils.generate_image import generate_thumbnail from onlylegs.utils.generate_image import generate_thumbnail
blueprint = Blueprint("api", __name__, url_prefix="/api") blueprint = Blueprint("api", __name__, url_prefix="/api")

View file

@ -10,8 +10,8 @@ from werkzeug.security import check_password_hash, generate_password_hash
from flask_login import login_user, logout_user, login_required from flask_login import login_user, logout_user, login_required
from gallery.extensions import db from onlylegs.extensions import db
from gallery.models import User from onlylegs.models import User
blueprint = Blueprint("auth", __name__, url_prefix="/auth") blueprint = Blueprint("auth", __name__, url_prefix="/auth")

View file

@ -3,7 +3,7 @@ OnlyLegs - Database models and ions for SQLAlchemy
""" """
from uuid import uuid4 from uuid import uuid4
from flask_login import UserMixin from flask_login import UserMixin
from .extensions import db from onlylegs.extensions import db
class GroupJunction(db.Model): # pylint: disable=too-few-public-methods, C0103 class GroupJunction(db.Model): # pylint: disable=too-few-public-methods, C0103

View file

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View file

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -9,12 +9,12 @@ function loadOnView() {
const webpSupport = checkWebpSupport(); const webpSupport = checkWebpSupport();
for (let i = 0; i < lazyLoad.length; i++) { for (let i = 0; i < lazyLoad.length; i++) {
let image = lazyLoad[i]; const image = lazyLoad[i];
if (image.getBoundingClientRect().top < window.innerHeight && image.getBoundingClientRect().bottom > 0) { if (image.getBoundingClientRect().top < window.innerHeight && image.getBoundingClientRect().bottom > 0) {
if (!image.src && webpSupport) { if (!image.src && webpSupport) {
image.src = image.getAttribute('data-src') + '&e=webp' image.src = `${image.getAttribute('data-src')}&e=webp`;
} else if (!image.src) { } else if (!image.src) {
image.src = image.getAttribute('data-src') image.src = image.getAttribute('data-src');
} }
} }
} }
@ -23,27 +23,24 @@ function loadOnView() {
window.onload = function () { window.onload = function () {
loadOnView(); loadOnView();
let times = document.querySelectorAll('.time'); const times = document.querySelectorAll('.time');
for (let i = 0; i < times.length; i++) { for (let i = 0; i < times.length; i++) {
// Remove milliseconds // Remove milliseconds
const raw = times[i].innerHTML.split('.')[0]; const raw = times[i].innerHTML.split('.')[0];
// Parse YYYY-MM-DD HH:MM:SS to Date object // Parse YYYY-MM-DD HH:MM:SS to Date object
const time = raw.split(' ')[1] const time = raw.split(' ')[1];
const date = raw.split(' ')[0].split('-'); const date = raw.split(' ')[0].split('-');
// Format to YYYY/MM/DD HH:MM:SS // Format to YYYY/MM/DD HH:MM:SS and convert to UTC Date object
let formatted = date[0] + '/' + date[1] + '/' + date[2] + ' ' + time + ' UTC'; const dateTime = new Date(`${date[0]}/${date[1]}/${date[2]} ${time} UTC`);
// Convert to UTC Date object
let dateTime = new Date(formatted);
// Convert to local time // Convert to local time
times[i].innerHTML = dateTime.toLocaleDateString() + ' ' + dateTime.toLocaleTimeString(); times[i].innerHTML = `${dateTime.toLocaleDateString()} ${dateTime.toLocaleTimeString()}`;
} }
// Top Of Page button // Top Of Page button
let topOfPage = document.querySelector('.top-of-page'); const topOfPage = document.querySelector('.top-of-page');
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) { if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) {
topOfPage.classList.add('show'); topOfPage.classList.add('show');
} else { } else {
@ -55,8 +52,7 @@ window.onload = function () {
} }
// Info button // Info button
let infoButton = document.querySelector('.info-button'); const infoButton = document.querySelector('.info-button');
if (infoButton) { if (infoButton) {
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) { if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) {
infoButton.classList.remove('show'); infoButton.classList.remove('show');
@ -65,7 +61,7 @@ window.onload = function () {
} }
infoButton.onclick = function () { infoButton.onclick = function () {
popUpShow('OnlyLegs', popUpShow('OnlyLegs',
'<a href="https://github.com/Fluffy-Bean/onlylegs">V23.04.10</a> ' + '<a href="https://github.com/Fluffy-Bean/onlylegs">v0.1.0</a> ' +
'using <a href="https://phosphoricons.com/">Phosphoricons</a> and Flask.' + 'using <a href="https://phosphoricons.com/">Phosphoricons</a> and Flask.' +
'<br>Made by Fluffy and others with ❤️'); '<br>Made by Fluffy and others with ❤️');
} }
@ -75,7 +71,7 @@ window.onscroll = function () {
loadOnView(); loadOnView();
// Top Of Page button // Top Of Page button
let topOfPage = document.querySelector('.top-of-page'); const topOfPage = document.querySelector('.top-of-page');
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) { if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) {
topOfPage.classList.add('show'); topOfPage.classList.add('show');
} else { } else {
@ -83,8 +79,7 @@ window.onscroll = function () {
} }
// Info button // Info button
let infoButton = document.querySelector('.info-button'); const infoButton = document.querySelector('.info-button');
if (infoButton) { if (infoButton) {
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) { if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) {
infoButton.classList.remove('show'); infoButton.classList.remove('show');

View file

@ -3,6 +3,7 @@ function showLogin() {
// Create elements // Create elements
cancelBtn = document.createElement('button'); cancelBtn = document.createElement('button');
cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('btn-block');
cancelBtn.classList.add('transparent');
cancelBtn.innerHTML = 'nuuuuuuuu'; cancelBtn.innerHTML = 'nuuuuuuuu';
cancelBtn.onclick = popupDissmiss; cancelBtn.onclick = popupDissmiss;
@ -61,9 +62,9 @@ function login(event) {
// AJAX takes control of subby form :3 // AJAX takes control of subby form :3
event.preventDefault(); event.preventDefault();
let formUsername = document.querySelector("#username").value; const formUsername = document.querySelector("#username").value;
let formPassword = document.querySelector("#password").value; const formPassword = document.querySelector("#password").value;
let formRememberMe = document.querySelector("#remember-me").checked; const formRememberMe = document.querySelector("#remember-me").checked;
if (formUsername === "" || formPassword === "") { if (formUsername === "" || formPassword === "") {
addNotification("Please fill in all fields!!!!", 3); addNotification("Please fill in all fields!!!!", 3);
@ -100,6 +101,7 @@ function showRegister() {
// Create buttons // Create buttons
cancelBtn = document.createElement('button'); cancelBtn = document.createElement('button');
cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('btn-block');
cancelBtn.classList.add('transparent');
cancelBtn.innerHTML = 'nuuuuuuuu'; cancelBtn.innerHTML = 'nuuuuuuuu';
cancelBtn.onclick = popupDissmiss; cancelBtn.onclick = popupDissmiss;
@ -156,10 +158,10 @@ function register(event) {
// AJAX takes control of subby form // AJAX takes control of subby form
event.preventDefault(); event.preventDefault();
let formUsername = document.querySelector("#username").value; const formUsername = document.querySelector("#username").value;
let formEmail = document.querySelector("#email").value; const formEmail = document.querySelector("#email").value;
let formPassword = document.querySelector("#password").value; const formPassword = document.querySelector("#password").value;
let formPasswordRepeat = document.querySelector("#password-repeat").value; const formPasswordRepeat = document.querySelector("#password-repeat").value;
if (formUsername === "" || formEmail === "" || formPassword === "" || formPasswordRepeat === "") { if (formUsername === "" || formEmail === "" || formPassword === "" || formPasswordRepeat === "") {
addNotification("Please fill in all fields!!!!", 3); addNotification("Please fill in all fields!!!!", 3);

View file

@ -10,11 +10,11 @@ function addNotification(notificationText, notificationLevel) {
// Create notification element // Create notification element
const notification = document.createElement('div'); const notification = document.createElement('div');
notification.classList.add('sniffle__notification'); notification.classList.add('sniffle__notification');
notification.onclick = function() { notification.onclick = () => {
if (notification) { if (notification) {
notification.classList.add('hide'); notification.classList.add('hide');
setTimeout(function() { setTimeout(() => {
notificationContainer.removeChild(notification); notificationContainer.removeChild(notification);
}, 500); }, 500);
} }
@ -48,15 +48,14 @@ function addNotification(notificationText, notificationLevel) {
// Append notification to container // Append notification to container
notificationContainer.appendChild(notification); notificationContainer.appendChild(notification);
setTimeout(function() { notification.classList.add('show'); }, 5); setTimeout(() => { notification.classList.add('show'); }, 5);
// Remove notification after 5 seconds // Remove notification after 5 seconds
setTimeout(function() { setTimeout(() => {
if (notification) { if (notification) {
notification.classList.add('hide'); notification.classList.add('hide');
setTimeout(() => {
setTimeout(function() { notificationContainer.removeChild(notification);
notificationContainer.removeChild(notification);
}, 500); }, 500);
} }
}, 5000); }, 5000);

View file

@ -28,13 +28,13 @@ function popUpShow(titleText, subtitleText, bodyContent=null, userActions=null)
actionsSelector.appendChild(userActions[i]); actionsSelector.appendChild(userActions[i]);
} }
} else { } else {
actionsSelector.innerHTML = '<button class="btn-block" onclick="popupDissmiss()">Close</button>'; actionsSelector.innerHTML = '<button class="btn-block transparent" onclick="popupDissmiss()">Close</button>';
} }
// Stop scrolling and show popup // Stop scrolling and show popup
document.querySelector("html").style.overflow = "hidden"; document.querySelector("html").style.overflow = "hidden";
popupSelector.style.display = 'block'; popupSelector.style.display = 'block';
setTimeout(function() { popupSelector.classList.add('active') }, 5); // 2ms delay to allow for css transition >:C setTimeout(() => { popupSelector.classList.add('active') }, 5); // 2ms delay to allow for css transition >:C
} }
function popupDissmiss() { function popupDissmiss() {
@ -42,5 +42,5 @@ function popupDissmiss() {
document.querySelector("html").style.overflow = "auto"; document.querySelector("html").style.overflow = "auto";
popupSelector.classList.remove('active'); popupSelector.classList.remove('active');
setTimeout(function() { popupSelector.style.display = 'none'; }, 200); setTimeout(() => { popupSelector.style.display = 'none'; }, 200);
} }

View file

@ -9,23 +9,23 @@ window.addEventListener("drop", (event) => {
// open upload tab // open upload tab
function openUploadTab() { function openUploadTab() {
let uploadTab = document.querySelector(".upload-panel"); const uploadTab = document.querySelector(".upload-panel");
// Stop scrolling and open upload tab // Stop scrolling and open upload tab
document.querySelector("html").style.overflow = "hidden"; document.querySelector("html").style.overflow = "hidden";
uploadTab.style.display = "block"; uploadTab.style.display = "block";
setTimeout(function () { uploadTab.classList.add("open"); }, 5); setTimeout(() => { uploadTab.classList.add("open"); }, 5);
} }
// close upload tab // close upload tab
function closeUploadTab() { function closeUploadTab() {
let uploadTab = document.querySelector(".upload-panel"); const uploadTab = document.querySelector(".upload-panel");
let uploadTabContainer = document.querySelector(".upload-panel .container"); const uploadTabContainer = document.querySelector(".upload-panel .container");
// un-Stop scrolling and close upload tab // un-Stop scrolling and close upload tab
document.querySelector("html").style.overflow = "auto"; document.querySelector("html").style.overflow = "auto";
uploadTab.classList.remove("open"); uploadTab.classList.remove("open");
setTimeout(function () { setTimeout(() => {
uploadTab.style.display = "none"; uploadTab.style.display = "none";
uploadTabContainer.style.transform = ""; uploadTabContainer.style.transform = "";
@ -35,7 +35,7 @@ function closeUploadTab() {
// toggle upload tab // toggle upload tab
function toggleUploadTab() { function toggleUploadTab() {
let uploadTab = document.querySelector(".upload-panel"); const uploadTab = document.querySelector(".upload-panel");
if (uploadTab.classList.contains("open")) { if (uploadTab.classList.contains("open")) {
closeUploadTab(); closeUploadTab();
@ -47,15 +47,15 @@ function toggleUploadTab() {
function tabDragStart(event) { function tabDragStart(event) {
event.preventDefault(); event.preventDefault();
let uploadTab = document.querySelector(".upload-panel .container"); const uploadTab = document.querySelector(".upload-panel .container");
let offset = uploadTab.getBoundingClientRect().y; const offset = uploadTab.getBoundingClientRect().y;
uploadTab.classList.add("dragging"); uploadTab.classList.add("dragging");
document.addEventListener('touchmove', event => { document.addEventListener('touchmove', moving => {
if (uploadTab.classList.contains("dragging")) { if (uploadTab.classList.contains("dragging")) {
if (event.touches[0].clientY - offset >= 0) { if (moving.touches[0].clientY - offset >= 0) {
uploadTab.dataset.lastY = event.touches[0].clientY; uploadTab.dataset.lastY = moving.touches[0].clientY;
} else { } else {
uploadTab.dataset.lastY = offset; uploadTab.dataset.lastY = offset;
} }
@ -67,7 +67,7 @@ function tabDragStart(event) {
function tabDragStopped(event) { function tabDragStopped(event) {
event.preventDefault(); event.preventDefault();
let uploadTab = document.querySelector(".upload-panel .container"); const uploadTab = document.querySelector(".upload-panel .container");
uploadTab.classList.remove("dragging"); uploadTab.classList.remove("dragging");
@ -76,7 +76,7 @@ function tabDragStopped(event) {
} else { } else {
uploadTab.style.transition = "transform 0.25s cubic-bezier(0.76, 0, 0.17, 1)"; uploadTab.style.transition = "transform 0.25s cubic-bezier(0.76, 0, 0.17, 1)";
uploadTab.style.transform = "translateY(0px)"; uploadTab.style.transform = "translateY(0px)";
setTimeout(function () { uploadTab.style.transition = ""; }, 250); setTimeout(() => { uploadTab.style.transition = ""; }, 250);
} }
} }
@ -85,16 +85,16 @@ function tabDragStopped(event) {
function fileActivate(event) { function fileActivate(event) {
event.preventDefault() event.preventDefault()
let fileDrop = document.querySelector('.fileDrop-block'); const fileDrop = document.querySelector('.fileDrop-block');
let fileDropTitle = fileDrop.querySelector('.status'); const fileDropTitle = fileDrop.querySelector('.status');
fileDrop.classList.remove('error'); fileDrop.classList.remove('error');
fileDrop.classList.add('edging'); fileDrop.classList.add('edging');
fileDropTitle.innerHTML = 'Drop to upload!'; fileDropTitle.innerHTML = 'Drop to upload!';
} }
function fileDefault() { function fileDefault() {
let fileDrop = document.querySelector('.fileDrop-block'); const fileDrop = document.querySelector('.fileDrop-block');
let fileDropTitle = fileDrop.querySelector('.status'); const fileDropTitle = fileDrop.querySelector('.status');
fileDrop.classList.remove('error'); fileDrop.classList.remove('error');
fileDrop.classList.remove('edging'); fileDrop.classList.remove('edging');
@ -104,8 +104,8 @@ function fileDefault() {
function fileDropHandle(event) { function fileDropHandle(event) {
event.preventDefault() event.preventDefault()
let fileDrop = document.querySelector('.fileDrop-block'); const fileDrop = document.querySelector('.fileDrop-block');
let fileUpload = fileDrop.querySelector('#file'); const fileUpload = fileDrop.querySelector('#file');
fileUpload.files = event.dataTransfer.files; fileUpload.files = event.dataTransfer.files;
@ -114,9 +114,9 @@ function fileDropHandle(event) {
} }
function fileChanged() { function fileChanged() {
let dropBlock = document.querySelector('.fileDrop-block'); const dropBlock = document.querySelector('.fileDrop-block');
let dropBlockStatus = dropBlock.querySelector('.status'); const dropBlockStatus = dropBlock.querySelector('.status');
let dropBlockInput = dropBlock.querySelector('#file'); const dropBlockInput = dropBlock.querySelector('#file');
if (dropBlockInput.value !== "") { if (dropBlockInput.value !== "") {
dropBlock.classList.add('active'); dropBlock.classList.add('active');
@ -127,12 +127,12 @@ function fileChanged() {
} }
function clearUpload() { function clearUpload() {
let fileDrop = document.querySelector('#uploadForm'); const fileDrop = document.querySelector('#uploadForm');
let fileUpload = fileDrop.querySelector('#file'); const fileUpload = fileDrop.querySelector('#file');
let fileAlt = fileDrop.querySelector('#alt'); const fileAlt = fileDrop.querySelector('#alt');
let fileDescription = fileDrop.querySelector('#description'); const fileDescription = fileDrop.querySelector('#description');
let fileTags = fileDrop.querySelector('#tags'); const fileTags = fileDrop.querySelector('#tags');
fileUpload.value = ""; fileUpload.value = "";
fileAlt.value = ""; fileAlt.value = "";
@ -169,21 +169,21 @@ function clearUpload() {
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
// Function to upload images // Function to upload images
let uploadTab = document.querySelector(".upload-panel"); const uploadTab = document.querySelector(".upload-panel");
if (!uploadTab) { return; } // If upload tab doesn't exist, don't run this code :3 if (!uploadTab) { return; } // If upload tab doesn't exist, don't run this code :3
let uploadTabDrag = uploadTab.querySelector("#dragIndicator"); const uploadTabDrag = uploadTab.querySelector("#dragIndicator");
let uploadForm = uploadTab.querySelector('#uploadForm'); const uploadForm = uploadTab.querySelector('#uploadForm');
// let jobList = document.querySelector(".upload-jobs"); // let jobList = document.querySelector(".upload-jobs");
let fileDrop = uploadForm.querySelector('.fileDrop-block'); const fileDrop = uploadForm.querySelector('.fileDrop-block');
let fileDropTitle = fileDrop.querySelector('.status'); const fileDropTitle = fileDrop.querySelector('.status');
let fileUpload = fileDrop.querySelector('#file'); const fileUpload = fileDrop.querySelector('#file');
let fileAlt = uploadForm.querySelector('#alt'); const fileAlt = uploadForm.querySelector('#alt');
let fileDescription = uploadForm.querySelector('#description'); const fileDescription = uploadForm.querySelector('#description');
let fileTags = uploadForm.querySelector('#tags'); const fileTags = uploadForm.querySelector('#tags');
clearUpload(); clearUpload();
@ -221,7 +221,7 @@ document.addEventListener('DOMContentLoaded', () => {
} }
// Make form // Make form
let formData = new FormData(); const formData = new FormData();
formData.append("file", fileUpload.files[0]); formData.append("file", fileUpload.files[0]);
formData.append("alt", fileAlt.value); formData.append("alt", fileAlt.value);

View file

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View file

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -57,7 +57,7 @@
width: 100% width: 100%
height: 100% height: 100%
background: linear-gradient(to right, RGB($primary), transparent) background: linear-gradient(to right, RGB($bg-100), transparent)
z-index: +1 z-index: +1

View file

@ -1,11 +1,12 @@
@mixin btn-block($color) @mixin btn-block($color)
background-color: RGBA($color, 0.1)
color: RGB($color) color: RGB($color)
box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2)
&:hover, &:focus-visible &:hover, &:focus-visible
background-color: RGBA($color, 0.1) background-color: RGBA($color, 0.15)
color: RGB($color) color: RGB($color)
box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($color, 0.2) // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($color, 0.2)
.btn-block .btn-block
@ -29,7 +30,7 @@
color: RGB($white) color: RGB($white)
border: none border: none
border-radius: $rad-inner border-radius: $rad-inner
box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2)
outline: none outline: none
cursor: pointer cursor: pointer
@ -37,23 +38,24 @@
&:hover, &:focus-visible &:hover, &:focus-visible
background-color: RGBA($white, 0.2) background-color: RGBA($white, 0.2)
box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3) // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3)
&.transparent
background-color: transparent
&:hover, &:focus-visible
text-decoration: underline
&.primary &.primary
@include btn-block($primary) @include btn-block($primary)
&.critical &.critical
@include btn-block($critical) @include btn-block($critical)
&.warning &.warning
@include btn-block($warning) @include btn-block($warning)
&.success &.success
@include btn-block($success) @include btn-block($success)
&.info &.info
@include btn-block($info) @include btn-block($info)
&.black &.black
@include btn-block($black) @include btn-block($black)
@ -94,7 +96,7 @@
border: none border: none
border-bottom: 3px solid RGBA($white, 0.1) border-bottom: 3px solid RGBA($white, 0.1)
border-radius: $rad-inner border-radius: $rad-inner
box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2)
outline: none outline: none
cursor: pointer cursor: pointer
@ -134,7 +136,7 @@
color: RGB($white) color: RGB($white)
border: none border: none
border-radius: $rad-inner border-radius: $rad-inner
box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2)
outline: none outline: none
cursor: pointer cursor: pointer
@ -157,17 +159,17 @@
&:hover, &:focus-visible &:hover, &:focus-visible
background-color: RGBA($white, 0.2) background-color: RGBA($white, 0.2)
color: RGB($white) color: RGB($white)
box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3) // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3)
&.active &.active
background-color: RGBA($primary, 0.2) background-color: RGBA($primary, 0.2)
color: RGB($primary) color: RGB($primary)
box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($primary, 0.3) // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($primary, 0.3)
&.edging &.edging
background-color: RGBA($white, 0.2) background-color: RGBA($white, 0.2)
color: RGB($white) color: RGB($white)
box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3) // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3)
input input
display: none // So it doesnt get in the way of the drop as that breaks things display: none // So it doesnt get in the way of the drop as that breaks things
@ -175,4 +177,4 @@
&.error &.error
background-color: RGBA($critical, 0.2) background-color: RGBA($critical, 0.2)
color: RGB($critical) color: RGB($critical)
box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($critical, 0.3) // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($critical, 0.3)

View file

@ -18,7 +18,7 @@
background-color: RGB($bg-200) background-color: RGB($bg-200)
border-radius: $rad border-radius: $rad
box-shadow: 0 1px 0 RGB($bg-100), 0 -1px 0 RGB($bg-300) // box-shadow: 0 1px 0 RGB($bg-100), 0 -1px 0 RGB($bg-300)
.pill-text .pill-text
margin: 0 margin: 0

View file

@ -25,9 +25,9 @@
.pop-up-wrapper .pop-up-wrapper
margin: 0 margin: 0
padding: 0 padding: 1rem
width: 621px width: 460px
height: auto height: auto
position: absolute position: absolute
@ -46,8 +46,8 @@
transition: transform 0.2s $animation-smooth transition: transform 0.2s $animation-smooth
.pop-up-header .pop-up-header
margin: 0 margin: 0 0 0.5rem 0
padding: 1rem padding: 0
width: 100% width: 100%
height: auto height: auto
@ -102,17 +102,6 @@
&:hover &:hover
text-decoration: underline text-decoration: underline
img
margin: auto
padding: 0
width: auto
height: auto
max-width: 100%
max-height: 40vh
border-radius: $rad-inner
form form
margin: 0 margin: 0
padding: 0 padding: 0
@ -128,7 +117,7 @@
.pop-up-controlls .pop-up-controlls
margin: 0 margin: 0
padding: 0.25rem padding: 0
width: 100% width: 100%
height: auto height: auto
@ -136,9 +125,9 @@
display: flex display: flex
flex-direction: row flex-direction: row
justify-content: flex-end justify-content: flex-end
gap: 0.25rem gap: 0.5rem
background-color: RGB($bg-100) // background-color: RGB($bg-100)
&.active &.active
opacity: 1 opacity: 1
@ -158,8 +147,9 @@
img img
max-height: 50vh max-height: 50vh
.pop-up-controlls button .pop-up-controlls
width: 100% button
width: 100%
&.active &.active
opacity: 1 opacity: 1

View file

@ -66,11 +66,10 @@ $breakpoint: 800px
--success: var(--green) --success: var(--green)
--info: var(--blue) --info: var(--blue)
--rad: 6px --rad: 8px
--rad-inner: calc(var(--rad) / 2) --rad-inner: calc(var(--rad) / 2)
--animation-smooth: cubic-bezier(0.76, 0, 0.17, 1) --animation-smooth: cubic-bezier(0.76, 0, 0.17, 1)
--animation-bounce: cubic-bezier(.68,-0.55,.27,1.55) --animation-bounce: cubic-bezier(.68,-0.55,.27,1.55)
--breakpoint: 800px --breakpoint: 800px

View file

@ -19,6 +19,7 @@
function groupDelete() { function groupDelete() {
cancelBtn = document.createElement('button'); cancelBtn = document.createElement('button');
cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('btn-block');
cancelBtn.classList.add('transparent');
cancelBtn.innerHTML = 'AAAAAAAAAA'; cancelBtn.innerHTML = 'AAAAAAAAAA';
cancelBtn.onclick = popupDissmiss; cancelBtn.onclick = popupDissmiss;
@ -79,6 +80,7 @@
// Create elements // Create elements
cancelBtn = document.createElement('button'); cancelBtn = document.createElement('button');
cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('btn-block');
cancelBtn.classList.add('transparent');
cancelBtn.innerHTML = 'go baaaaack'; cancelBtn.innerHTML = 'go baaaaack';
cancelBtn.onclick = popupDissmiss; cancelBtn.onclick = popupDissmiss;

View file

@ -31,6 +31,7 @@
function imageDelete() { function imageDelete() {
cancelBtn = document.createElement('button'); cancelBtn = document.createElement('button');
cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('btn-block');
cancelBtn.classList.add('transparent');
cancelBtn.innerHTML = 'nuuuuuuuu'; cancelBtn.innerHTML = 'nuuuuuuuu';
cancelBtn.onclick = popupDissmiss; cancelBtn.onclick = popupDissmiss;

View file

@ -11,6 +11,7 @@
// Create elements // Create elements
cancelBtn = document.createElement('button'); cancelBtn = document.createElement('button');
cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('btn-block');
cancelBtn.classList.add('transparent');
cancelBtn.innerHTML = 'nuuuuuuuu'; cancelBtn.innerHTML = 'nuuuuuuuu';
cancelBtn.onclick = popupDissmiss; cancelBtn.onclick = popupDissmiss;

View file

@ -5,9 +5,9 @@ sounds more limiting that it actually is in this gallery
""" """
from flask import Blueprint, render_template, url_for from flask import Blueprint, render_template, url_for
from gallery.models import Post, User, GroupJunction, Group from onlylegs.models import Post, User, GroupJunction, Group
from gallery.extensions import db from onlylegs.extensions import db
from gallery.utils import contrast from onlylegs.utils import contrast
blueprint = Blueprint("group", __name__, url_prefix="/group") blueprint = Blueprint("group", __name__, url_prefix="/group")

View file

@ -3,8 +3,8 @@ Onlylegs - Image View
""" """
from math import ceil from math import ceil
from flask import Blueprint, render_template, url_for, current_app from flask import Blueprint, render_template, url_for, current_app
from gallery.models import Post, GroupJunction, Group from onlylegs.models import Post, GroupJunction, Group
from gallery.extensions import db from onlylegs.extensions import db
blueprint = Blueprint("image", __name__, url_prefix="/image") blueprint = Blueprint("image", __name__, url_prefix="/image")

View file

@ -6,7 +6,7 @@ from math import ceil
from flask import Blueprint, render_template, request, current_app from flask import Blueprint, render_template, request, current_app
from werkzeug.exceptions import abort from werkzeug.exceptions import abort
from gallery.models import Post from onlylegs.models import Post
blueprint = Blueprint("gallery", __name__) blueprint = Blueprint("gallery", __name__)

View file

@ -5,7 +5,7 @@ from flask import Blueprint, render_template, request
from werkzeug.exceptions import abort from werkzeug.exceptions import abort
from flask_login import current_user from flask_login import current_user
from gallery.models import Post, User from onlylegs.models import Post, User
blueprint = Blueprint("profile", __name__, url_prefix="/profile") blueprint = Blueprint("profile", __name__, url_prefix="/profile")

100
poetry.lock generated
View file

@ -24,14 +24,14 @@ tz = ["python-dateutil"]
[[package]] [[package]]
name = "astroid" name = "astroid"
version = "2.15.2" version = "2.15.3"
description = "An abstract syntax tree for Python with inference support." description = "An abstract syntax tree for Python with inference support."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7.2" python-versions = ">=3.7.2"
files = [ files = [
{file = "astroid-2.15.2-py3-none-any.whl", hash = "sha256:dea89d9f99f491c66ac9c04ebddf91e4acf8bd711722175fe6245c0725cc19bb"}, {file = "astroid-2.15.3-py3-none-any.whl", hash = "sha256:f11e74658da0f2a14a8d19776a8647900870a63de71db83713a8e77a6af52662"},
{file = "astroid-2.15.2.tar.gz", hash = "sha256:6e61b85c891ec53b07471aec5878f4ac6446a41e590ede0f2ce095f39f7d49dd"}, {file = "astroid-2.15.3.tar.gz", hash = "sha256:44224ad27c54d770233751315fa7f74c46fa3ee0fab7beef1065f99f09897efe"},
] ]
[package.dependencies] [package.dependencies]
@ -42,6 +42,56 @@ wrapt = [
{version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, {version = ">=1.14,<2", markers = "python_version >= \"3.11\""},
] ]
[[package]]
name = "black"
version = "23.3.0"
description = "The uncompromising code formatter."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
{file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
{file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
{file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
{file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
{file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
{file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
{file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
{file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
{file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
{file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
{file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
{file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
{file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
{file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
{file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
{file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
{file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
{file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
{file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
{file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
{file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
{file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
{file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
{file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]] [[package]]
name = "brotli" name = "brotli"
version = "1.0.9" version = "1.0.9"
@ -431,14 +481,14 @@ tornado = ["tornado (>=0.2)"]
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "6.2.1" version = "6.5.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "importlib_metadata-6.2.1-py3-none-any.whl", hash = "sha256:f65e478a7c2177bd19517a3a15dac094d253446d8690c5f3e71e735a04312374"}, {file = "importlib_metadata-6.5.0-py3-none-any.whl", hash = "sha256:03ba783c3a2c69d751b109fc0c94a62c51f581b3d6acf8ed1331b6d5729321ff"},
{file = "importlib_metadata-6.2.1.tar.gz", hash = "sha256:5a66966b39ff1c14ef5b2d60c1d842b0141fefff0f4cc6365b4bc9446c652807"}, {file = "importlib_metadata-6.5.0.tar.gz", hash = "sha256:7a8bdf1bc3a726297f5cfbc999e6e7ff6b4fa41b26bba4afc580448624460045"},
] ]
[package.dependencies] [package.dependencies]
@ -680,6 +730,42 @@ files = [
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
] ]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "main"
optional = false
python-versions = ">=3.5"
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
[[package]]
name = "packaging"
version = "23.1"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
]
[[package]]
name = "pathspec"
version = "0.11.1"
description = "Utility library for gitignore style pattern matching of file paths."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
]
[[package]] [[package]]
name = "pillow" name = "pillow"
version = "9.5.0" version = "9.5.0"
@ -1136,4 +1222,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "88387c49c901feebd4685ee75f6b79c0bbc8cc9c1a64798cd0394b140e165603" content-hash = "7309b76a75c6ab11febc8d91b3e2c9bfe0adb656f06dcae9b602ce5dea1db35e"

View file

@ -1,10 +1,10 @@
[tool.poetry] [tool.poetry]
name = "onlylegs" name = "onlylegs"
version = "23.04.10" version = "0.1.0"
description = "Gallery built for fast and simple image management" description = "Gallery built for fast and simple image management"
authors = ["Fluffy-Bean <michal-gdula@protonmail.com>"] authors = ["Fluffy-Bean <michal-gdula@protonmail.com>"]
license = "MIT" license = "MIT"
readme = ".github/README.md" readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.8" python = "^3.8"
@ -21,10 +21,11 @@ pyyaml = "^6.0"
colorthief = "^0.2.1" colorthief = "^0.2.1"
Pillow = "^9.4.0" Pillow = "^9.4.0"
platformdirs = "^3.0.0" platformdirs = "^3.0.0"
pylint = "^2.16.3"
libsass = "^0.22.0" libsass = "^0.22.0"
jsmin = "^3.0.1" jsmin = "^3.0.1"
cssmin = "^0.2.0" cssmin = "^0.2.0"
pylint = "^2.16.3"
black = "^23.3.0"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]

4
run.py
View file

@ -15,7 +15,7 @@ print(
#+# #+# #+# #+#+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+#+# #+# #+# #+# #+# #+# #+# #+# #+#
######## ### #### ########## ### ########## ######### ######### ######## ######## ### #### ########## ### ########## ######### ######### ########
Created by Fluffy Bean - Version 23.04.10 Created by Fluffy Bean - Version 0.1.0
""" """
) )
@ -25,7 +25,7 @@ Configuration()
if DEBUG: if DEBUG:
from gallery import create_app from onlylegs import create_app
create_app().run(host=ADDRESS, port=PORT, debug=True, threaded=True) create_app().run(host=ADDRESS, port=PORT, debug=True, threaded=True)
else: else:

View file

@ -10,7 +10,8 @@ class OnlyLegs(Application):
Gunicorn application Gunicorn application
""" """
def __init__(self, options={}): # pylint: disable=W0102, W0231 # TODO: Make this not shit, thanks
def __init__(self, options={}): # skipcq: PYL-W0231 # pylint: disable=W0231
self.usage = None self.usage = None
self.callable = None self.callable = None
self.options = options self.options = options
@ -27,8 +28,8 @@ class OnlyLegs(Application):
return cfg return cfg
@staticmethod @staticmethod
def prog(): # pylint: disable=C0116, E0202 def prog(): # skipcq: PYL-E0202 # pylint: disable=E0202, C0116
return "OnlyLegs" return "OnlyLegs"
def load(self): def load(self):
return util.import_app("gallery:create_app()") return util.import_app("onlylegs:create_app()")