diff --git a/period/__init__.py b/period/__init__.py index 644b3dc..d0fb374 100644 --- a/period/__init__.py +++ b/period/__init__.py @@ -22,4 +22,14 @@ def create_app(test_config=None): def hello(): return 'Hello, World!' + from . import db + db.init_app(app) + + # from . import auth + # app.register_blueprint(auth.bp) + + from . import cycles + app.register_blueprint(cycles.bp) + app.add_url_rule('/', endpoint='index') + return app \ No newline at end of file diff --git a/period/cycles.py b/period/cycles.py new file mode 100644 index 0000000..e918863 --- /dev/null +++ b/period/cycles.py @@ -0,0 +1,59 @@ +from itertools import cycle +from tracemalloc import start +from flask import ( + Blueprint, flash, g, redirect, render_template, request, url_for +) +from werkzeug.exceptions import abort +import pendulum + +# from flaskr.auth import login_required +from period.db import get_db + +bp = Blueprint('cycles', __name__) + +@bp.route('/') +def index(): + db = get_db() + cycles = db.execute( + 'SELECT id, start_time, end_time, cycle_length' + ' FROM cycle ORDER BY start_time DESC' + ).fetchall() + return render_template('cycle/index.html', cycles=cycles) + +@bp.route('/create', methods=('GET', 'POST')) +def create(): + if request.method == 'POST': + start_time = pendulum.from_format(request.form['start_time'], 'YYYY-MM-DD') + # start_time = start_time.to_datetime_string() + try: + end_time = pendulum.from_format(request.form['end_time'], 'YYYY-MM-DD') + except ValueError: + end_time = pendulum.datetime(1900,1,1) + error = None + print(request.form['end_time']) + + if not start_time: + error = "You must provide a start date" + + if end_time > start_time: + cycle_length = (end_time - start_time).days + else: + cycle_length = (pendulum.now() - start_time).days + + if error is not None: + flash(error) + else: + db = get_db() + if end_time > start_time: + db.execute( + 'INSERT INTO cycle (start_time, end_time, cycle_length) VALUES (?, ?, ?)', + (start_time.to_datetime_string(), end_time.to_datetime_string(), cycle_length) + ) + else: + db.execute( + 'INSERT INTO cycle (start_time, cycle_length) VALUES (?, ?)', + (start_time.to_datetime_string(), cycle_length) + ) + db.commit() + return redirect(url_for('index')) + return render_template('cycle/create.html') \ No newline at end of file diff --git a/period/db.py b/period/db.py new file mode 100644 index 0000000..a0d7f9e --- /dev/null +++ b/period/db.py @@ -0,0 +1,37 @@ +import sqlite3 + +import click +from flask import current_app, g +from flask.cli import with_appcontext + +def get_db(): + if 'db' not in g: + g.db = sqlite3.connect( + current_app.config['DATABASE'], + detect_types=sqlite3.PARSE_DECLTYPES + ) + g.db.row_factory = sqlite3.Row + + return g.db + +def close_db(e=None): + db = g.pop('db', None) + + if db is not None: + db.close() + +def init_db(): + db = get_db() + + with current_app.open_resource('schema.sql') as f: + db.executescript(f.read().decode('utf8')) + +@click.command('init-db') +@with_appcontext +def init_db_command(): + init_db() + click.echo('Initializing the database.') + +def init_app(app): + app.teardown_appcontext(close_db) + app.cli.add_command(init_db_command) \ No newline at end of file diff --git a/period/schema.sql b/period/schema.sql new file mode 100644 index 0000000..0663be7 --- /dev/null +++ b/period/schema.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS cycle; + +CREATE TABLE cycle ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + start_time DATETIME, + end_time DATETIME, + cycle_length INTEGER +); \ No newline at end of file diff --git a/period/static/style.css b/period/static/style.css new file mode 100644 index 0000000..93623a4 --- /dev/null +++ b/period/static/style.css @@ -0,0 +1,26 @@ +html { font-family: sans-serif; background: #eee; padding: 1rem; } +body { max-width: 960px; margin: 0 auto; background: white; } +h1 { font-family: serif; color: #377ba8; margin: 1rem 0; } +a { color: #377ba8; } +hr { border: none; border-top: 1px solid lightgray; } +nav { background: lightgray; display: flex; align-items: center; padding: 0 0.5rem; } +nav h1 { flex: auto; margin: 0; } +nav h1 a { text-decoration: none; padding: 0.25rem 0.5rem; } +nav ul { display: flex; list-style: none; margin: 0; padding: 0; } +nav ul li a, nav ul li span, header .action { display: block; padding: 0.5rem; } +.content { padding: 0 1rem 1rem; } +.content > header { border-bottom: 1px solid lightgray; display: flex; align-items: flex-end; } +.content > header h1 { flex: auto; margin: 1rem 0 0.25rem 0; } +.flash { margin: 1em 0; padding: 1em; background: #cae6f6; border: 1px solid #377ba8; } +.post > header { display: flex; align-items: flex-end; font-size: 0.85em; } +.post > header > div:first-of-type { flex: auto; } +.post > header h1 { font-size: 1.5em; margin-bottom: 0; } +.post .about { color: slategray; font-style: italic; } +.post .body { white-space: pre-line; } +.content:last-child { margin-bottom: 0; } +.content form { margin: 1em 0; display: flex; flex-direction: column; } +.content label { font-weight: bold; margin-bottom: 0.5em; } +.content input, .content textarea { margin-bottom: 1em; } +.content textarea { min-height: 12em; resize: vertical; } +input.danger { color: #cc2f2e; } +input[type=submit] { align-self: start; min-width: 10em; } \ No newline at end of file diff --git a/period/templates/base.html b/period/templates/base.html new file mode 100644 index 0000000..794d3af --- /dev/null +++ b/period/templates/base.html @@ -0,0 +1,17 @@ + +{% block title %}{% endblock %} - Period + + +
+
+ {% block header %}{% endblock %} +
+ {% for message in get_flashed_messages() %} +
{{ message }}
+ {% endfor %} + {% block content %}{% endblock %} +
\ No newline at end of file diff --git a/period/templates/cycle/create.html b/period/templates/cycle/create.html new file mode 100644 index 0000000..360a7c9 --- /dev/null +++ b/period/templates/cycle/create.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} + +{% block header %} +

{% block title %}New Cycle{% endblock %}

+{% endblock %} + +{% block content %} +
+ + + + + +
+{% endblock %} \ No newline at end of file diff --git a/period/templates/cycle/index.html b/period/templates/cycle/index.html new file mode 100644 index 0000000..8ae4fb1 --- /dev/null +++ b/period/templates/cycle/index.html @@ -0,0 +1,22 @@ +{% extends 'base.html' %} + +{% block header %} +

{% block title %}Cycles{% endblock %}

New +{% endblock %} + +{% block content %} + {% for cycle in cycles %} +
+
+
+

{{ cycle['id'] }}

+
Started: {{ cycle['start_time'] }} and ended: {{ cycle['end_time'] }}
+
+
+

Cycle Length: {{ cycle['cycle_length'] }} days.

+
+ {% if not loop.last %} +
+ {% endif %} + {% endfor %} +{% endblock %} \ No newline at end of file