commit 830b64f0e1d1abb6c7009c88398274132e86dfc6 Author: lars Date: Fri Apr 20 01:50:59 2012 +0000 renamed directory diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..2570676 --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ +SetHandler wsgi-script +Options ExecCGI + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..0aa3b81 --- /dev/null +++ b/README.txt @@ -0,0 +1,14 @@ += tycker - a web-based ticker input form = + +tycker offers a very simple interface to be used for entering ticker information. +Each entry consists of the current time, a title and content. +The content may be written in wikicreole syntax: +http://www.wikicreole.org/imageServlet?page=CheatSheet%2Fcreole_cheat_sheet.png + +The data items are stored in an sqlite database by default. Other options +(mysql/postgres) are easily configurable, as well. + +The result is processed via the template "display.html". Adjust this file to +generate the desired layout. +Generated html files are stored in the parent directory of tycker's base directory. + diff --git a/templates/admin_show_entries.html b/templates/admin_show_entries.html new file mode 100644 index 0000000..3ff0404 --- /dev/null +++ b/templates/admin_show_entries.html @@ -0,0 +1,42 @@ + + + + Admin Ticker + + + + + +

+ + static website +

+ + + + + + + + + + + +
TimestampTitleContent
+ + +
+ + + diff --git a/templates/display.html b/templates/display.html new file mode 100644 index 0000000..8152d2b --- /dev/null +++ b/templates/display.html @@ -0,0 +1,23 @@ + + + + Ticker + + + + + + ${nav_links()} +
    +
  • + ${show_timestamp(entry['timestamp'])}
    + ${entry['title']}: + ${formatter(entry['content'])} +
  • +
+ ${nav_links()} + + + diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 0000000..13dc1a1 --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,54 @@ + + + + + + + ${select('*|text()')} + + + + ") and html.endswith("

"): + html = html[3:-4] + return genshi.Markup(html) + + + TODAY_FORMAT = "%H:%M" + FULL_FORMAT = "%d.%m.%y %H:%M" + last_day = datetime.datetime.today() - datetime.timedelta(days=1) + def show_timestamp(date): + if date <= last_day: + template = TODAY_FORMAT + else: + template = FULL_FORMAT + return date.strftime(template) + + def nav_links(): + result = [] + if prev_link: + result.append('aktuellere' % prev_link) + if next_link: + result.append('ältere' % next_link) + return genshi.Markup(" | ".join(result)) + ?> + + + + + ${select('*|text()')} + + + + + diff --git a/tycker.py b/tycker.py new file mode 100644 index 0000000..d194fcb --- /dev/null +++ b/tycker.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +# the basedir is the parent dir of the location of this script +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Somehow "/usr/lib/python2.X/dist-packages" is missing from sys.path - thus bobo is not found. +# This applies to libapache2-mod-wsgi (3.3-2). +import sys +for path in list(sys.path): + options = [] + parent_dir, last_dir = os.path.split(path) + options.append(os.path.join(path, "dist-packages")) + options.append(os.path.join(parent_dir, "pymodules", last_dir)) + for option in options: + if os.path.isdir(option): + sys.path.append(option) + +DATE_FORMAT = "%H:%M %d.%m.%Y" +PAGE_SIZE = 4 +FILENAME_TEMPLATE = "ticker%d.html" +FULL_PATH_FILENAME_TEMPLATE = os.path.join(BASE_DIR, os.path.pardir, FILENAME_TEMPLATE) +BASE_URL = "./" + +import datetime +import bobo +import sqlobject +import genshi.template + + +db_uri = "sqlite:///%s/tycker.sqlite" % BASE_DIR +sqlobject.sqlhub.processConnection = sqlobject.connectionForURI(db_uri) + +loader = genshi.template.TemplateLoader(os.path.join(BASE_DIR, 'templates'), auto_reload=True) + + +class Entry(sqlobject.SQLObject): + timestamp = sqlobject.DateTimeCol() + title = sqlobject.UnicodeCol() + content = sqlobject.UnicodeCol() + + +def render(filename, **values): + stream = loader.load(filename).generate(**values) + return stream.render("html", doctype="html") + +def get_filename(index): + return FULL_PATH_FILENAME_TEMPLATE % index + +def get_link(index): + return FILENAME_TEMPLATE % index + +def update_static_html(): + entries = list(Entry.select().orderBy("-timestamp")) + file_index = 1 + while entries: + current = entries[:PAGE_SIZE] + entries = entries[PAGE_SIZE:] + current_filename = get_filename(file_index) + if file_index > 1: + previous_link = get_link(file_index - 1) + else: + previous_link = None + if entries: + next_link = get_link(file_index + 1) + else: + next_link = None + values = { "entries": current, + "prev_link": previous_link, + "next_link": next_link, + } + rendered = render("display.html", **values) + open(current_filename, "w").write(rendered) + file_index += 1 + +@bobo.query('/submit') +def submit_entry(entry_id=None, title=None, content=None, date=None): + title = title.strip() + content = content.strip() + if not all((title, content, date)): + return bobo.redirect(BASE_URL) + try: + date = datetime.datetime.strptime(date, DATE_FORMAT) + except ValueError: + bobo.redirect(BASE_URL) + if entry_id is None: + Entry(title=title, content=content, timestamp=date) + else: + try: + entry = Entry.get(entry_id) + except sqlobject.SQLObjectNotFound: + bobo.redirect(BASE_URL) + entry.title = title + entry.content = content + entry.date = date + update_static_html() + return bobo.redirect(BASE_URL) + +@bobo.query('/delete') +def delete_entry(entry_id): + try: + Entry.delete(entry_id) + except sqlobject.SQLObjectNotFound: + bobo.redirect(BASE_URL) + update_static_html() + return bobo.redirect(BASE_URL) + +@bobo.query('/generate') +def generate_static(): + update_static_html() + return bobo.redirect(BASE_URL) + +@bobo.query('/') +def show_entries(): + values = {} + values["entries"] = Entry.select().orderBy("-timestamp") + values["date_format"] = DATE_FORMAT + values["static_url"] = get_link(1) + return render("admin_show_entries.html", **values) + +@bobo.query('') +def redirect_base(): + return bobo.redirect(os.path.split(__file__)[1] + "/") + + +for table in (Entry, ): + #table.dropTable() + if not table.tableExists(): + table.createTable() + +application = bobo.Application(bobo_resources=__name__) +