diff --git a/onlylegs/api.py b/onlylegs/api.py index 9bcf477..fffeea5 100644 --- a/onlylegs/api.py +++ b/onlylegs/api.py @@ -9,7 +9,6 @@ from uuid import uuid4 from flask import ( Blueprint, - flash, abort, send_from_directory, jsonify, @@ -21,7 +20,7 @@ from flask_login import login_required, current_user from colorthief import ColorThief from onlylegs.extensions import db -from onlylegs.models import Users, Pictures, Albums, AlbumJunction +from onlylegs.models import Users, Pictures from onlylegs.utils.metadata import yoink from onlylegs.utils.generate_image import generate_thumbnail @@ -111,8 +110,8 @@ def media(path): r for resolution, thumb for thumbnail etc e for extension, jpg, png etc """ - res = request.args.get("r", default=None).strip() - ext = request.args.get("e", default=None).strip() + res = request.args.get("r", "").strip() + ext = request.args.get("e", "").strip() # if no args are passed, return the raw file if not res and not ext: @@ -181,113 +180,3 @@ def upload(): db.session.commit() return jsonify({"message": "File uploaded"}), 200 - - -@blueprint.route("/media/delete/", methods=["POST"]) -@login_required -def delete_image(image_id): - """ - Deletes an image from the server and database - """ - post = db.get_or_404(Pictures, image_id) - - # Check if image exists and if user is allowed to delete it (author) - if post.author_id != current_user.id: - logging.info("User %s tried to delete image %s", current_user.id, image_id) - return ( - jsonify({"message": "You are not allowed to delete this image, heck off"}), - 403, - ) - - # Delete file - try: - os.remove(os.path.join(current_app.config["UPLOAD_FOLDER"], post.filename)) - except FileNotFoundError: - logging.warning( - "File not found: %s, already deleted or never existed", post.filename - ) - - # Delete cached files - cache_name = post.filename.rsplit(".")[0] - for cache_file in pathlib.Path(current_app.config["CACHE_FOLDER"]).glob( - cache_name + "*" - ): - os.remove(cache_file) - - AlbumJunction.query.filter_by(picture_id=image_id).delete() - db.session.delete(post) - db.session.commit() - - logging.info("Removed image (%s) %s", image_id, post.filename) - flash(["Image was all in Le Head!", "1"]) - return jsonify({"message": "Image deleted"}), 200 - - -@blueprint.route("/group/create", methods=["POST"]) -@login_required -def create_group(): - """ - Creates a group - """ - group_name = request.form.get("name", "").strip() - group_description = request.form.get("description", "").strip() - group_author = current_user.id - - new_group = Albums( - name=group_name, - description=group_description, - author_id=group_author, - ) - - db.session.add(new_group) - db.session.commit() - - return jsonify({"message": "Group created", "id": new_group.id}) - - -@blueprint.route("/group/modify", methods=["POST"]) -@login_required -def modify_group(): - """ - Changes the images in a group - """ - group_id = request.form.get("group", "").strip() - image_id = request.form.get("image", "").strip() - action = request.form.get("action", "").strip() - - group = db.get_or_404(Albums, group_id) - db.get_or_404(Pictures, image_id) # Check if image exists - - if group.author_id != current_user.id: - return jsonify({"message": "You are not the owner of this group"}), 403 - - junction_exist = AlbumJunction.query.filter_by( - album_id=group_id, picture_id=image_id - ).first() - - if action == "add" and not junction_exist: - db.session.add(AlbumJunction(album_id=group_id, picture_id=image_id)) - elif request.form["action"] == "remove": - AlbumJunction.query.filter_by(album_id=group_id, picture_id=image_id).delete() - - db.session.commit() - return jsonify({"message": "Group modified"}) - - -@blueprint.route("/group/delete", methods=["POST"]) -def delete_group(): - """ - Deletes a group - """ - group_id = request.form.get("group", "").strip() - group = db.get_or_404(Albums, group_id) - - if group.author_id != current_user.id: - return jsonify({"message": "You are not the owner of this group"}), 403 - - AlbumJunction.query.filter_by(album_id=group_id).delete() - db.session.delete(group) - db.session.commit() - - flash(["Group yeeted!", "1"]) - return jsonify({"message": "Group deleted"}) diff --git a/onlylegs/static/js/groupPage.js b/onlylegs/static/js/groupPage.js new file mode 100644 index 0000000..193dccc --- /dev/null +++ b/onlylegs/static/js/groupPage.js @@ -0,0 +1,155 @@ +function groupDeletePopup() { + let title = 'Yeet!'; + let subtitle = + 'Are you surrrre? This action is irreversible ' + + 'and very final. This wont delete the images, ' + + 'but it will remove them from this group.' + let body = null; + + let deleteBtn = document.createElement('button'); + deleteBtn.classList.add('btn-block'); + deleteBtn.classList.add('critical'); + deleteBtn.innerHTML = 'Dewww eeeet!'; + deleteBtn.onclick = groupDeleteConfirm; + + popupShow(title, subtitle, body, [popupCancelButton, deleteBtn]); +} + +function groupDeleteConfirm(event) { + // AJAX takes control of subby form :3 + event.preventDefault(); + + fetch('/group/' + group_data['id'], { + method: 'DELETE', + }).then(response => { + if (response.ok) { + window.location.href = '/group/'; + } else { + addNotification('Server exploded, returned:' + response.status, 2); + } + }).catch(error => { + addNotification('Error yeeting group!' + error, 2); + }); +} + +function groupEditPopup() { + let title = 'Nothing stays the same'; + let subtitle = 'Add, remove, or change, the power is in your hands...' + + let formSubmitButton = document.createElement('button'); + formSubmitButton.setAttribute('form', 'groupEditForm'); + formSubmitButton.setAttribute('type', 'submit'); + formSubmitButton.classList.add('btn-block'); + formSubmitButton.classList.add('primary'); + formSubmitButton.innerHTML = 'Saveeee'; + + // Create form + let body = document.createElement('form'); + body.setAttribute('onsubmit', 'return groupEditConfirm(event);'); + body.id = 'groupEditForm'; + + let formImageId = document.createElement('input'); + formImageId.setAttribute('type', 'text'); + formImageId.setAttribute('placeholder', 'Image ID'); + formImageId.setAttribute('required', ''); + formImageId.classList.add('input-block'); + formImageId.id = 'groupFormImageId'; + + let formAction = document.createElement('input'); + formAction.setAttribute('type', 'text'); + formAction.setAttribute('value', 'add'); + formAction.setAttribute('placeholder', '[add, remove]'); + formAction.setAttribute('required', ''); + formAction.classList.add('input-block'); + formAction.id = 'groupFormAction'; + + body.appendChild(formImageId); + body.appendChild(formAction); + + popupShow(title, subtitle, body, [popupCancelButton, formSubmitButton]); +} + +function groupEditConfirm(event) { + // AJAX takes control of subby form :3 + event.preventDefault(); + + let imageId = document.querySelector("#groupFormImageId").value; + let action = document.querySelector("#groupFormAction").value; + let formData = new FormData(); + formData.append("imageId", imageId); + formData.append("action", action); + + fetch('/group/' + group_data['id'], { + method: 'PUT', + body: formData + }).then(response => { + if (response.ok) { + window.location.reload(); + } else { + addNotification('Server exploded, returned:' + response.status, 2); + } + }).catch(error => { + addNotification('Error!!!!! Panic!!!!' + error, 2); + }); +} + +function groupCreatePopup() { + let title = 'New stuff!'; + let subtitle = + 'Image groups are a simple way to ' + + '"group" images together, are you ready?' + + let formSubmitButton = document.createElement('button'); + formSubmitButton.setAttribute('form', 'groupCreateForm'); + formSubmitButton.setAttribute('type', 'submit'); + formSubmitButton.classList.add('btn-block'); + formSubmitButton.classList.add('primary'); + formSubmitButton.innerHTML = 'Huzzah!'; + + // Create form + let body = document.createElement('form'); + body.setAttribute('onsubmit', 'return groupCreateConfirm(event);'); + body.id = 'groupCreateForm'; + + let formName = document.createElement('input'); + formName.setAttribute('type', 'text'); + formName.setAttribute('placeholder', 'Group namey'); + formName.setAttribute('required', ''); + formName.classList.add('input-block'); + formName.id = 'groupFormName'; + + let formDescription = document.createElement('input'); + formDescription.setAttribute('type', 'text'); + formDescription.setAttribute('placeholder', 'What it about????'); + formDescription.classList.add('input-block'); + formDescription.id = 'groupFormDescription'; + + body.appendChild(formName); + body.appendChild(formDescription); + + popupShow(title, subtitle, body, [popupCancelButton, formSubmitButton]); +} + +function groupCreateConfirm(event) { + // AJAX takes control of subby form :3 + event.preventDefault(); + + let name = document.querySelector("#groupFormName").value; + let description = document.querySelector("#groupFormDescription").value; + let formData = new FormData(); + formData.append("name", name); + formData.append("description", description); + + fetch('/group/', { + method: 'POST', + body: formData + }).then(response => { + if (response.ok) { + window.location.reload(); + } else { + addNotification('Server exploded, returned:' + response.status, 2); + } + }).catch(error => { + addNotification('Error summoning group!' + error, 2); + }); +} \ No newline at end of file diff --git a/onlylegs/static/js/imagePage.js b/onlylegs/static/js/imagePage.js new file mode 100644 index 0000000..b98d46d --- /dev/null +++ b/onlylegs/static/js/imagePage.js @@ -0,0 +1,101 @@ +function imageFullscreen() { + let info = document.querySelector('.info-container'); + let image = document.querySelector('.image-container'); + + if (info.classList.contains('collapsed')) { + info.classList.remove('collapsed'); + image.classList.remove('collapsed'); + document.cookie = "image-info=0" + } else { + info.classList.add('collapsed'); + image.classList.add('collapsed'); + document.cookie = "image-info=1" + } +} +function imageDeletePopup() { + let title = 'DESTRUCTION!!!!!!'; + let subtitle = + 'Do you want to delete this image along with ' + + 'all of its data??? This action is irreversible!'; + let body = null; + + let deleteBtn = document.createElement('button'); + deleteBtn.classList.add('btn-block'); + deleteBtn.classList.add('critical'); + deleteBtn.innerHTML = 'Dewww eeeet!'; + deleteBtn.onclick = imageDeleteConfirm; + + popupShow(title, subtitle, body, [popupCancelButton, deleteBtn]); +} +function imageDeleteConfirm() { + popupDismiss(); + + fetch('/image/' + image_data["id"], { + method: 'DELETE', + }).then(response => { + if (response.ok) { + window.location.href = '/'; + } else { + addNotification('Image *clings*', 2); + } + }); +} + +function imageEditPopup() { + let title = 'Edit image!'; + let subtitle = 'Enter funny stuff here!'; + + let formSubmitButton = document.createElement('button'); + formSubmitButton.setAttribute('form', 'imageEditForm'); + formSubmitButton.setAttribute('type', 'submit'); + formSubmitButton.classList.add('btn-block'); + formSubmitButton.classList.add('primary'); + formSubmitButton.innerHTML = 'Saveeee'; + + // Create form + let body = document.createElement('form'); + body.setAttribute('onsubmit', 'return imageEditConfirm(event);'); + body.id = 'imageEditForm'; + + let formAlt = document.createElement('input'); + formAlt.setAttribute('type', 'text'); + formAlt.setAttribute('value', image_data["alt"]); + formAlt.setAttribute('placeholder', 'Image Alt'); + formAlt.classList.add('input-block'); + formAlt.id = 'imageFormAlt'; + + let formDescription = document.createElement('input'); + formDescription.setAttribute('type', 'text'); + formDescription.setAttribute('value', image_data["description"]); + formDescription.setAttribute('placeholder', 'Image Description'); + formDescription.classList.add('input-block'); + formDescription.id = 'imageFormDescription'; + + body.appendChild(formAlt); + body.appendChild(formDescription); + + popupShow(title, subtitle, body, [popupCancelButton, formSubmitButton]); +} + +function imageEditConfirm(event) { + // Yoink subby form + event.preventDefault(); + + let alt = document.querySelector('#imageFormAlt').value; + let description = document.querySelector('#imageFormDescription').value; + let form = new FormData(); + form.append('alt', alt); + form.append('description', description); + + fetch('/image/' + image_data["id"], { + method: 'PUT', + body: form, + }).then(response => { + if (response.ok) { + popupDismiss(); + window.location.reload(); + } else { + addNotification('Image *clings*', 2); + } + }); +} diff --git a/onlylegs/static/js/login.js b/onlylegs/static/js/login.js index 1e2287a..ed95512 100644 --- a/onlylegs/static/js/login.js +++ b/onlylegs/static/js/login.js @@ -5,7 +5,7 @@ function showLogin() { cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('transparent'); cancelBtn.innerHTML = 'nuuuuuuuu'; - cancelBtn.onclick = popupDissmiss; + cancelBtn.onclick = popupDismiss; loginBtn = document.createElement('button'); loginBtn.classList.add('btn-block'); @@ -50,7 +50,7 @@ function showLogin() { loginForm.appendChild(passwordInput); loginForm.appendChild(rememberMeSpan); - popUpShow( + popupShow( 'Login!', 'Need an account? Register!', loginForm, @@ -103,7 +103,7 @@ function showRegister() { cancelBtn.classList.add('btn-block'); cancelBtn.classList.add('transparent'); cancelBtn.innerHTML = 'nuuuuuuuu'; - cancelBtn.onclick = popupDissmiss; + cancelBtn.onclick = popupDismiss; registerBtn = document.createElement('button'); registerBtn.classList.add('btn-block'); @@ -146,7 +146,7 @@ function showRegister() { registerForm.appendChild(passwordInput); registerForm.appendChild(passwordInputRepeat); - popUpShow( + popupShow( 'Who are you?', 'Already have an account? Login!', registerForm, diff --git a/onlylegs/static/js/popup.js b/onlylegs/static/js/popup.js index b0b19ac..0ef8cc4 100644 --- a/onlylegs/static/js/popup.js +++ b/onlylegs/static/js/popup.js @@ -1,4 +1,4 @@ -function popUpShow(titleText, subtitleText, bodyContent=null, userActions=null) { +function popupShow(titleText, subtitleText, bodyContent=null, userActions=null) { // Get popup elements const popupSelector = document.querySelector('.pop-up'); const headerSelector = document.querySelector('.pop-up-header'); @@ -9,38 +9,47 @@ function popUpShow(titleText, subtitleText, bodyContent=null, userActions=null) actionsSelector.innerHTML = ''; // Set popup header and subtitle - const titleElement = document.createElement('h2'); - titleElement.innerHTML = titleText; - headerSelector.appendChild(titleElement); + let titleElement = document.createElement('h2'); + titleElement.innerHTML = titleText; + headerSelector.appendChild(titleElement); - const subtitleElement = document.createElement('p'); - subtitleElement.innerHTML = subtitleText; - headerSelector.appendChild(subtitleElement); + let subtitleElement = document.createElement('p'); + subtitleElement.innerHTML = subtitleText; + headerSelector.appendChild(subtitleElement); - if (bodyContent) { - headerSelector.appendChild(bodyContent); - } + if (bodyContent) { headerSelector.appendChild(bodyContent) } // Set buttons that will be displayed if (userActions) { - // for each user action, add the element - for (let i = 0; i < userActions.length; i++) { - actionsSelector.appendChild(userActions[i]); - } + userActions.forEach((action) => { + actionsSelector.appendChild(action); + }); } else { - actionsSelector.innerHTML = ''; + let closeButton = document.createElement('button'); + closeButton.classList.add('btn-block'); + closeButton.classList.add('transparent'); + closeButton.innerHTML = 'Yeet!'; + closeButton.onclick = popupDismiss; + actionsSelector.appendChild(closeButton); } // Stop scrolling and show popup document.querySelector("html").style.overflow = "hidden"; popupSelector.style.display = 'block'; - setTimeout(() => { popupSelector.classList.add('active') }, 5); // 2ms delay to allow for css transition >:C + + // 5ms delay to allow for css transition >:C + setTimeout(() => { popupSelector.classList.add('active') }, 5); } -function popupDissmiss() { +function popupDismiss() { const popupSelector = document.querySelector('.pop-up'); - document.querySelector("html").style.overflow = "auto"; popupSelector.classList.remove('active'); setTimeout(() => { popupSelector.style.display = 'none'; }, 200); } + +const popupCancelButton = document.createElement('button'); + popupCancelButton.classList.add('btn-block'); + popupCancelButton.classList.add('transparent'); + popupCancelButton.innerHTML = 'nuuuuuuuu'; + popupCancelButton.onclick = popupDismiss; diff --git a/onlylegs/templates/base.html b/onlylegs/templates/base.html index f39b915..b580c7f 100644 --- a/onlylegs/templates/base.html +++ b/onlylegs/templates/base.html @@ -36,7 +36,7 @@
- +
@@ -160,7 +160,7 @@ infoButton.classList.add('show'); } infoButton.onclick = () => { - popUpShow('OnlyLegs', + popupShow('OnlyLegs', 'v{{ config['APP_VERSION'] }} ' + 'using Phosphoricons and Flask.' + '
Made by Fluffy and others with ❤️'); diff --git a/onlylegs/templates/group.html b/onlylegs/templates/group.html index c942713..67cfb1f 100644 --- a/onlylegs/templates/group.html +++ b/onlylegs/templates/group.html @@ -11,163 +11,11 @@ {% endif %}