Revision 1371822e
Added by dsorber over 11 years ago
| software/bookmark_library/bmklib/lib/bookmark.py | ||
|---|---|---|
|
def __init__(self, db_conn, id=None, url=None):
|
||
|
|
||
|
# Make sure the DB connection is valid before doing anything else
|
||
|
if not db_conn:
|
||
|
if not db_conn or not isinstance(db_conn, sqlite3.Connection):
|
||
|
raise DBConnectionError('Invalid database connection object!')
|
||
|
|
||
|
# Setup internal parameters
|
||
| ... | ... | |
|
|
||
|
# Grab category tags
|
||
|
for row in db.execute(SQL_SELECT_CAT_TAGS, (self.id,)):
|
||
|
self.category_tags.add(Tag(int(row[0])))
|
||
|
self.category_tags.add(Tag(db_conn, int(row[0])))
|
||
|
|
||
|
# Grab description tags
|
||
|
for row in db.execute(SQL_SELECT_DESC_TAGS, (self.id,)):
|
||
|
self.description_tags.add(Tag(int(row[0])))
|
||
|
self.description_tags.add(Tag(db_conn, int(row[0])))
|
||
|
|
||
|
# Store hash of tag sets for dirty comparison
|
||
|
self._cat_tags_hash = hash(frozenset(self.category_tags))
|
||
| software/bookmark_library/bmklib/lib/tag.py | ||
|---|---|---|
|
def __init__(self, db_conn, id=None, value=None):
|
||
|
|
||
|
# Make sure the DB connection is valid before doing anything else
|
||
|
if not db_conn:
|
||
|
if not db_conn or not isinstance(db_conn, sqlite3.Connection):
|
||
|
raise DBConnectionError('Invalid database connection object!')
|
||
|
|
||
|
self._db_conn = db_conn
|
||
| software/bookmark_library/bmklib/web/base_controller.py | ||
|---|---|---|
|
DB_PATH = os.path.join(BASE_PATH, 'bookmarks.db')
|
||
|
TEMPLATE_PATH = os.path.join(BASE_PATH, 'bmklib', 'web', 'templates')
|
||
|
|
||
|
# Someday this should go into some sort of configuration
|
||
|
MAX_PER_PAGE = 20
|
||
|
|
||
|
class BaseHTMLController(object):
|
||
|
|
||
|
def __init__(self, environ, template_name=None):
|
||
| software/bookmark_library/bmklib/web/controllers/bookmark.py | ||
|---|---|---|
|
import sqlite3
|
||
|
|
||
|
from bmklib.lib.bookmark import Bookmark
|
||
|
from bmklib.web.base_controller import BaseHTMLController, DB_PATH
|
||
|
from bmklib.web.base_controller import BaseHTMLController, DB_PATH, MAX_PER_PAGE
|
||
|
|
||
|
class BookmarkPageController(BaseHTMLController):
|
||
|
|
||
| ... | ... | |
|
super(BookmarkPageController, self).__init__(environ, template_name)
|
||
|
|
||
|
def build_content(self):
|
||
|
conn = sqlite3.connect(DB_PATH)
|
||
|
|
||
|
# Split the path so we can parse it below
|
||
|
path = self.environ['PATH_INFO'][1:]
|
||
|
path_parts = path.split('/')
|
||
|
|
||
|
conn = sqlite3.connect(DB_PATH)
|
||
|
db = conn.cursor()
|
||
|
db.execute("SELECT id FROM bookmarks WHERE deleted=0")
|
||
|
|
||
|
page_idx = 0
|
||
|
|
||
|
# Parse the path and modify the query as needed
|
||
|
if len(path_parts) == 2:
|
||
|
if path_parts[1] == 'all':
|
||
|
db.execute("SELECT id FROM bookmarks WHERE deleted=0")
|
||
|
else:
|
||
|
# Attempt to grab a new query index from the URL
|
||
|
try:
|
||
|
page_idx = int(path_parts[1])
|
||
|
except ValueError:
|
||
|
pass
|
||
|
|
||
|
query = "SELECT id FROM bookmarks WHERE deleted=0 LIMIT {:d}"\
|
||
|
" OFFSET {:d}".format(MAX_PER_PAGE, page_idx * MAX_PER_PAGE)
|
||
|
db.execute(query)
|
||
|
else:
|
||
|
db.execute("SELECT id FROM bookmarks WHERE deleted=0 LIMIT {:d}".format(MAX_PER_PAGE))
|
||
|
|
||
|
# Build Bookmark objects for all of the returned results
|
||
|
bookmarks = [Bookmark(conn, id=row[0]) for row in db.fetchall()]
|
||
|
|
||
|
self.content['bookmarks'] = bookmarks
|
||
|
self.content['path_parts'] = len(path_parts)
|
||
|
|
||
|
# Set previous and next to control pagination in the template
|
||
|
if page_idx == 0:
|
||
|
self.content['previous'] = None
|
||
|
else:
|
||
|
prev_idx = page_idx - 1
|
||
|
if len(path_parts) == 2:
|
||
|
self.content['previous'] = '../../bookmark/{:d}'.format(prev_idx)
|
||
|
else:
|
||
|
self.content['previous'] = '../bookmark/{:d}'.format(prev_idx)
|
||
|
|
||
|
next_idx = page_idx + 1
|
||
|
if len(path_parts) == 2:
|
||
|
self.content['next'] = '../../bookmark/{:d}'.format(next_idx)
|
||
|
else:
|
||
|
self.content['next'] = '../bookmark/{:d}'.format(next_idx)
|
||
| software/bookmark_library/bmklib/web/htdocs/css/bmk_main.css | ||
|---|---|---|
|
table {
|
||
|
border: 1px solid #000;
|
||
|
border-spacing: 0px;
|
||
|
margin-left: auto;
|
||
|
margin-left: 2em;
|
||
|
margin-right: auto;
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
border-top: 1px solid #000;
|
||
|
padding: 2px 5px;
|
||
|
}
|
||
|
|
||
|
.tag {
|
||
|
background-color: #CCC;
|
||
|
font-size: 12px
|
||
|
padding: 4px;
|
||
|
border-right: 2px;
|
||
|
}
|
||
| software/bookmark_library/bmklib/web/templates/bookmark.html | ||
|---|---|---|
|
xmlns:py="http://genshi.edgewall.org/">
|
||
|
<head>
|
||
|
<title>Bookmark Library</title>
|
||
|
<link rel="stylesheet" type="text/css" href="../htdocs/css/bmk_main.css"></link>
|
||
|
<link rel="stylesheet" type="text/css" href="http://127.0.0.1/htdocs/css/bmk_main.css"></link>
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<h1>Bookmarks</h1>
|
||
|
|
||
|
<p>${path_parts}</p>
|
||
|
|
||
|
<table>
|
||
|
<tr py:for="idx, bookmark in enumerate(bookmarks)" class="${idx % 2 == 1 and 'odd' or 'even'}">
|
||
|
<td>${bookmark.id}</td>
|
||
|
<td><a href="${bookmark.url}">${bookmark.title and bookmark.title or 'no title'}</a></td>
|
||
|
<td><py:for each="tag in bookmark.category_tags"><div class="tag">${tag.value}</div></py:for></td>
|
||
|
<td><py:for each="tag in bookmark.description_tags"><div class="tag">${tag.value}</div></py:for></td>
|
||
|
<td><py:for each="tag in bookmark.category_tags"><span class="tag">${tag.value}</span></py:for></td>
|
||
|
<td><py:for each="tag in bookmark.description_tags"><span class="tag">${tag.value}</span></py:for></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
|
||
|
<py:if test="previous is not None"><a href="bookmark/${previous}">Previous</a></py:if>
|
||
|
|
||
|
<py:if test="next is not None"><a href="bookmark/${next}">Next</a></py:if>
|
||
|
</body>
|
||
|
</html>
|
||
| software/bookmark_library/bmklib/web/templates/main.html | ||
|---|---|---|
|
|
||
|
There are currently ${total_num_bmks} bookmarks in the library.
|
||
|
<ul>
|
||
|
<li><a href="bookmark">All bookmarks</a></li>
|
||
|
<li><a href="bmk/bookmark">All bookmarks</a></li>
|
||
|
<li>All tags</li>
|
||
|
</ul>
|
||
|
</body>
|
||
Fixed an issue with the Bookmark class was not properly creating the category and description tag sets. Also fixed an issue with both the Bookmark and Tag classes where the passed in DB connection was not being type checked before being used. Finally I added basic pagination to the BookmarkPageController.