Initial commit

This commit is contained in:
Andros Fenollosa
2016-09-17 12:21:42 +02:00
parent 3b8b91b76a
commit 7e878f6fe1
22 changed files with 817 additions and 0 deletions

164
src/app.py Normal file
View File

@ -0,0 +1,164 @@
from flask import Flask, render_template, request, url_for, redirect, session
from functools import wraps
from sqlalchemy import or_
from markdown import markdown
from database import db, User, Note
app = Flask(__name__)
# Decoration: check login in session
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user_id' not in session:
session.clear()
return redirect(url_for('index'))
return f(*args, **kwargs)
return decorated_function
@app.route('/')
def index(data=None):
return render_template('items/login.html', data=data)
@app.route('/login', methods=['POST'])
def login():
data = dict()
if request.form['email'] and request.form['password']:
# Checks if the user exists
data['email'] = request.form['email']
data['password'] = request.form['password']
my_user = User.query.filter_by(
email=data['email'], password=data['password']).first()
if my_user:
# Create user session
session['user_id'] = my_user.id
session['user_email'] = my_user.email
return redirect(url_for('dashboard'))
else:
data['error'] = True
else:
data['error'] = True
return index(data)
@app.route('/logout')
@login_required
def logout():
# Clear sessions
session.clear()
return redirect(url_for('index'))
@app.route('/dashboard')
@login_required
def dashboard(my_param_note=None):
my_main_note = None
# Searchs
my_notes = my_param_note
if not my_notes:
# Nothing found
my_notes = Note.query.order_by(Note.id.desc()).all()
if my_notes:
# Show first result
my_main_note = my_notes[0]
# Show first note
if request.args.get('id'):
my_note_temp = Note.query.filter_by(id=request.args.get('id')).first()
# Is there any note in the database?
if my_note_temp:
my_main_note = my_note_temp
# Data for template
data = dict()
data['notes'] = my_notes
data['main_note'] = my_main_note
data['markdown'] = markdown
return render_template('items/dashboard.html', data=data)
@app.route('/search')
@login_required
def search():
q = request.args.get('q')
return dashboard(Note.query.filter(
or_(Note.title.like('%' + q + '%'), Note.text.like('%' + q + '%')
)).all())
@app.route('/new')
@login_required
def new():
return render_template('items/new.html')
@app.route('/new/save', methods=['POST'])
@login_required
def save_note():
myNote = Note(request.form['title'], request.form['text'])
# Create
db.session.add(myNote)
db.session.commit()
return redirect(url_for('dashboard'))
@app.route('/edit')
@login_required
def edit(data=None):
id = request.args.get('id')
my_note = Note.query.filter_by(id=id).first()
data = dict()
data['main_note'] = my_note
return render_template('items/edit.html', data=data)
@app.route('/edit_note', methods=['POST'])
@login_required
def edit_note(data=None):
if request.form['id']:
# Update
my_note = Note.query.filter_by(id=request.form['id']).first()
my_note.title = request.form['title']
my_note.text = request.form['text']
db.session.commit()
return redirect(url_for('dashboard'))
@app.route('/delete')
@login_required
def delete():
id = request.args.get('id')
my_note = Note.query.filter_by(id=id).first()
data = dict()
data['main_note'] = my_note
data['markdown'] = markdown
return render_template('items/delete.html', data=data)
@app.route('/delete_note')
@login_required
def delete_note():
id = request.args.get('id')
# Delete
my_note = Note.query.filter_by(id=id).first()
db.session.delete(my_note)
db.session.commit()
return redirect(url_for('dashboard', id=id))
# App
if __name__ == "__main__":
app.secret_key = 'secret'
app.run()

32
src/database.py Normal file
View File

@ -0,0 +1,32 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.sqlite'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True)
password = db.Column(db.String(32))
def __init__(self, email, password):
self.email = email
self.password = password
def __repr__(self):
return '<User {email}>'.format(email=self.email)
class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), unique=True)
text = db.Column(db.Text())
def __init__(self, title, text):
self.title = title
self.text = text
def __repr__(self):
return '<Note {title}>'.format(title=self.title)

View File

@ -0,0 +1,62 @@
{% extends 'layouts/master.html' %}
{% block contain %}
<div class="row">
<div class="col-sm-4">
<form action="{{ url_for('search') }}" method="get">
<div class="input-group">
<input name="q" type="text" class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-secondary" type="submit">Go!</button>
</span>
</div>
</form>
</div>
<div class="col-sm-8 text-right">
<strong>{{ session['user_email'] }}</strong>
<a href="{{ url_for('logout') }}" class="btn btn-primary">Logout</a>
</div>
</div>
<br/>
<div class="row">
<div class="col-xs-6">
<a href="{{ url_for('new') }}" class="btn btn-success">New</a>
</div>
<div class="col-xs-6 text-right">
{%- if data.main_note -%}
<a href="{{ url_for('edit', id=data.main_note.id) }}" class="btn btn-warning">Edit</a>
<a href="{{ url_for('delete', id=data.main_note.id) }}" class="btn btn-danger">Delete</a>
{% endif %}
</div>
</div>
<br/>
<div class="row">
<div class="col-xs-4">
<div class="list-group">
{% for note in data.notes %}
<a href="{{ url_for('dashboard', id=note.id) }}" class="list-group-item">
<h4 class="list-group-item-heading">{{ data.markdown(note.title)|safe }}</h4>
<p class="list-group-item-text">
{%- if note.text|length > 140 -%}
{{ data.markdown(note.text[:140] + '...')|safe }}
{% else %}
{{ data.markdown(note.text)|safe }}
{% endif %}
</p>
</a>
{% endfor %}
</div>
</div>
<div class="col-xs-8">
{%- if data.main_note -%}
<div class="panel panel-default">
<div class="panel-body">
<h3>
{{ data.markdown(data.main_note.title)|safe }}
</h3>
{{ data.markdown(data.main_note.text)|safe }}
</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends 'layouts/master.html' %}
{% block contain %}
<div class="row">
<div class="col-sm-6"><h4>Do you want to delete this note?</h4></div>
<div class="col-sm-6 text-right">
<a href="{{ url_for('dashboard') }}" class="btn btn-danger">No, please!</a>
<a href="{{ url_for('delete_note', id=data.main_note.id) }}" class="btn btn-success">Yes</a>
</div>
</div>
<br/>
<div class="row">
<div class="panel panel-default">
<div class="panel-body">
<h3>
{{ data.markdown(data.main_note.title)|safe }}
</h3>
{{ data.markdown(data.main_note.text)|safe }}
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% extends 'layouts/master.html' %}
{% block contain %}
<div class="row text-right">
<strong>{{ session['user_email'] }}</strong>
<a href="{{ url_for('logout') }}" class="btn btn-primary">Logout</a>
</div>
<br/>
<form action="{{ url_for('edit_note') }}" method="post">
<input name="id" type="hidden" value="{{ data.main_note.id }}"/>
<div class="row">
<div class="col-xs-6">
<a href="{{ url_for('dashboard') }}" class="btn btn-danger">Back</a>
</div>
<div class="col-xs-6 text-right">
<button type="submit" class="btn btn-success">Edit</button>
</div>
</div>
<br/>
<div class="row">
<input type="text" name="title" class="form-control" required value="{{ data.main_note.title }}">
<textarea name="text" class="form-control" rows="10" required>{{ data.main_note.text }}</textarea>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends 'layouts/master.html' %}
{% block contain %}
{% if data['error'] %}
<div class="row">
<div class="alert alert-danger" role="alert">
<strong>Error</strong> Email or password incorrect
</div>
</div>
{% endif %}
<div class="row">
<form method="post" action="{{ url_for('login') }}">
<div class="form-group">
<input type="email" class="form-control" id="email" placeholder="Email" name="email" value="{{ data['email'] }}">
</div>
<div class="form-group">
<input type="password" class="form-control" id="password" placeholder="Password" name="password" value="{{ data['password'] }}">
</div>
<button type="submit" class="btn btn-default center-block">Login</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends 'layouts/master.html' %}
{% block contain %}
<div class="row text-right">
<strong>{{ session['user_email'] }}</strong>
<a href="{{ url_for('logout') }}" class="btn btn-primary">Logout</a>
</div>
<br/>
<form action="{{ url_for('save_note') }}" method="post">
<div class="row">
<div class="col-xs-6">
<a href="{{ url_for('dashboard') }}" class="btn btn-danger">Back</a>
</div>
<div class="col-xs-6 text-right">
<button type="submit" class="btn btn-success">Save</button>
</div>
</div>
<br/>
<div class="row">
<input type="text" name="title" class="form-control" placeholder="Title..." required>
<textarea name="text" class="form-control" rows="10" placeholder="Your text..." required></textarea>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<link href="https://bootswatch.com/flatly/bootstrap.min.css" rel="stylesheet">
<title>Flask-note</title>
</head>
<body>
<div class="container">
<div class="page-header">
<h1 class="text-center">
<small>Flask-note</small>
</h1>
</div>
<div class="row">
{% block contain %}
{% endblock %}
</div>
</div>
</body>
</html>