mirror of
https://github.com/Xevion/v1.xevion.dev.git
synced 2025-12-07 18:08:47 -06:00
adding all previous files for init commit
This commit is contained in:
18
app/__init__.py
Normal file
18
app/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Main Flask and Flask configs
|
||||||
|
from flask import Flask
|
||||||
|
from config import Config
|
||||||
|
# Flask Extensions
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_migrate import Migrate
|
||||||
|
from flask_login import LoginManager
|
||||||
|
|
||||||
|
# App & App config setup
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_object(Config)
|
||||||
|
# App extension setup
|
||||||
|
login = LoginManager(app)
|
||||||
|
login.login_view = 'login'
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
migrate = Migrate(app, db)
|
||||||
|
|
||||||
|
from app import routes, models
|
||||||
9
app/forms.py
Normal file
9
app/forms.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, PasswordField, BooleanField, SubmitField
|
||||||
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
class LoginForm(FlaskForm):
|
||||||
|
username = StringField('Username', validators=[DataRequired()])
|
||||||
|
password = PasswordField('Password', validators=[DataRequired()])
|
||||||
|
remember_me = BooleanField('Remember Me')
|
||||||
|
submit = SubmitField('Sign in')
|
||||||
34
app/models.py
Normal file
34
app/models.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from flask_login import UserMixin
|
||||||
|
from datetime import datetime
|
||||||
|
from app import db, login
|
||||||
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
|
|
||||||
|
@login.user_loader
|
||||||
|
class User(UserMixin, db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
username = db.Column(db.String(64), index=True, unique=True)
|
||||||
|
email = db.Column(db.String(120), index=True, unique=True)
|
||||||
|
password_hash = db.Column(db.String(64))
|
||||||
|
posts = db.relationship('Post', backref='author', lazy='dynamic')
|
||||||
|
|
||||||
|
def set_password(self, password):
|
||||||
|
self.password_hash = generate_password_hash(password)
|
||||||
|
|
||||||
|
def check_password(self, password):
|
||||||
|
return check_password_hash(self.password_hash, password)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<User {}>'.format(self.username)
|
||||||
|
|
||||||
|
class Post(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
body = db.Column(db.String(140))
|
||||||
|
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<Post {}>'.format(self.body)
|
||||||
|
|
||||||
|
@login.user_loader
|
||||||
|
def load_user(id):
|
||||||
|
return User.query.get(int(id))
|
||||||
73
app/routes.py
Normal file
73
app/routes.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from app import app
|
||||||
|
from app.models import User
|
||||||
|
from app.forms import LoginForm
|
||||||
|
from werkzeug.urls import url_parse
|
||||||
|
from flask import render_template, redirect, url_for, flash, request, jsonify
|
||||||
|
from flask_login import current_user, login_user, logout_user, login_required
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import faker
|
||||||
|
import json
|
||||||
|
|
||||||
|
fake = faker.Faker()
|
||||||
|
|
||||||
|
def strgen(length): return ''.join(
|
||||||
|
random.choices(list(string.ascii_letters), k=length))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/dashboard')
|
||||||
|
def dashboard():
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@app.route('/userinfo')
|
||||||
|
@login_required
|
||||||
|
def user_info():
|
||||||
|
prepare = {
|
||||||
|
'id' : current_user.get_id(),
|
||||||
|
'email' : current_user.email,
|
||||||
|
'username' : current_user.username,
|
||||||
|
'password_hash' : current_user.password_hash,
|
||||||
|
'is_active' : current_user.is_active,
|
||||||
|
'is_anonymous' : current_user.is_anonymous,
|
||||||
|
'is_authenticated' : current_user.is_authenticated,
|
||||||
|
'metadata' : current_user.metadata.info
|
||||||
|
}
|
||||||
|
return jsonify(prepare)
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
print(current_user)
|
||||||
|
content = [{'text': fake.paragraph(nb_sentences=15),
|
||||||
|
'seed': random.randint(0, 1000),
|
||||||
|
'title': fake.word().title()}
|
||||||
|
for _ in range(10)]
|
||||||
|
return render_template('index.html', content=content)
|
||||||
|
|
||||||
|
@app.route('/signup')
|
||||||
|
@app.route('/sign-up')
|
||||||
|
def signup():
|
||||||
|
return render_template('signup.html', title='Sign Up', hideSignup=True)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
form = LoginForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
user = User.query.filter_by(username=form.username.data).first()
|
||||||
|
if user is None or not user.check_password(form.password.data):
|
||||||
|
flash('Invalid username or password')
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
login_user(user, remember=form.remember_me.data)
|
||||||
|
next_page = request.args.get('next')
|
||||||
|
if not next_page or url_parse(next_page).netloc != '':
|
||||||
|
next_page = url_for('index')
|
||||||
|
return redirect(next_page)
|
||||||
|
return render_template('login.html', title='Sign In', form=form, hideLogin=True)
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
return redirect(url_for('index'))
|
||||||
BIN
app/static/brand.png
Normal file
BIN
app/static/brand.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
6610
app/static/bulma.css
vendored
Normal file
6610
app/static/bulma.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
110
app/static/particlesjs-config.json
Normal file
110
app/static/particlesjs-config.json
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"particles": {
|
||||||
|
"number": {
|
||||||
|
"value": 80,
|
||||||
|
"density": {
|
||||||
|
"enable": true,
|
||||||
|
"value_area": 800
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"value": "#d2d2d2"
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"type": "triangle",
|
||||||
|
"stroke": {
|
||||||
|
"width": 0.2,
|
||||||
|
"color": "#666666"
|
||||||
|
},
|
||||||
|
"polygon": {
|
||||||
|
"nb_sides": 5
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"src": "img/github.svg",
|
||||||
|
"width": 100,
|
||||||
|
"height": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"opacity": {
|
||||||
|
"value": 0.5,
|
||||||
|
"random": false,
|
||||||
|
"anim": {
|
||||||
|
"enable": false,
|
||||||
|
"speed": 1,
|
||||||
|
"opacity_min": 0.1,
|
||||||
|
"sync": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"value": 3.2,
|
||||||
|
"random": true,
|
||||||
|
"anim": {
|
||||||
|
"enable": false,
|
||||||
|
"speed": 40,
|
||||||
|
"size_min": 0.1,
|
||||||
|
"sync": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"line_linked": {
|
||||||
|
"enable": true,
|
||||||
|
"distance": 150,
|
||||||
|
"color": "#c3c3c3",
|
||||||
|
"opacity": 0.4,
|
||||||
|
"width": 1
|
||||||
|
},
|
||||||
|
"move": {
|
||||||
|
"enable": true,
|
||||||
|
"speed": 6,
|
||||||
|
"direction": "none",
|
||||||
|
"random": true,
|
||||||
|
"straight": false,
|
||||||
|
"out_mode": "out",
|
||||||
|
"bounce": false,
|
||||||
|
"attract": {
|
||||||
|
"enable": false,
|
||||||
|
"rotateX": 8017.060304327614,
|
||||||
|
"rotateY": 7696.377892154509
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"interactivity": {
|
||||||
|
"detect_on": "canvas",
|
||||||
|
"events": {
|
||||||
|
"onhover": {
|
||||||
|
"enable": false,
|
||||||
|
"mode": "bubble"
|
||||||
|
},
|
||||||
|
"onclick": {
|
||||||
|
"enable": false,
|
||||||
|
"mode": "push"
|
||||||
|
},
|
||||||
|
"resize": true
|
||||||
|
},
|
||||||
|
"modes": {
|
||||||
|
"grab": {
|
||||||
|
"distance": 400,
|
||||||
|
"line_linked": {
|
||||||
|
"opacity": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bubble": {
|
||||||
|
"distance": 400,
|
||||||
|
"size": 40,
|
||||||
|
"duration": 2,
|
||||||
|
"opacity": 8,
|
||||||
|
"speed": 3
|
||||||
|
},
|
||||||
|
"repulse": {
|
||||||
|
"distance": 200,
|
||||||
|
"duration": 0.4
|
||||||
|
},
|
||||||
|
"push": {
|
||||||
|
"particles_nb": 4
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"particles_nb": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"retina_detect": true
|
||||||
|
}
|
||||||
77
app/static/style.css
Normal file
77
app/static/style.css
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/* github.com/plasticneko */
|
||||||
|
/* bulma css framework by jeremy thomas (github.com/jgthms | bulma.io) */
|
||||||
|
|
||||||
|
/* basic formatting changes */
|
||||||
|
|
||||||
|
body, .section {
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-next, .pagination-previous, .pagination-link {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-top-shadow {
|
||||||
|
background-color: #fff;
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-wrapper {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-wrapper {
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-header img, .content-header img {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.continue-reading {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-content-details {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrapper p {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.end-content-nav-wrapper {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.end-post-details {
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* edits made to the bulma framework */
|
||||||
|
|
||||||
|
/* centering card-header-title text(1):
|
||||||
|
ensures bottom shadow remains */
|
||||||
|
.card-header-fix-center {
|
||||||
|
box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* centering card-header-title text(2):
|
||||||
|
ensures the header text remains of similar quality */
|
||||||
|
.card-header-title-fix {
|
||||||
|
flex-grow: 1;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* giving corners to the box styling */
|
||||||
|
.box {
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
85
app/templates/base.html
Normal file
85
app/templates/base.html
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
{% block title %}
|
||||||
|
{% if title %}
|
||||||
|
<title>{{ title }} - Xevion.dev</title>
|
||||||
|
{% else %}
|
||||||
|
<title>Xevion.dev</title>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block head %}
|
||||||
|
<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/bulmaswatch/0.7.2/yeti/bulmaswatch.min.css"> -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma-divider@2.0.1/dist/css/bulma-divider.min.css">
|
||||||
|
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
|
||||||
|
<style type="text/css">
|
||||||
|
{% block css %}
|
||||||
|
/* Single line word breaking for content */
|
||||||
|
.word-break {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.raleway-font {
|
||||||
|
font-family: 'Raleway', sans-serif;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
{% endblock css %}
|
||||||
|
</style>
|
||||||
|
{% endblock head %}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="navbar-brand">
|
||||||
|
<a class="navbar-item raleway-font" href="{{ url_for('index') }}">
|
||||||
|
Xevion
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false"
|
||||||
|
data-target="navbarBasicExample">
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="navbarBasicExample" class="navbar-menu">
|
||||||
|
<div class="navbar-start">
|
||||||
|
{% block navbarstart %}
|
||||||
|
<a href="{{ url_for('index') }}" class="navbar-item">Home</a>
|
||||||
|
{% endblock navbarstart %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="navbar-end">
|
||||||
|
<div class="navbar-item">
|
||||||
|
<div class="buttons">
|
||||||
|
{% block navbarend %}
|
||||||
|
{% if current_user.is_anonymous %}
|
||||||
|
|
||||||
|
{% if not hideSignup %}
|
||||||
|
<a href="{{ url_for('signup') }}" class="button is-outlined is-info">Signup</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if not hideLogin %}
|
||||||
|
<a href="{{ url_for('login') }}" class="button is-outlined is-info">Login</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('logout') }}" class="button is-outlined is-info">Logout</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock navbarend %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
{% endblock body %}
|
||||||
|
|
||||||
|
</body>
|
||||||
56
app/templates/index.html
Normal file
56
app/templates/index.html
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block body %}
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<section class="hero is-fullheight-with-navbar">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="container has-text-centered">
|
||||||
|
<p class="title">
|
||||||
|
Xevion
|
||||||
|
</p>
|
||||||
|
<p class="subtitle">
|
||||||
|
Python Developer
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- End Hero Section -->
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="is-divider" data-content="Recent Projects"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Section -->
|
||||||
|
<section class="section section-padding">
|
||||||
|
<div class="container">
|
||||||
|
{% if content %}
|
||||||
|
<div class="columns is-mobile is-multiline is-centered">
|
||||||
|
|
||||||
|
{% for card in content %}
|
||||||
|
<div class="column is-5">
|
||||||
|
<!-- Card -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="card-header-title">
|
||||||
|
{{ card.title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-image">
|
||||||
|
<figure class="image">
|
||||||
|
<img src="https://picsum.photos/600/400/?random={{ card.seed }}" alt="Picsum Picture">
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="content word-break">
|
||||||
|
{{ card.text }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Card End -->
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- End Dynamic Content -->
|
||||||
|
{% endblock body %}
|
||||||
86
app/templates/login.html
Normal file
86
app/templates/login.html
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{% 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 %}
|
||||||
|
<!-- Login Section -->
|
||||||
|
<section class="section section-padding">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-mobile is-multiline is-centered">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="card-header-title">
|
||||||
|
<h1 class="title">{{ title }}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
{% with messages = get_flashed_messages() %}
|
||||||
|
{% for message in messages %}
|
||||||
|
{{ error(message, title='Error - Login Error') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
{% for formerror in form.username.errors %}
|
||||||
|
{{ error(formerror, title='Error - Username') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% for formerror in form.password.errors %}
|
||||||
|
{{ error(formerror, title='Error - Password') }}
|
||||||
|
{% endfor %}
|
||||||
|
<!-- Sign-in Form-->
|
||||||
|
<form action="" method="post" novalidate>
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<!-- Username Field -->
|
||||||
|
<div class="field">
|
||||||
|
{{ form.username.label }}
|
||||||
|
<p class="control has-icons-left">
|
||||||
|
{{ form.username(size=32, class_="input", placeholder="Username") }}
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-lock"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<!-- Password Field -->
|
||||||
|
</div>
|
||||||
|
<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-envelope"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- Checkbox/Button Field -->
|
||||||
|
<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>
|
||||||
|
<!-- Submit Button Field -->
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
{{ form.submit(class_="button is-success") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- End Login Section -->
|
||||||
|
{% endblock body %}
|
||||||
75
app/templates/signup.html
Normal file
75
app/templates/signup.html
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<!-- Login Section -->
|
||||||
|
<section class="section section-padding">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-mobile is-multiline is-centered">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="card-header-title">
|
||||||
|
<h1 class="title">{{ title }}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
{% with messages = get_flashed_messages() %}
|
||||||
|
{% for message in messages %}
|
||||||
|
{{ error(message, title='Error - Login Error') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
{% for formerror in form.username.errors %}
|
||||||
|
{{ error(formerror, title='Error - Username') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% for formerror in form.password.errors %}
|
||||||
|
{{ error(formerror, title='Error - Password') }}
|
||||||
|
{% endfor %}
|
||||||
|
<!-- Sign-in Form-->
|
||||||
|
<form action="" method="post" novalidate>
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<!-- Username Field -->
|
||||||
|
<div class="field">
|
||||||
|
{{ form.username.label }}
|
||||||
|
<p class="control has-icons-left">
|
||||||
|
{{ form.username(size=32, class_="input", placeholder="Username") }}
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-lock"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<!-- Password Field -->
|
||||||
|
</div>
|
||||||
|
<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-envelope"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- Checkbox/Button Field -->
|
||||||
|
<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>
|
||||||
|
<!-- Submit Button Field -->
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
{{ form.submit(class_="button is-success") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- End Login Section -->
|
||||||
|
|
||||||
|
{% endblock body %}
|
||||||
9
config.py
Normal file
9
config.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import os
|
||||||
|
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
class Config(object):
|
||||||
|
SECRET_KEY = os.environ.get('SECRET_KEY') or '641e30802818e6bc77d11f428675525fcbff1c22eaf1dac17525edefb4d84899'
|
||||||
|
TEMPLATES_AUTO_RELOAD=True
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
|
||||||
|
'sqlite:///' + os.path.join(basedir, 'app.db')
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
Reference in New Issue
Block a user