renamed directory

This commit is contained in:
lars 2012-04-20 01:50:59 +00:00
commit 830b64f0e1
6 changed files with 269 additions and 0 deletions

3
.htaccess Normal file
View file

@ -0,0 +1,3 @@
SetHandler wsgi-script
Options ExecCGI

14
README.txt Normal file
View file

@ -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.

View file

@ -0,0 +1,42 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.html" />
<head>
<title>Admin Ticker</title>
</head>
<body>
<?python
import datetime
now = datetime.datetime.now()
?>
<p><form action="generate" method="GET">
<input type="submit" value="Generate" />
<i><a href="../../${static_url}" title="static website">static website</a></i>
</form></p>
<table border="1">
<tr><th>Timestamp</th><th>Title</th><th>Content</th></tr>
<tr><form action="submit" method="GET">
<td><input type="text" size="15" name="date" value="${now.strftime(date_format)}" /></td>
<td><input type="text" size="25" name="title" value="" autofocus="autofocus" /></td>
<td><textarea name="content" rows="8" cols="80" /></td>
<td><input type="submit" value="Create" /></td>
</form></tr>
<tr py:for="entry in entries"><form action="submit" method="GET">
<td><input type="text" size="15" name="date" value="${entry['timestamp'].strftime(date_format)}" /></td>
<td><input type="text" size="25" name="title" value="${entry['title']}" /></td>
<td><textarea name="content" rows="8" cols="80">${entry['content']}</textarea></td>
<td><input type="hidden" name="entry_id" value="${entry.id}" /><input type="submit" value="Update" /></td>
</form>
<td><form action="delete" method="GET">
<input type="hidden" name="entry_id" value="${entry.id}" />
<input type="submit" value="Delete" />
</form></td>
</tr>
</table>
</body>
</html>

23
templates/display.html Normal file
View file

@ -0,0 +1,23 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.html" />
<head>
<title>Ticker</title>
</head>
<body>
${nav_links()}
<ul>
<li py:for="entry in entries">
<span class="timestamp">${show_timestamp(entry['timestamp'])}</span><br/>
<span class="title">${entry['title']}:</span>
<span class="content">${formatter(entry['content'])}</span>
</li>
</ul>
${nav_links()}
</body>
</html>

54
templates/layout.html Normal file
View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/" py:strip="">
<py:match path="head" once="true">
<head py:attrs="select('@*')">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
${select('*|text()')}
</head>
</py:match>
<?python
import creoleparser
import genshi
import datetime
def formatter(text):
if not text:
return u""
text = text.replace("\\", "\\\\")
html = creoleparser.text2html(text, encoding=None).strip()
if html.startswith("<p>") and html.endswith("</p>"):
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('<a href="%s" title="zeige neuere Eintr&auml;ge">aktuellere</a>' % prev_link)
if next_link:
result.append('<a href="%s" title="zeige &auml;ltere Eintr&auml;ge">&auml;ltere</a>' % next_link)
return genshi.Markup(" | ".join(result))
?>
<py:match path="body" once="true">
<body py:attrs="select('@*')">
${select('*|text()')}
</body>
</py:match>
</html>

133
tycker.py Normal file
View file

@ -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__)