added sign-up, tweaked jinja macro flashes and message display

This commit is contained in:
Xevion
2019-07-02 14:10:11 -05:00
parent 60c499d471
commit 3cc7e46aaf
8 changed files with 177 additions and 78 deletions

View File

@@ -15,4 +15,5 @@ login.login_view = 'login'
db = SQLAlchemy(app) db = SQLAlchemy(app)
migrate = Migrate(app, db) migrate = Migrate(app, db)
from app import routes, models from app import routes, models
app.jinja_env.globals.update(get_hidden=routes.get_hidden)

View File

@@ -1,9 +1,27 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired from wtforms.validators import ValidationError, DataRequired, EqualTo, Email
from app.models import User
class LoginForm(FlaskForm): class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()]) username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()]) password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me') remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign in') submit = SubmitField('Sign in')
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
password2 = PasswordField('Repeat Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Register')
def validate_username(self, username):
user = User.query.filter_by(username=username.data).first()
if user is not None:
raise ValidationError('That username is not available.')
def validate_email(self, email):
user = User.query.filter_by(email=email.data).first()
if user is not None:
raise ValidationError('That email address is not available.')

View File

@@ -1,6 +1,6 @@
from app import app from app import app, db
from app.models import User from app.models import User
from app.forms import LoginForm from app.forms import LoginForm, RegistrationForm
from werkzeug.urls import url_parse from werkzeug.urls import url_parse
from flask import render_template, redirect, url_for, flash, request, jsonify from flask import render_template, redirect, url_for, flash, request, jsonify
from flask_login import current_user, login_user, logout_user, login_required from flask_login import current_user, login_user, logout_user, login_required
@@ -49,11 +49,19 @@ def index():
for _ in range(10)] for _ in range(10)]
return render_template('index.html', content=content) return render_template('index.html', content=content)
@app.route('/signup') @app.route('/register', methods=['GET', 'POST'])
@app.route('/sign-up') def register():
def signup(): if current_user.is_authenticated:
return render_template('signup.html', title='Sign Up', hideSignup=True) return redirect(url_for('index'))
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash('Registered Successfully!', 'info')
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form, hideRegister=True)
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])
def login(): def login():
@@ -63,14 +71,14 @@ def login():
if form.validate_on_submit(): if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first() user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data): if user is None or not user.check_password(form.password.data):
flash('Invalid username or password') flash('Invalid username or password', 'error')
return redirect(url_for('login')) return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data) login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next') next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '': if not next_page or url_parse(next_page).netloc != '':
next_page = url_for('index') next_page = url_for('index')
return redirect(next_page) return redirect(next_page)
return render_template('login.html', title='Sign In', form=form, hideLogin=True) return render_template('login.html', title='Login', form=form, hideLogin=True)
@app.route('/logout') @app.route('/logout')
def logout(): def logout():
@@ -95,6 +103,9 @@ def validate_id(id):
val = str(app.config['HIDDEN_URL']).strip() val = str(app.config['HIDDEN_URL']).strip()
return id == val return id == val
def get_hidden():
return "/hidden{}/".format(app.config['HIDDEN_URL'])
@app.route('/hidden<id>/help') @app.route('/hidden<id>/help')
@login_required @login_required
def hidden_help(id): def hidden_help(id):
@@ -103,7 +114,7 @@ def hidden_help(id):
else: else:
return 'error: bad id' return 'error: bad id'
@app.route('/hidden<id>') @app.route('/hidden<id>/')
@login_required @login_required
def hidden(id): def hidden(id):
if not validate_id(id): if not validate_id(id):
@@ -124,7 +135,7 @@ def hidden(id):
showfull = boolparse(request.args.get('showfull')) showfull = boolparse(request.args.get('showfull'))
showtags = boolparse(request.args.get('showtags')) showtags = boolparse(request.args.get('showtags'))
# Request, Parse & Build Data # Request, Parse & Build Data
data = trap(tags, page-1, count, base64, showfull) data = build_data(tags, page-1, count, base64, showfull)
# Handling for limiters # Handling for limiters
if base64: if base64:
if showfull: if showfull:
@@ -139,7 +150,7 @@ def base64ify(url):
gelbooru_api_url = "https://gelbooru.com/index.php?page=dapi&s=post&q=index&tags={}&pid={}&limit={}" gelbooru_api_url = "https://gelbooru.com/index.php?page=dapi&s=post&q=index&tags={}&pid={}&limit={}"
gelbooru_view_url = "https://gelbooru.com/index.php?page=post&s=view&id={}" gelbooru_view_url = "https://gelbooru.com/index.php?page=post&s=view&id={}"
def trap(tags, page, count, base64, showfull): def build_data(tags, page, count, base64, showfull):
# URL Building & Request # URL Building & Request
temp = gelbooru_api_url.format(tags, page, count) temp = gelbooru_api_url.format(tags, page, count)
response = requests.get(temp).text response = requests.get(temp).text

View File

@@ -1,23 +1,35 @@
console.log('loaded') console.log('Loaded');
$('.delete').each(function (e) {
console.log('Each');
$(this).click(function() {
$(this).parent().parent().fadeOut();
console.log('Parent');
});
});
console.log('1');
$('.delete').click(function () {
console.log('Received Click');
});
// Close mobile & tablet menu on item click // Close mobile & tablet menu on item click
$('.navbar-item').each(function (e) { $('.navbar-item').each(function (e) {
$(this).click(function () { $(this).click(function () {
if ($('#navbar-burger-id').hasClass('is-active')) { if ($('#navbar-burger-id').hasClass('is-active')) {
$('#navbar-burger-id').removeClass('is-active'); $('#navbar-burger-id').removeClass('is-active');
$('#navbar-menu-id').removeClass('is-active'); $('#navbar-menu-id').removeClass('is-active');
} }
}); });
}); });
// Open or Close mobile & tablet menu // Open or Close mobile & tablet menu
$('#navbar-burger-id').click(function () { $('#navbar-burger-id').click(function () {
console.log("hit") console.log("hit")
if ($('#navbar-burger-id').hasClass('is-active')) { if ($('#navbar-burger-id').hasClass('is-active')) {
$('#navbar-burger-id').removeClass('is-active'); $('#navbar-burger-id').removeClass('is-active');
$('#navbar-menu-id').removeClass('is-active'); $('#navbar-menu-id').removeClass('is-active');
} else { } else {
$('#navbar-burger-id').addClass('is-active'); $('#navbar-burger-id').addClass('is-active');
$('#navbar-menu-id').addClass('is-active'); $('#navbar-menu-id').addClass('is-active');
} }
}); });

View File

@@ -1,3 +1,21 @@
{#
Title = Title of the Message Box
Text = Text inside the Message Box
Color = Bulma Color Type of the Message Box
#}
{% macro flash(title, text, color) -%}
<article class="message is-small {{ color }}">
<div class="message-header">
<span class="fas fa-exclamation-triangle"></span>
{{ title }}
<button id="message-box-delete" class="delete" aria-label="delete"></button>
</div>
<div class="message-body">
{{ text }}
</div>
</article>
{%- endmacro %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@@ -12,7 +30,8 @@
{% block head %} {% block head %}
<link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css">
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script> <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<style type="text/css"> <style type="text/css">
/* Single line word breaking for content */ /* Single line word breaking for content */
@@ -24,6 +43,11 @@
font-family: 'Raleway', sans-serif; font-family: 'Raleway', sans-serif;
font-size: 1.75rem; font-size: 1.75rem;
} }
.is-vertical-center {
vertical-align: middle;
padding: 1rem;
}
</style> </style>
{% endblock head %} {% endblock head %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma-divider@2.0.1/dist/css/bulma-divider.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma-divider@2.0.1/dist/css/bulma-divider.min.css">
@@ -53,25 +77,43 @@
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
<div class="navbar-item"> {% block navbarend %}
<div class="buttons"> <div id="navbar-dropdown" class="navbar-item has-dropdown is-hoverable">
{% block navbarend %} <a class="navbar-link is-mobile">
{% if current_user.is_anonymous %} <figure style="padding: 0.5rem;" class="image is-48x48">
{% set default = 'https://via.placeholder.com/256' %}
{% if not hideSignup %} <img class=""
<a href="{{ url_for('signup') }}" class="button is-outlined is-info">Signup</a> src="{{ current_user.profile_picture or default if current_user.is_authenticated else default }}">
{% endif %} </figure>
{% if not hideLogin %} <strong>
<a href="{{ url_for('login') }}" class="button is-outlined is-info">Login</a> Hello, {{ current_user.username if current_user.is_authenticated else 'Anonymous' }}
{% endif %} </strong>
</a>
<div class="navbar-dropdown">
{% if current_user.is_authenticated %}
{# <a class="navbar-item" href="{{ url_for('profile') }}">
Profile
</a> #}
<a class="navbar-item" href="{{ get_hidden() }}">
Hidden
</a>
<hr class="navbar-divider">
<a class="navbar-item" href="{{ url_for('logout') }}">
Logout
</a>
{% else %} {% else %}
<a href="{{ url_for('logout') }}" class="button is-outlined is-info">Logout</a> <a class="navbar-item" href="{{ url_for('login') }}">
Login
</a>
<a class="navbar-item" href="{{ url_for('register') }}">
Register
</a>
{% endif %} {% endif %}
{% endblock navbarend %}
</div> </div>
</div> </div>
{% endblock navbarend %}
</div> </div>
</div> </div>
</nav> </nav>

View File

@@ -99,7 +99,7 @@
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<div class="card-header-title"> <div class="card-header-title">
Image #{{ image.index }} <a href="{{ image.view }}"><sup class="sup">source</sup></a> Image #{{ image.index }}<a href="{{ image.view }}"><sup class="sup">(source)</sup></a>
</div> </div>
</div> </div>
<div class="card-image"> <div class="card-image">

View File

@@ -1,17 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% macro error(text, title='Error') -%}
<article class="message is-small is-danger">
<div class="message-header">
<p>{{ title }}</p>
<button class="delete" aria-label="delete"></button>
</div>
<div class="message-body">
{{ text }}
</div>
</article>
{%- endmacro %}
{% block body %} {% block body %}
<!-- Login Section --> <!-- Login Section -->
<section class="section section-padding"> <section class="section section-padding">
@@ -26,14 +14,19 @@
<div class="card-content"> <div class="card-content">
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% for message in messages %} {% for message in messages %}
{{ error(message, title='Error - Login Error') }} {% if category == 'error' %}
{{ flash(title='Error - Login Error', text=message, color='is-danger') }}
{% else %}
{# Will work fine for most other flashed messages #}
{{ flash(title='Info', text=message, color='is-info' )}}
{% endif %}
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
{% for formerror in form.username.errors %} {% for formerror in form.username.errors %}
{{ error(formerror, title='Error - Username') }} {{ flash(title='Error - Username', text=formerror, color='is-danger') }}
{% endfor %} {% endfor %}
{% for formerror in form.password.errors %} {% for formerror in form.password.errors %}
{{ error(formerror, title='Error - Password') }} {{ flash(title='Error - Password', text=formerror, color='is-danger') }}
{% endfor %} {% endfor %}
<!-- Sign-in Form--> <!-- Sign-in Form-->
<form action="" method="post" novalidate> <form action="" method="post" novalidate>

View File

@@ -14,14 +14,23 @@
<div class="card-content"> <div class="card-content">
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% for message in messages %} {% for message in messages %}
{{ error(message, title='Error - Login Error') }} {{ flash(title='Error - Registration Error', text=formerror, color='is-danger') }}
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
{% for formerror in form.username.errors %} {% for formerror in form.username.errors %}
{{ error(formerror, title='Error - Username') }} {{ flash(title='Error - Username', text=formerror, color='is-danger') }}
{% endfor %} {% endfor %}
{% for formerror in form.email.errors %}
{{ flash(title='Error - Email', text=formerror, color='is-danger') }}
{% endfor %}
{% for formerror in form.password.errors %} {% for formerror in form.password.errors %}
{{ error(formerror, title='Error - Password') }} {{ flash(title='Error - Password', text=formerror, color='is-danger') }}
{% endfor %}
{% for formerror in form.password2.errors %}
{{ flash(title='Error - Repeat Password', text=formerror, color='is-danger') }}
{% endfor %} {% endfor %}
<!-- Sign-in Form--> <!-- Sign-in Form-->
<form action="" method="post" novalidate> <form action="" method="post" novalidate>
@@ -32,28 +41,42 @@
<p class="control has-icons-left"> <p class="control has-icons-left">
{{ form.username(size=32, class_="input", placeholder="Username") }} {{ form.username(size=32, class_="input", placeholder="Username") }}
<span class="icon is-small is-left"> <span class="icon is-small is-left">
<i class="fas fa-lock"></i> <i class="fas fa-user"></i>
</span> </span>
</p> </p>
<!-- Password Field -->
</div> </div>
<!-- Email Field -->
<div class="field"> <div class="field">
{{ form.password.label }} {{ form.email.label }}
<p class="control has-icons-left"> <p class="control has-icons-left">
{{ form.password(size=32, class_="input", placeholder="Password") }} {{ form.email(size=64, class_="input", placeholder="Email Address") }}
<span class="icon is-small is-left"> <span class="icon is-small is-left">
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
</span> </span>
</p> </p>
</div> </div>
<!-- Password Field -->
<div class="field">
{{ form.password.label }}
<p class="control has-icons-left">
{{ form.password(size=32, class_="input", placeholder="Password") }}
<span class="icon is-small is-left">
<i class="fas fa-lock"></i>
</span>
</p>
</div>
<!-- Password2 Field -->
<div class="field">
{{ form.password2.label }}
<p class="control has-icons-left">
{{ form.password2(size=32, class_="input", placeholder="Repeat Password") }}
<span class="icon is-small is-left">
<i class="fas fa-lock"></i>
</span>
</p>
</div>
<!-- Checkbox/Button Field --> <!-- Checkbox/Button Field -->
<div class="columns is-mobile is-vcentered is-centered"> <div class="columns is-mobile is-vcentered is-centered">
<!-- Remember Me Checkbox Field -->
<div class="column is-6">
<label class="checkbox">
{{ form.remember_me(class_="checkbox") }} {{ form.remember_me.label }}</p>
<label>
</div>
<div class="column is-2"></div> <div class="column is-2"></div>
<!-- Submit Button Field --> <!-- Submit Button Field -->
<div class="column is-4"> <div class="column is-4">
@@ -71,5 +94,4 @@
</div> </div>
</section> </section>
<!-- End Login Section --> <!-- End Login Section -->
{% endblock body %} {% endblock body %}