mirror of
https://github.com/Derpy-Leggies/OnlyLegs.git
synced 2025-06-29 03:26:16 +00:00
Bundle JS into a compact format
Run file checks on startup Fix visual bugs in Sass
This commit is contained in:
parent
e3a0eaf60b
commit
e6d289ed64
16 changed files with 283 additions and 221 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -1,9 +1,6 @@
|
||||||
# Remove all development files
|
gallery/static/theme
|
||||||
gallery/user/logs/*
|
gallery/static/.webassets-cache
|
||||||
gallery/user/uploads/*
|
gallery/static/gen
|
||||||
gallery/user/conf.yml
|
|
||||||
gallery/user/conf.json
|
|
||||||
gallery/static/theme/*
|
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
|
@ -10,12 +10,12 @@ Created by Fluffy Bean - Version 23.03.09
|
||||||
|
|
||||||
# Import system modules
|
# Import system modules
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# Flask
|
# Flask
|
||||||
from flask_compress import Compress
|
from flask_compress import Compress
|
||||||
from flask_caching import Cache
|
from flask_caching import Cache
|
||||||
|
from flask_assets import Environment, Bundle
|
||||||
from flask import Flask, render_template
|
from flask import Flask, render_template
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
@ -24,57 +24,32 @@ import platformdirs
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from . import theme_manager
|
from . import theme_manager
|
||||||
|
|
||||||
|
|
||||||
USER_DIR = platformdirs.user_config_dir('onlylegs')
|
|
||||||
INSTANCE_PATH = os.path.join(USER_DIR, 'instance')
|
|
||||||
|
|
||||||
|
|
||||||
# Check if any of the required files are missing
|
|
||||||
if not os.path.exists(platformdirs.user_config_dir('onlylegs')):
|
|
||||||
from . import setup
|
from . import setup
|
||||||
|
|
||||||
|
|
||||||
|
# Run setup checks
|
||||||
setup.SetupApp()
|
setup.SetupApp()
|
||||||
|
|
||||||
|
USER_DIR = platformdirs.user_config_dir('onlylegs')
|
||||||
|
|
||||||
# Get environment variables
|
# Get environment variables
|
||||||
if os.path.exists(os.path.join(USER_DIR, '.env')):
|
|
||||||
load_dotenv(os.path.join(USER_DIR, '.env'))
|
load_dotenv(os.path.join(USER_DIR, '.env'))
|
||||||
print("Loaded environment variables")
|
print("Loaded environment variables")
|
||||||
else:
|
|
||||||
print("No environment variables found!")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
# Get config file
|
# Get config file
|
||||||
if os.path.exists(os.path.join(USER_DIR, 'conf.yml')):
|
|
||||||
with open(os.path.join(USER_DIR, 'conf.yml'), encoding='utf-8') as f:
|
with open(os.path.join(USER_DIR, 'conf.yml'), encoding='utf-8') as f:
|
||||||
conf = yaml.load(f, Loader=yaml.FullLoader)
|
conf = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
print("Loaded gallery config")
|
print("Loaded gallery config")
|
||||||
else:
|
|
||||||
print("No config file found!")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Setup the logging config
|
|
||||||
LOGS_PATH = os.path.join(platformdirs.user_config_dir('onlylegs'), 'logs')
|
|
||||||
|
|
||||||
if not os.path.isdir(LOGS_PATH):
|
|
||||||
os.mkdir(LOGS_PATH)
|
|
||||||
|
|
||||||
logging.getLogger('werkzeug').disabled = True
|
|
||||||
logging.basicConfig(
|
|
||||||
filename=os.path.join(LOGS_PATH, 'only.log'),
|
|
||||||
level=logging.INFO,
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S',
|
|
||||||
format='%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s',
|
|
||||||
encoding='utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def create_app(test_config=None):
|
def create_app(test_config=None):
|
||||||
"""
|
"""
|
||||||
Create and configure the main app
|
Create and configure the main app
|
||||||
"""
|
"""
|
||||||
app = Flask(__name__,instance_path=INSTANCE_PATH)
|
app = Flask(__name__,instance_path=os.path.join(USER_DIR, 'instance'))
|
||||||
compress = Compress()
|
assets = Environment()
|
||||||
cache = Cache(config={'CACHE_TYPE': 'SimpleCache', 'CACHE_DEFAULT_TIMEOUT': 69})
|
cache = Cache(config={'CACHE_TYPE': 'SimpleCache', 'CACHE_DEFAULT_TIMEOUT': 69})
|
||||||
|
compress = Compress()
|
||||||
|
|
||||||
# App configuration
|
# App configuration
|
||||||
app.config.from_mapping(
|
app.config.from_mapping(
|
||||||
|
@ -102,6 +77,11 @@ def create_app(test_config=None):
|
||||||
theme_manager.CompileTheme('default', app.root_path)
|
theme_manager.CompileTheme('default', app.root_path)
|
||||||
|
|
||||||
|
|
||||||
|
# Bundle JS files
|
||||||
|
js = Bundle('js/*.js', output='gen/packed.js')
|
||||||
|
assets.register('js_all', js)
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(405)
|
@app.errorhandler(405)
|
||||||
def method_not_allowed(err):
|
def method_not_allowed(err):
|
||||||
error = '405'
|
error = '405'
|
||||||
|
@ -153,6 +133,10 @@ def create_app(test_config=None):
|
||||||
from . import api
|
from . import api
|
||||||
app.register_blueprint(api.blueprint)
|
app.register_blueprint(api.blueprint)
|
||||||
|
|
||||||
compress.init_app(app)
|
|
||||||
|
logging.info('Gallery started successfully!')
|
||||||
|
|
||||||
|
assets.init_app(app)
|
||||||
cache.init_app(app)
|
cache.init_app(app)
|
||||||
|
compress.init_app(app)
|
||||||
return app
|
return app
|
||||||
|
|
|
@ -5,6 +5,7 @@ Runs when the app detects that there is no user directory
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import platformdirs
|
import platformdirs
|
||||||
|
import logging
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
USER_DIR = platformdirs.user_config_dir('onlylegs')
|
USER_DIR = platformdirs.user_config_dir('onlylegs')
|
||||||
|
@ -19,6 +20,8 @@ class SetupApp:
|
||||||
"""
|
"""
|
||||||
print("Running setup...")
|
print("Running setup...")
|
||||||
|
|
||||||
|
self.requires_restart = False
|
||||||
|
|
||||||
if not os.path.exists(USER_DIR):
|
if not os.path.exists(USER_DIR):
|
||||||
self.make_dir()
|
self.make_dir()
|
||||||
if not os.path.exists(os.path.join(USER_DIR, '.env')):
|
if not os.path.exists(os.path.join(USER_DIR, '.env')):
|
||||||
|
@ -26,6 +29,13 @@ class SetupApp:
|
||||||
if not os.path.exists(os.path.join(USER_DIR, 'conf.yml')):
|
if not os.path.exists(os.path.join(USER_DIR, 'conf.yml')):
|
||||||
self.make_yaml()
|
self.make_yaml()
|
||||||
|
|
||||||
|
self.logging_config()
|
||||||
|
|
||||||
|
if self.requires_restart:
|
||||||
|
print("WARNING: You need to restart and edit the config files before running the app again!")
|
||||||
|
print("You can find the config files at:", USER_DIR)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
def make_dir(self):
|
def make_dir(self):
|
||||||
"""
|
"""
|
||||||
Create the user directory
|
Create the user directory
|
||||||
|
@ -37,7 +47,7 @@ class SetupApp:
|
||||||
print("Created user directory at:", USER_DIR)
|
print("Created user directory at:", USER_DIR)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("Error creating user directory:", err)
|
print("Error creating user directory:", err)
|
||||||
sys.exit(1) # exit with error code
|
sys.exit(1)
|
||||||
|
|
||||||
def make_env(self):
|
def make_env(self):
|
||||||
"""
|
"""
|
||||||
|
@ -55,7 +65,7 @@ class SetupApp:
|
||||||
print("Error creating environment variables:", err)
|
print("Error creating environment variables:", err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
print("Generated default .env file. EDIT IT BEFORE RUNNING THE APP AGAIN!")
|
print("Generated default .env file, please edit!")
|
||||||
|
|
||||||
def make_yaml(self):
|
def make_yaml(self):
|
||||||
"""
|
"""
|
||||||
|
@ -95,4 +105,19 @@ class SetupApp:
|
||||||
print("Error creating default gallery config:", err)
|
print("Error creating default gallery config:", err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
print("Generated default YAML config. EDIT IT BEFORE RUNNING THE APP AGAIN!")
|
print("Generated default YAML config, please edit!")
|
||||||
|
|
||||||
|
def logging_config(self):
|
||||||
|
LOGS_PATH = os.path.join(platformdirs.user_config_dir('onlylegs'), 'logs')
|
||||||
|
|
||||||
|
if not os.path.isdir(LOGS_PATH):
|
||||||
|
os.mkdir(LOGS_PATH)
|
||||||
|
print("Created logs directory at:", LOGS_PATH)
|
||||||
|
|
||||||
|
logging.getLogger('werkzeug').disabled = True
|
||||||
|
logging.basicConfig(
|
||||||
|
filename=os.path.join(LOGS_PATH, 'only.log'),
|
||||||
|
level=logging.INFO,
|
||||||
|
datefmt='%Y-%m-%d %H:%M:%S',
|
||||||
|
format='%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s',
|
||||||
|
encoding='utf-8')
|
|
@ -1,63 +1,37 @@
|
||||||
function imgFade(obj) {
|
// fade in images
|
||||||
$(obj).animate({opacity: 1}, 250);
|
function imgFade(obj, time = 250) {
|
||||||
|
$(obj).animate({ opacity: 1 }, time);
|
||||||
}
|
}
|
||||||
|
// https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
|
||||||
let times = document.getElementsByClassName('time');
|
function colourContrast(bgColor, lightColor, darkColor, threshold = 0.179) {
|
||||||
for (let i = 0; i < times.length; i++) {
|
var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;
|
||||||
// Remove milliseconds
|
var r = parseInt(color.substring(0, 2), 16); // hexToR
|
||||||
const raw = times[i].innerHTML.split('.')[0];
|
var g = parseInt(color.substring(2, 4), 16); // hexToG
|
||||||
|
var b = parseInt(color.substring(4, 6), 16); // hexToB
|
||||||
// Parse YYYY-MM-DD HH:MM:SS to Date object
|
var uicolors = [r / 255, g / 255, b / 255];
|
||||||
const time = raw.split(' ')[1]
|
var c = uicolors.map((col) => {
|
||||||
const date = raw.split(' ')[0].split('-');
|
if (col <= 0.03928) {
|
||||||
|
return col / 12.92;
|
||||||
// Format to YYYY/MM/DD HH:MM:SS
|
|
||||||
let formatted = date[0] + '/' + date[1] + '/' + date[2] + ' ' + time + ' UTC';
|
|
||||||
|
|
||||||
// Convert to UTC Date object
|
|
||||||
let dateTime = new Date(formatted);
|
|
||||||
|
|
||||||
// Convert to local time
|
|
||||||
times[i].innerHTML = dateTime.toLocaleDateString() + ' ' + dateTime.toLocaleTimeString();
|
|
||||||
}
|
}
|
||||||
|
return Math.pow((col + 0.055) / 1.055, 2.4);
|
||||||
let images = document.querySelectorAll('.gallery-item img');
|
});
|
||||||
|
var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);
|
||||||
|
return (L > threshold) ? darkColor : lightColor;
|
||||||
|
}
|
||||||
|
// Lazy load images when they are in view
|
||||||
function loadOnView() {
|
function loadOnView() {
|
||||||
for (let i = 0; i < images.length; i++) {
|
let lazyLoad = document.querySelectorAll('#lazy-load');
|
||||||
let image = images[i];
|
|
||||||
|
for (let i = 0; i < lazyLoad.length; i++) {
|
||||||
|
let 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) {
|
if (!image.src) {
|
||||||
image.src = `/api/uploads/${image.getAttribute('data-src')}?w=500&h=500`
|
image.src = `/api/uploads/${image.getAttribute('data-src')}?w=400&h=400`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (images.length > 0) {
|
// Function to upload images
|
||||||
window.onload = function() {
|
|
||||||
loadOnView();
|
|
||||||
};
|
|
||||||
window.onscroll = function() {
|
|
||||||
loadOnView();
|
|
||||||
};
|
|
||||||
window.onresize = function() {
|
|
||||||
loadOnView();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
document.onscroll = function() {
|
|
||||||
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) {
|
|
||||||
document.querySelector('.jumpUp').classList = 'jumpUp jumpUp--show';
|
|
||||||
} else {
|
|
||||||
document.querySelector('.jumpUp').classList = 'jumpUp';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.querySelector('.jumpUp').onclick = function() {
|
|
||||||
document.body.scrollTop = 0;
|
|
||||||
document.documentElement.scrollTop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function uploadFile() {
|
function uploadFile() {
|
||||||
// AJAX takes control of subby form
|
// AJAX takes control of subby form
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -146,7 +120,7 @@ function uploadFile(){
|
||||||
$("#tags").val("");
|
$("#tags").val("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// open upload tab
|
||||||
function openUploadTab() {
|
function openUploadTab() {
|
||||||
// Stop scrolling
|
// Stop scrolling
|
||||||
document.querySelector("html").style.overflow = "hidden";
|
document.querySelector("html").style.overflow = "hidden";
|
||||||
|
@ -159,7 +133,7 @@ function openUploadTab() {
|
||||||
uploadTab.classList.add("open");
|
uploadTab.classList.add("open");
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
// close upload tab
|
||||||
function closeUploadTab() {
|
function closeUploadTab() {
|
||||||
// un-Stop scrolling
|
// un-Stop scrolling
|
||||||
document.querySelector("html").style.overflow = "auto";
|
document.querySelector("html").style.overflow = "auto";
|
||||||
|
@ -172,7 +146,7 @@ function closeUploadTab() {
|
||||||
uploadTab.style.display = "none";
|
uploadTab.style.display = "none";
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
|
// toggle upload tab
|
||||||
function toggleUploadTab() {
|
function toggleUploadTab() {
|
||||||
if (document.querySelector(".upload-panel").classList.contains("open")) {
|
if (document.querySelector(".upload-panel").classList.contains("open")) {
|
||||||
closeUploadTab();
|
closeUploadTab();
|
||||||
|
@ -180,7 +154,7 @@ function toggleUploadTab() {
|
||||||
openUploadTab();
|
openUploadTab();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Function to show login
|
||||||
function showLogin() {
|
function showLogin() {
|
||||||
popUpShow(
|
popUpShow(
|
||||||
'idk what to put here, just login please',
|
'idk what to put here, just login please',
|
||||||
|
@ -192,31 +166,23 @@ function showLogin() {
|
||||||
</form>'
|
</form>'
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
function showRegister() {
|
// Function to login
|
||||||
popUpShow(
|
|
||||||
'Who are you?',
|
|
||||||
'Already have an account? <span class="pop-up__link" onclick="showLogin()">Login!</span>',
|
|
||||||
'<button class="pop-up__btn pop-up__btn-primary-fill" form="registerForm" type="submit">Register</button>',
|
|
||||||
'<form id="registerForm" onsubmit="return register(event)">\
|
|
||||||
<input class="pop-up__input" type="text" placeholder="Namey" id="username"/>\
|
|
||||||
<input class="pop-up__input" type="text" placeholder="E mail!" id="email"/>\
|
|
||||||
<input class="pop-up__input" type="password" placeholder="Passywassy" id="password"/>\
|
|
||||||
<input class="pop-up__input" type="password" placeholder="Passywassy again!" id="password-repeat"/>\
|
|
||||||
</form>'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
function login(event) {
|
function login(event) {
|
||||||
// AJAX takes control of subby form
|
// AJAX takes control of subby form :3
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if ($("#username").val() === "" || $("#password").val() === "") {
|
let formUsername = document.querySelector("#username").value;
|
||||||
addNotification("Please fill in all fields", 3);
|
let formPassword = document.querySelector("#password").value;
|
||||||
} else {
|
|
||||||
|
if (formUsername === "" || formPassword === "") {
|
||||||
|
addNotification("Please fill in all fields!!!!", 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make form
|
// Make form
|
||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
formData.append("username", $("#username").val());
|
formData.append("username", formUsername);
|
||||||
formData.append("password", $("#password").val());
|
formData.append("password", formPassword);
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/auth/login',
|
url: '/auth/login',
|
||||||
|
@ -242,20 +208,41 @@ function login(event) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
// Function to show register
|
||||||
|
function showRegister() {
|
||||||
|
popUpShow(
|
||||||
|
'Who are you?',
|
||||||
|
'Already have an account? <span class="pop-up__link" onclick="showLogin()">Login!</span>',
|
||||||
|
'<button class="pop-up__btn pop-up__btn-primary-fill" form="registerForm" type="submit">Register</button>',
|
||||||
|
'<form id="registerForm" onsubmit="return register(event)">\
|
||||||
|
<input class="pop-up__input" type="text" placeholder="Namey" id="username"/>\
|
||||||
|
<input class="pop-up__input" type="text" placeholder="E mail!" id="email"/>\
|
||||||
|
<input class="pop-up__input" type="password" placeholder="Passywassy" id="password"/>\
|
||||||
|
<input class="pop-up__input" type="password" placeholder="Passywassy again!" id="password-repeat"/>\
|
||||||
|
</form>'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
// Function to register
|
||||||
function register(obj) {
|
function register(obj) {
|
||||||
// AJAX takes control of subby form
|
// AJAX takes control of subby form
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if ($("#username").val() === "" || $("#email").val() === "" || $("#password").val() === "" || $("#password-repeat").val() === "") {
|
let formUsername = document.querySelector("#username").value;
|
||||||
addNotification("Please fill in all fields", 3);
|
let formEmail = document.querySelector("#email").value;
|
||||||
} else {
|
let formPassword = document.querySelector("#password").value;
|
||||||
|
let formPasswordRepeat = document.querySelector("#password-repeat").value;
|
||||||
|
|
||||||
|
if (formUsername === "" || formEmail === "" || formPassword === "" || formPasswordRepeat === "") {
|
||||||
|
addNotification("Please fill in all fields!!!!", 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make form
|
// Make form
|
||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
formData.append("username", $("#username").val());
|
formData.append("username", formUsername);
|
||||||
formData.append("email", $("#email").val());
|
formData.append("email", formEmail);
|
||||||
formData.append("password", $("#password").val());
|
formData.append("password", formPassword);
|
||||||
formData.append("password-repeat", $("#password-repeat").val());
|
formData.append("password-repeat", formPasswordRepeat);
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/auth/register',
|
url: '/auth/register',
|
||||||
|
@ -288,4 +275,51 @@ function register(obj) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.onload = function () {
|
||||||
|
loadOnView();
|
||||||
|
|
||||||
|
const darkColor = '#151515';
|
||||||
|
const lightColor = '#E8E3E3';
|
||||||
|
let contrastCheck = document.querySelectorAll('#contrast-check');
|
||||||
|
for (let i = 0; i < contrastCheck.length; i++) {
|
||||||
|
bgColor = contrastCheck[i].getAttribute('data-color');
|
||||||
|
contrastCheck[i].style.color = colourContrast(bgColor, lightColor, darkColor, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let times = document.querySelectorAll('.time');
|
||||||
|
for (let i = 0; i < times.length; i++) {
|
||||||
|
// Remove milliseconds
|
||||||
|
const raw = times[i].innerHTML.split('.')[0];
|
||||||
|
|
||||||
|
// Parse YYYY-MM-DD HH:MM:SS to Date object
|
||||||
|
const time = raw.split(' ')[1]
|
||||||
|
const date = raw.split(' ')[0].split('-');
|
||||||
|
|
||||||
|
// Format to YYYY/MM/DD HH:MM:SS
|
||||||
|
let formatted = date[0] + '/' + date[1] + '/' + date[2] + ' ' + time + ' UTC';
|
||||||
|
|
||||||
|
// Convert to UTC Date object
|
||||||
|
let dateTime = new Date(formatted);
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
|
times[i].innerHTML = dateTime.toLocaleDateString() + ' ' + dateTime.toLocaleTimeString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.onscroll = function () {
|
||||||
|
loadOnView();
|
||||||
|
|
||||||
|
// Jump to top button
|
||||||
|
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 20) {
|
||||||
|
document.querySelector('.jumpUp').classList = 'jumpUp jumpUp--show';
|
||||||
|
} else {
|
||||||
|
document.querySelector('.jumpUp').classList = 'jumpUp';
|
||||||
|
}
|
||||||
|
document.querySelector('.jumpUp').onclick = function () {
|
||||||
|
document.body.scrollTop = 0;
|
||||||
|
document.documentElement.scrollTop = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.onresize = function () {
|
||||||
|
loadOnView();
|
||||||
|
};
|
|
@ -11,7 +11,8 @@
|
||||||
style="opacity:0; background-color:rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }})"
|
style="opacity:0; background-color:rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }})"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
style="background-image: linear-gradient(to right, rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }}), transparent)"
|
class="banner-filter"
|
||||||
|
style="background: linear-gradient(to right, rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }}), transparent)"
|
||||||
></span>
|
></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
<p></p>
|
<p></p>
|
||||||
<h2><span class="time">{{ image.created_at }}</span></h2>
|
<h2><span class="time">{{ image.created_at }}</span></h2>
|
||||||
</span>
|
</span>
|
||||||
<img data-src="{{ image.file_name }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img data-src="{{ image.file_name }}" onload="imgFade(this)" style="opacity:0;" id="lazy-load"/>
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="banner">
|
<div class="banner">
|
||||||
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
<span></span>
|
<span class="banner-filter"></span>
|
||||||
|
|
||||||
<div class="banner-content">
|
<div class="banner-content">
|
||||||
<p>{{ config.WEBSITE.motto }}</p>
|
<p>{{ config.WEBSITE.motto }}</p>
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
<h2>{{ group.name }}</h2>
|
<h2>{{ group.name }}</h2>
|
||||||
</span>
|
</span>
|
||||||
{% if group.thumbnail %}
|
{% if group.thumbnail %}
|
||||||
<img data-src="{{ group.thumbnail }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img data-src="{{ group.thumbnail }}" onload="imgFade(this)" style="opacity:0;" id="lazy-load"/>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/error.png') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('static', filename='images/error.png') }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="banner">
|
<div class="banner">
|
||||||
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
<span></span>
|
<span class="banner-filter"></span>
|
||||||
|
|
||||||
<div class="banner-content">
|
<div class="banner-content">
|
||||||
<p>{{ config.WEBSITE.motto }}</p>
|
<p>{{ config.WEBSITE.motto }}</p>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<p></p>
|
<p></p>
|
||||||
<h2><span class="time">{{ image.created_at }}</span></h2>
|
<h2><span class="time">{{ image.created_at }}</span></h2>
|
||||||
</span>
|
</span>
|
||||||
<img data-src="{{ image.file_name }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img data-src="{{ image.file_name }}" onload="imgFade(this)" style="opacity:0;" id="lazy-load"/>
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,15 +7,9 @@
|
||||||
<link rel="icon" href="{{url_for('static', filename='images/icon.png')}}">
|
<link rel="icon" href="{{url_for('static', filename='images/icon.png')}}">
|
||||||
<link rel="stylesheet" href="{{url_for('static', filename='theme/style.css')}}" defer>
|
<link rel="stylesheet" href="{{url_for('static', filename='theme/style.css')}}" defer>
|
||||||
|
|
||||||
<!-- Jquery for AJAX -->
|
{% assets "js_all" %}
|
||||||
<script src="{{url_for('static', filename='js/jquery-3.6.3.min.js')}}"></script>
|
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
|
||||||
|
{% endassets %}
|
||||||
<!-- Main Script -->
|
|
||||||
<script src="{{ url_for('static', filename='js/main.js') }}" defer></script>
|
|
||||||
|
|
||||||
<!-- UI -->
|
|
||||||
<script src="{{ url_for('static', filename='js/ui/popup.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/ui/notifications.js') }}"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="notifications"></div>
|
<div class="notifications"></div>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
object-fit: cover
|
object-fit: cover
|
||||||
object-position: center center
|
object-position: center center
|
||||||
|
|
||||||
span
|
.banner-filter
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 0
|
top: 0
|
||||||
left: 0
|
left: 0
|
||||||
|
@ -77,9 +77,6 @@
|
||||||
width: 100vw
|
width: 100vw
|
||||||
height: 25vh
|
height: 25vh
|
||||||
|
|
||||||
span
|
|
||||||
background-image: linear-gradient(to bottom, rgba($primary, 1), rgba($primary, 0))
|
|
||||||
|
|
||||||
.banner-content
|
.banner-content
|
||||||
padding: 0.5rem
|
padding: 0.5rem
|
||||||
|
|
||||||
|
|
|
@ -233,6 +233,8 @@
|
||||||
left: 0
|
left: 0
|
||||||
bottom: calc(-100vh + 3.5rem)
|
bottom: calc(-100vh + 3.5rem)
|
||||||
|
|
||||||
|
border-radius: $rad $rad 0 0
|
||||||
|
|
||||||
&.open
|
&.open
|
||||||
.container
|
.container
|
||||||
left: 0
|
left: 0
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
opacity: 1
|
opacity: 1
|
||||||
|
|
||||||
img
|
img
|
||||||
transform: scale(1.1)
|
transform: scale(1.05)
|
||||||
|
|
||||||
@media (max-width: 800px)
|
@media (max-width: 800px)
|
||||||
.gallery-grid
|
.gallery-grid
|
||||||
|
|
|
@ -18,12 +18,11 @@ $info: $blue
|
||||||
$rad: 6px
|
$rad: 6px
|
||||||
$rad-inner: 3px
|
$rad-inner: 3px
|
||||||
|
|
||||||
//$font: "Work Sans", sans-serif
|
|
||||||
$font: "Work Sans", sans-serif
|
$font: "Work Sans", sans-serif
|
||||||
|
|
||||||
$breakpoint: 800px // responsive breakpoint for mobile
|
// responsive breakpoint for mobile
|
||||||
|
$breakpoint: 800px
|
||||||
|
|
||||||
// Work Sans
|
|
||||||
@font-face
|
@font-face
|
||||||
font-family: 'Work Sans'
|
font-family: 'Work Sans'
|
||||||
src: url('fonts/worksans-regular.woff2')
|
src: url('fonts/worksans-regular.woff2')
|
||||||
|
|
44
poetry.lock
generated
44
poetry.lock
generated
|
@ -204,6 +204,22 @@ Werkzeug = ">=2.2.2"
|
||||||
async = ["asgiref (>=3.2)"]
|
async = ["asgiref (>=3.2)"]
|
||||||
dotenv = ["python-dotenv"]
|
dotenv = ["python-dotenv"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flask-assets"
|
||||||
|
version = "2.0"
|
||||||
|
description = "Asset management for Flask, to compress and merge CSS and Javascript files."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "Flask-Assets-2.0.tar.gz", hash = "sha256:1dfdea35e40744d46aada72831f7613d67bf38e8b20ccaaa9e91fdc37aa3b8c2"},
|
||||||
|
{file = "Flask_Assets-2.0-py3-none-any.whl", hash = "sha256:2845bd3b479be9db8556801e7ebc2746ce2d9edb4e7b64a1c786ecbfc1e5867b"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
Flask = ">=0.8"
|
||||||
|
webassets = ">=2.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flask-caching"
|
name = "flask-caching"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
@ -641,18 +657,18 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytes
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pylint"
|
name = "pylint"
|
||||||
version = "2.16.4"
|
version = "2.17.0"
|
||||||
description = "python code static checker"
|
description = "python code static checker"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7.2"
|
python-versions = ">=3.7.2"
|
||||||
files = [
|
files = [
|
||||||
{file = "pylint-2.16.4-py3-none-any.whl", hash = "sha256:4a770bb74fde0550fa0ab4248a2ad04e7887462f9f425baa0cd8d3c1d098eaee"},
|
{file = "pylint-2.17.0-py3-none-any.whl", hash = "sha256:e097d8325f8c88e14ad12844e3fe2d963d3de871ea9a8f8ad25ab1c109889ddc"},
|
||||||
{file = "pylint-2.16.4.tar.gz", hash = "sha256:8841f26a0dbc3503631b6a20ee368b3f5e0e5461a1d95cf15d103dab748a0db3"},
|
{file = "pylint-2.17.0.tar.gz", hash = "sha256:1460829b6397cb5eb0cdb0b4fc4b556348e515cdca32115f74a1eb7c20b896b4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
astroid = ">=2.14.2,<=2.16.0-dev0"
|
astroid = ">=2.15.0,<=2.17.0-dev0"
|
||||||
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||||
dill = [
|
dill = [
|
||||||
{version = ">=0.2", markers = "python_version < \"3.11\""},
|
{version = ">=0.2", markers = "python_version < \"3.11\""},
|
||||||
|
@ -736,14 +752,14 @@ files = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "67.5.1"
|
version = "67.6.0"
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "setuptools-67.5.1-py3-none-any.whl", hash = "sha256:1c39d42bda4cb89f7fdcad52b6762e3c309ec8f8715b27c684176b7d71283242"},
|
{file = "setuptools-67.6.0-py3-none-any.whl", hash = "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2"},
|
||||||
{file = "setuptools-67.5.1.tar.gz", hash = "sha256:15136a251127da2d2e77ac7a1bc231eb504654f7e3346d93613a13f2e2787535"},
|
{file = "setuptools-67.6.0.tar.gz", hash = "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
@ -865,6 +881,18 @@ files = [
|
||||||
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
|
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webassets"
|
||||||
|
version = "2.0"
|
||||||
|
description = "Media asset management for Python, with glue code for various web frameworks"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "webassets-2.0-py3-none-any.whl", hash = "sha256:a31a55147752ba1b3dc07dee0ad8c8efff274464e08bbdb88c1fd59ffd552724"},
|
||||||
|
{file = "webassets-2.0.tar.gz", hash = "sha256:167132337677c8cedc9705090f6d48da3fb262c8e0b2773b29f3352f050181cd"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "werkzeug"
|
name = "werkzeug"
|
||||||
version = "2.2.3"
|
version = "2.2.3"
|
||||||
|
@ -987,4 +1015,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 = "0c2a7c41e8974f82e33d09ddcdf4a97f54fdbf1be71c0d7c7e4be1daa05fe661"
|
content-hash = "28f7d599f912b9385b4a497f89da59cf2b087ac1ec12c3582e603f47f8e11492"
|
||||||
|
|
|
@ -9,16 +9,17 @@ readme = ".github/README.md"
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.8"
|
python = "^3.8"
|
||||||
Flask = "^2.2.2"
|
Flask = "^2.2.2"
|
||||||
flask-compress = "^1.13"
|
Flask-Compress = "^1.13"
|
||||||
flask-caching = "^2.0.2"
|
Flask-Caching = "^2.0.2"
|
||||||
gunicorn = "^20.1.0"
|
Flask-Assets = "^2.0"
|
||||||
|
SQLAlchemy = "^2.0.3"
|
||||||
python-dotenv = "^0.21.0"
|
python-dotenv = "^0.21.0"
|
||||||
|
gunicorn = "^20.1.0"
|
||||||
pyyaml = "^6.0"
|
pyyaml = "^6.0"
|
||||||
libsass = "^0.22.0"
|
libsass = "^0.22.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"
|
||||||
SQLAlchemy = "^2.0.3"
|
|
||||||
pylint = "^2.16.3"
|
pylint = "^2.16.3"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue