--- /dev/null
+{% block footer %}
+ <div class="copyright">© Copyright 2011-2012, <a href="http://less.ly/" target="_blank">less.ly</a>.</div>
+{% endblock footer %}
--- /dev/null
+{% block header %}
+
+ <div class="auth">
+ {% if not session.logged_in %}
+ <a class="login" href="{{ url_for('login') }}">login</a>
+ {% else %}
+ <a class="logout" href="{{ url_for('logout') }}">logout</a>
+ {% endif %}
+ </div>
+
+ {% set messages = get_flashed_messages() %}
+ {% if messages %}
+ <div class="messages">
+ {% for message in messages %}
+ <div class="flash">{{ message }}</div>
+ {% endfor %}
+ </div>
+ {% endif %}
+
+{% endblock header %}
--- /dev/null
+{% extends "layout.html" %}
+{% block title %}Home{% endblock %}
+{% block content %}
+
+ {% if session.logged_in %}
+ <h2>hi!</h2>
+ {% endif %}
+
+ <ul class="haikus">
+ {% for haiku in haikus %}
+ <li class="haiku">
+ <h2>{{ haiku.title }}</h2>
+ {{ haiku.text | safe }}
+ </li>
+ {% else %}
+ <li><em>Unbelievable. No haikus so far!</em></li>
+ {% endfor %}
+ </ul>
+
+{% endblock %}
\ No newline at end of file
--- /dev/null
+<!doctype html>
+<html>
+<head>
+{% block head %}
+ <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='reset.min.css') }}">
+ <title>{% block title %}Welcome!{% endblock %} | CrisisHaiku</title>
+{% endblock %}
+</head>
+<body class="{{ body_classes }} {{ 'logged_in' if session.logged_in else 'not_logged_in' }}">
+ <header>
+ {% include 'header.html' %}
+ </header>
+ <div id="content">
+ {% block content %}{% endblock %}
+ </div>
+ <footer>
+ {% include 'footer.html' %}
+ </footer>
+</body>
+</html>
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from . import decorators
+from .home import *
+from .auth import *
+from .report import *
+
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
+__all__ = ('login', 'login_twitter', 'oauth_authorized', 'logout',)
from flask import (
request, session, url_for, redirect, abort,
from crisishaiku.model import User, Haiku, Section
# from crisishaiku.model import User, Haiku, Section, Comment, Like, Target
-STATIC = path(app.root_path)/'static'
-
+from .decorators import *
-
-@app.route('/')
-def index():
- return 'Hello World!'
+STATIC = path(app.root_path)/'static'
-@app.route('/favicon.ico')
-def favicon():
- return send_from_directory(STATIC, 'favicon.ico', mimetype='image/vnd.microsoft.icon')
+### User Auth
-@app.route('/login')
+@app.route('/login', methods=['GET', 'POST'])
def login():
+ error = None
+ if request.method == 'POST':
+ # FIXME: this is sample code
+ if request.form['username'] != 'test':
+ error = 'Invalid username'
+ elif request.form['password'] != 'loldongs':
+ error = 'Invalid password'
+ else:
+ session['logged_in'] = True
+ flash('You were logged in')
+ return redirect(url_for('home'))
+ return render_template('login.html', error=error)
+
+@app.route('/login/twitter')
+def login_twitter():
return twitter.authorize(callback=url_for('oauth_authorized',
next=request.args.get('next') or request.referrer or None))
@app.route('/oauth-authorized')
@twitter.authorized_handler
def oauth_authorized(res):
- next_url = request.args.get('next') or url_for('index')
+ next_url = request.args.get('next') or url_for('home')
if res is None:
flash(u'You denied the request to sign in.')
return redirect('/login')
flash('You were signed in as %s' % res['screen_name'])
return redirect(next_url)
+
+@app.route('/logout')
+def logout():
+ session.pop('logged_in', None)
+ flash('You were logged out')
+ return redirect(url_for('home'))
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+__all__ = ('login_required', 'templated', 'cached',)
+
+from functools import wraps
+from flask import (
+ request, session, url_for, redirect, abort,
+ render_template, g, flash, send_from_directory, )
+from path import path
+
+
+def login_required(f):
+ @wraps(f)
+ def decorated_function(*args, **kwargs):
+ if g.user is None:
+ return redirect(url_for('login', next=request.url))
+ return f(*args, **kwargs)
+ return decorated_function
+
+
+def templated(template=None):
+ def decorator(f):
+ @wraps(f)
+ def decorated_function(*args, **kwargs):
+ template_name = template
+ if template_name is None:
+ template_name = request.endpoint \
+ .replace('.', '/') + '.html'
+ ctx = f(*args, **kwargs)
+ if ctx is None:
+ ctx = {}
+ elif not isinstance(ctx, dict):
+ return ctx
+ return render_template(template_name, **ctx)
+ return decorated_function
+ return decorator
+
+
+try:
+ from crisishaiku import cache
+ def cached(timeout=5*60, key='view/%s'):
+ def decorator(f):
+ @wraps(f)
+ def decorated_function(*args, **kwargs):
+ cache_key = key % request.path
+ rv = cache.get(cache_key)
+ if rv is not None:
+ return rv
+ rv = f(*args, **kwargs)
+ cache.set(cache_key, rv, timeout=timeout)
+ return rv
+ return decorated_function
+ return decorator
+
+except ImportError:
+ # from crisishaiku import app
+ # app.logger.info('Caching disabled!')
+ def identity(f): return f
+ def cached(timeout=5*60, key='view/%s'):
+ return identity
+
+
--- /dev/null
+# -*- coding: utf-8 -*-
+__all__ = ('favicon', 'home',)
+
+from flask import (
+ request, session, url_for, redirect, abort,
+ render_template, g, flash, send_from_directory, )
+from path import path
+
+from crisishaiku import app, db, crypt, twitter
+from crisishaiku.model import User, Haiku, Section
+# from crisishaiku.model import User, Haiku, Section, Comment, Like, Target
+
+from .decorators import *
+
+STATIC = path(app.root_path)/'static'
+
+
+
+@app.route('/favicon.ico')
+def favicon():
+ return send_from_directory(STATIC, 'favicon.ico', mimetype='image/vnd.microsoft.icon')
+
+@app.route('/')
+@templated() # template inferred from endpoint function name
+def home():
+ return dict(haikus=[], body_classes='home')
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+__all__ = ('report', 'report_chapter',)
+
+from flask import (
+ request, session, url_for, redirect, abort,
+ render_template, g, flash, send_from_directory, )
+from path import path
+
+from crisishaiku import app, db, crypt, twitter
+from crisishaiku.model import User, Haiku, Section
+# from crisishaiku.model import User, Haiku, Section, Comment, Like, Target
+
+from .decorators import *
+
+STATIC = path(app.root_path)/'static'
+
+
+
+### Report pages
+
+@app.route('/report')
+@app.route('/report/toc')
+@templated() # template inferred from endpoint function name
+def report():
+ return {}
+
+@app.route('/report/<chapter>/')
+@app.route('/report/chapter/<int:chapter_num>/')
+@templated()
+def report_chapter(chapter=None, chapter_num=None):
+ return {}
+
+