diff --git a/gallery/__init__.py b/gallery/__init__.py index 103f76e..8657f37 100644 --- a/gallery/__init__.py +++ b/gallery/__init__.py @@ -16,7 +16,7 @@ from flask import Flask, render_template # Configuration import platformdirs from dotenv import load_dotenv -from yaml import FullLoader, safe_load +from yaml import safe_load # Utils from gallery.utils import theme_manager @@ -58,11 +58,6 @@ def create_app(test_config=None): else: app.config.from_mapping(test_config) - try: - os.makedirs(app.instance_path) - except OSError: - pass - # Load theme theme_manager.CompileTheme('default', app.root_path) @@ -71,11 +66,7 @@ def create_app(test_config=None): assets.register('js_all', js_scripts) # Error handlers - @app.errorhandler(403) - @app.errorhandler(404) - @app.errorhandler(405) - @app.errorhandler(410) - @app.errorhandler(500) + @app.errorhandler(Exception) def error_page(err): error = err.code msg = err.description diff --git a/gallery/routes/routing.py b/gallery/routes/routing.py index 4ae6a15..9d38a72 100644 --- a/gallery/routes/routing.py +++ b/gallery/routes/routing.py @@ -1,7 +1,7 @@ """ Onlylegs Gallery - Routing """ -from flask import Blueprint, render_template, url_for +from flask import Blueprint, render_template, url_for, request from werkzeug.exceptions import abort from sqlalchemy.orm import sessionmaker @@ -23,6 +23,9 @@ def index(): db.Posts.image_colours, db.Posts.created_at, db.Posts.id).order_by(db.Posts.id.desc()).all() + + if request.args.get('coffee') == 'please': + abort(418) return render_template('index.html', images=images) diff --git a/gallery/static/js/login.js b/gallery/static/js/login.js index f7cd4cb..735ccca 100644 --- a/gallery/static/js/login.js +++ b/gallery/static/js/login.js @@ -3,14 +3,14 @@ function showLogin() { popUpShow( 'Login!', 'Need an account? Register!', - '\ - ', - '
' + '' + + '', + '' ); -}; +} // Function to login function login(event) { // AJAX takes control of subby form :3 @@ -67,7 +67,7 @@ function showRegister() { \ ' ); -}; +} // Function to register function register(obj) { // AJAX takes control of subby form @@ -101,7 +101,7 @@ function register(obj) { addNotification('Registered successfully! Now please login to continue', 1); showLogin(); } else { - for (var i = 0; i < response.length; i++) { + for (let i = 0; i < response.length; i++) { addNotification(response[i], 2); } } @@ -120,4 +120,4 @@ function register(obj) { } } }); -} \ No newline at end of file +} diff --git a/gallery/static/js/main.js b/gallery/static/js/main.js index 4458cdd..cba5135 100644 --- a/gallery/static/js/main.js +++ b/gallery/static/js/main.js @@ -5,26 +5,29 @@ function imgFade(obj, time = 250) { // https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color function colourContrast(bgColor, lightColor, darkColor, threshold = 0.179) { // if color is in hex format then convert to rgb else parese rgb + let r = 0 + let g = 0 + let b = 0 if (bgColor.charAt(0) === '#') { - var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor; - var r = parseInt(color.substring(0, 2), 16); // hexToR - var g = parseInt(color.substring(2, 4), 16); // hexToG - var b = parseInt(color.substring(4, 6), 16); // hexToB + const color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor; + r = parseInt(color.substring(0, 2), 16); // hexToR + g = parseInt(color.substring(2, 4), 16); // hexToG + b = parseInt(color.substring(4, 6), 16); // hexToB } else { - var color = bgColor.replace('rgb(', '').replace(')', '').split(','); - var r = color[0]; - var g = color[1]; - var b = color[2]; + const color = bgColor.replace('rgb(', '').replace(')', '').split(','); + r = color[0]; + g = color[1]; + b = color[2]; } - var uicolors = [r / 255, g / 255, b / 255]; - var c = uicolors.map((col) => { + const uicolors = [r / 255, g / 255, b / 255]; + const c = uicolors.map((col) => { if (col <= 0.03928) { return col / 12.92; } return Math.pow((col + 0.055) / 1.055, 2.4); }); - var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]); + const 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 @@ -48,8 +51,7 @@ window.onload = function () { const lightColor = '#E8E3E3'; let contrastCheck = document.querySelectorAll('#contrast-check'); for (let i = 0; i < contrastCheck.length; i++) { - console.log(contrastCheck[i].getAttribute('data-color')); - bgColor = contrastCheck[i].getAttribute('data-color'); + let bgColor = contrastCheck[i].getAttribute('data-color'); contrastCheck[i].style.color = colourContrast(bgColor, lightColor, darkColor); } @@ -89,4 +91,4 @@ window.onscroll = function () { }; window.onresize = function () { loadOnView(); -}; \ No newline at end of file +}; diff --git a/gallery/static/js/notifications.js b/gallery/static/js/notifications.js index 9d46f2e..de7e3c6 100644 --- a/gallery/static/js/notifications.js +++ b/gallery/static/js/notifications.js @@ -1,8 +1,8 @@ function addNotification(text='Sample notification', type=4) { - var container = document.querySelector('.notifications'); + let container = document.querySelector('.notifications'); // Create notification element - var div = document.createElement('div'); + let div = document.createElement('div'); div.classList.add('sniffle__notification'); div.onclick = function() { if (div.parentNode) { @@ -15,44 +15,36 @@ function addNotification(text='Sample notification', type=4) { }; // Create icon element and append to notification - var icon = document.createElement('span'); + let icon = document.createElement('span'); icon.classList.add('sniffle__notification-icon'); switch (type) { case 1: div.classList.add('sniffle__notification--success'); - icon.innerHTML = ''; + icon.innerHTML = ''; break; case 2: div.classList.add('sniffle__notification--error'); - icon.innerHTML = ''; + icon.innerHTML = ''; break; case 3: div.classList.add('sniffle__notification--warning'); - icon.innerHTML = ''; + icon.innerHTML = ''; break; default: div.classList.add('sniffle__notification--info'); - icon.innerHTML = ''; + icon.innerHTML = ''; break; } div.appendChild(icon); // Create text element and append to notification - var description = document.createElement('span'); + let description = document.createElement('span'); description.classList.add('sniffle__notification-text'); description.innerHTML = text; div.appendChild(description); // Create span to show time remaining - var timer = document.createElement('span'); + let timer = document.createElement('span'); timer.classList.add('sniffle__notification-time'); div.appendChild(timer); diff --git a/gallery/static/js/popup.js b/gallery/static/js/popup.js index c564aa7..46bd0ce 100644 --- a/gallery/static/js/popup.js +++ b/gallery/static/js/popup.js @@ -1,11 +1,11 @@ -function popUpShow(title, body, actions, content) { +function popUpShow(title, body, actions = '', content = '') { // Stop scrolling document.querySelector("html").style.overflow = "hidden"; // Get popup elements - var popup = document.querySelector('.pop-up'); - var popupContent = document.querySelector('.pop-up-content'); - var popupActions = document.querySelector('.pop-up-controlls'); + let popup = document.querySelector('.pop-up'); + let popupContent = document.querySelector('.pop-up-content'); + let popupActions = document.querySelector('.pop-up-controlls'); // Set popup content popupContent.innerHTML = `${body}
${content}`; @@ -24,7 +24,7 @@ function popupDissmiss() { // un-Stop scrolling document.querySelector("html").style.overflow = "auto"; - var popup = document.querySelector('.pop-up'); + let popup = document.querySelector('.pop-up'); popup.classList.remove('active'); diff --git a/gallery/static/js/uploadTab.js b/gallery/static/js/uploadTab.js index 7963adc..27bb9b7 100644 --- a/gallery/static/js/uploadTab.js +++ b/gallery/static/js/uploadTab.js @@ -1,92 +1,160 @@ -// Function to upload images -function uploadFile() { - // AJAX takes control of subby form - event.preventDefault(); +window.addEventListener("dragover",(event) => { + event.preventDefault(); +},false); +window.addEventListener("drop",(event) => { + event.preventDefault(); +},false); - const jobList = document.querySelector(".upload-jobs"); +function fileChanged(obj) { + document.querySelector('.fileDrop-block').classList.remove('error'); - // Check for empty upload - if ($("#file").val() === "") { - addNotification("Please select a file to upload", 2); + if ($(obj).val() === '') { + document.querySelector('.fileDrop-block').classList.remove('active'); + document.querySelector('.fileDrop-block .status').innerHTML = 'Choose or Drop file'; } else { - // Make form - let formData = new FormData(); - formData.append("file", $("#file").prop("files")[0]); - formData.append("alt", $("#alt").val()); - formData.append("description", $("#description").val()); - formData.append("tags", $("#tags").val()); - formData.append("submit", $("#submit").val()); - - // Upload the information - $.ajax({ - url: '/api/upload', - type: 'post', - data: formData, - contentType: false, - processData: false, - beforeSend: function () { - jobContainer = document.createElement("div"); - jobContainer.classList.add("job"); - - jobStatus = document.createElement("span"); - jobStatus.classList.add("job__status"); - jobStatus.innerHTML = "Uploading..."; - - jobProgress = document.createElement("span"); - jobProgress.classList.add("progress"); - - jobImg = document.createElement("img"); - jobImg.src = URL.createObjectURL($("#file").prop("files")[0]); - - jobImgFilter = document.createElement("span"); - jobImgFilter.classList.add("img-filter"); - - jobContainer.appendChild(jobStatus); - jobContainer.appendChild(jobProgress); - jobContainer.appendChild(jobImg); - jobContainer.appendChild(jobImgFilter); - jobList.appendChild(jobContainer); - }, - success: function (response) { - jobContainer.classList.add("success"); - jobStatus.innerHTML = "Uploaded!"; - if (!document.querySelector(".upload-panel").classList.contains("open")) { - addNotification("Image uploaded successfully", 1); - } - }, - error: function (response) { - jobContainer.classList.add("critical"); - switch (response.status) { - case 500: - jobStatus.innerHTML = "Server exploded, F's in chat"; - break; - case 400: - case 404: - jobStatus.innerHTML = "Error uploading. Blame yourself"; - break; - case 403: - jobStatus.innerHTML = "None but devils play past here..."; - break; - case 413: - jobStatus.innerHTML = "File too large!!!!!!"; - break; - default: - jobStatus.innerHTML = "Error uploading file, blame someone"; - break; - } - if (!document.querySelector(".upload-panel").classList.contains("open")) { - addNotification("Error uploading file", 2); - } - }, - }); - - // Empty values - $("#file").val(""); - $("#alt").val(""); - $("#description").val(""); - $("#tags").val(""); + document.querySelector('.fileDrop-block').classList.add('active'); + document.querySelector('.fileDrop-block .status').innerHTML = obj.files[0].name; } -}; +} + +document.addEventListener('DOMContentLoaded', function() { + // Function to upload images + const uploadForm = document.querySelector('#uploadForm'); + const fileDrop = document.querySelector('.fileDrop-block'); + const fileDropTitle = fileDrop.querySelector('.status'); + const fileUpload = uploadForm.querySelector('#file'); + + + $(fileUpload).val(''); + + + // Choose or drop file button + ['dragover', 'dragenter'].forEach(eventName => { + fileDrop.addEventListener(eventName, fileActivate, false); + }); + ['dragleave', 'drop'].forEach(eventName => { + fileDrop.addEventListener(eventName, fileDefault, false); + }) + + // Drop file into box + fileDrop.addEventListener('drop', fileDropHandle, false); + + + // Edging the file plunge :3 + function fileActivate(event) { + fileDrop.classList.remove('error'); + fileDrop.classList.add('edging'); + fileDropTitle.innerHTML = 'Drop to upload!'; + } + function fileDefault(event) { + fileDrop.classList.remove('error'); + fileDrop.classList.remove('edging'); + fileDropTitle.innerHTML = 'Choose or Drop file'; + } + + function fileDropHandle(event) { + event.preventDefault() + fileUpload.files = event.dataTransfer.files; + + fileDropTitle.innerHTML = fileUpload.files[0].name; + fileDrop.classList.add('active'); + } + + + uploadForm.addEventListener('submit', (event) => { + // AJAX takes control of subby form + event.preventDefault() + + const jobList = document.querySelector(".upload-jobs"); + + // Check for empty upload + if ($(fileUpload).val() === '') { + fileDrop.classList.add('error'); + fileDropTitle.innerHTML = 'No file selected!'; + } else { + // Make form + let formData = new FormData(); + formData.append("file", $("#file").prop("files")[0]); + formData.append("alt", $("#alt").val()); + formData.append("description", $("#description").val()); + formData.append("tags", $("#tags").val()); + formData.append("submit", $("#submit").val()); + + // Upload the information + $.ajax({ + url: '/api/upload', + type: 'post', + data: formData, + contentType: false, + processData: false, + beforeSend: function () { + jobContainer = document.createElement("div"); + jobContainer.classList.add("job"); + + jobStatus = document.createElement("span"); + jobStatus.classList.add("job__status"); + jobStatus.innerHTML = "Uploading..."; + + jobProgress = document.createElement("span"); + jobProgress.classList.add("progress"); + + jobImg = document.createElement("img"); + jobImg.src = URL.createObjectURL($("#file").prop("files")[0]); + + jobImgFilter = document.createElement("span"); + jobImgFilter.classList.add("img-filter"); + + jobContainer.appendChild(jobStatus); + jobContainer.appendChild(jobProgress); + jobContainer.appendChild(jobImg); + jobContainer.appendChild(jobImgFilter); + jobList.appendChild(jobContainer); + }, + success: function (response) { + jobContainer.classList.add("success"); + jobStatus.innerHTML = "Uploaded!"; + if (!document.querySelector(".upload-panel").classList.contains("open")) { + addNotification("Image uploaded successfully", 1); + } + }, + error: function (response) { + jobContainer.classList.add("critical"); + switch (response.status) { + case 500: + jobStatus.innerHTML = "Server exploded, F's in chat"; + break; + case 400: + case 404: + jobStatus.innerHTML = "Error uploading. Blame yourself"; + break; + case 403: + jobStatus.innerHTML = "None but devils play past here..."; + break; + case 413: + jobStatus.innerHTML = "File too large!!!!!!"; + break; + default: + jobStatus.innerHTML = "Error uploading file, blame someone"; + break; + } + if (!document.querySelector(".upload-panel").classList.contains("open")) { + addNotification("Error uploading file", 2); + } + }, + }); + + // Empty values + $(fileUpload).val(''); + $("#alt").val(''); + $("#description").val(''); + $("#tags").val(''); + + // Reset drop + fileDrop.classList.remove('active'); + fileDropTitle.innerHTML = 'Choose or Drop file'; + } + }); +}); // open upload tab function openUploadTab() { diff --git a/gallery/templates/image.html b/gallery/templates/image.html index 7cf1a27..fd7f52b 100644 --- a/gallery/templates/image.html +++ b/gallery/templates/image.html @@ -35,9 +35,7 @@ {% if next_url %}