[Checkins] SVN: Sandbox/luciano/kirbi/src/kirbi/ implemented
personal collections and items
Luciano Ramalho
luciano at ramalho.org
Sun Aug 19 21:45:34 EDT 2007
Log message for revision 79006:
implemented personal collections and items
Changed:
U Sandbox/luciano/kirbi/src/kirbi/app_templates/login.pt
U Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt
U Sandbox/luciano/kirbi/src/kirbi/book.py
U Sandbox/luciano/kirbi/src/kirbi/collection.py
A Sandbox/luciano/kirbi/src/kirbi/collection_templates/addbookitems.pt
U Sandbox/luciano/kirbi/src/kirbi/item.py
U Sandbox/luciano/kirbi/src/kirbi/pac.py
U Sandbox/luciano/kirbi/src/kirbi/static/master.css
U Sandbox/luciano/kirbi/src/kirbi/tests/test_doctests.py
-=-
Modified: Sandbox/luciano/kirbi/src/kirbi/app_templates/login.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/app_templates/login.pt 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/app_templates/login.pt 2007-08-20 01:45:32 UTC (rev 79006)
@@ -3,7 +3,7 @@
<span metal:fill-slot="content_title">Login</span>
- <span metal:fill-slot="content_search"></span>
+ <span metal:fill-slot="user_menu"></span>
<div metal:fill-slot="content">
Modified: Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt 2007-08-20 01:45:32 UTC (rev 79006)
@@ -30,43 +30,53 @@
<img tal:attributes="src static/circulante-logo-transp-212x51.png"
title="Circulante.org" width="212" height="51" />
</a>
- <ul tal:condition="anonymous">
- <li><a tal:attributes="href python:view.application_url('pac')">catalog</a></li>
- <li><a tal:attributes="href python:view.application_url('login')">login</a></li>
+ <ul class="menu">
+ <tal:anon condition="anonymous">
<li><a tal:attributes="href python:view.application_url('join')">join</a></li>
+ </tal:anon>
+ <tal:auth condition="not:anonymous">
+ <li><a tal:attributes="href string:${view/application_url}/u/${request/principal/id}"
+ ><span tal:replace="request/principal/id" />'s collection</a></li>
+ </tal:auth>
+ <li><a tal:attributes="href python:view.application_url('pac')">collective catalog</a></li>
+ <li class="noborder"><form tal:attributes="action python:view.application_url('pac')"
+ ><input type="text" name="query"> <input type="submit" name="submit" value="search"
+ ></form></li>
</ul>
- <ul tal:condition="not:anonymous">
- <li><a tal:attributes="href python:view.application_url('pac')">catalog</a></li>
- <li><a tal:attributes="href python:view.application_url('u')">users</a></li>
- <li><a tal:attributes="href python:view.application_url('pac/addbooks')">add books</a></li>
- <li><a tal:attributes="href python:view.application_url('logout')">logout</a></li>
- </ul>
</div>
<div metal:define-slot="body">
<div class="content_menu">
- <span metal:define-slot="content_menu">
+ <div metal:define-slot="content_menu">
<span class="content_title">
<span metal:define-slot="content_title">
Content title
</span>
</span>
<span class="content_login">
- <span tal:condition="anonymous">
- (not logged in)
- </span>
<span tal:condition="not:anonymous">
login: <span tal:replace="view/request/principal/id" />
</span>
</span>
- <span metal:define-slot="content_search">
- <form class="search" tal:attributes="action python:view.application_url('pac')">
- <input type="text" name="query">
- <input type="submit" name="submit" value="search">
- </form>
+ <span class="user_menu">
+ <span metal:define-slot="user_menu">
+ <ul class="menu">
+ <li tal:condition="anonymous" class="noborder"><form
+ tal:attributes="action string:${view/application_url}/login"
+ method="post">login <input
+ type="text" name="login" id="login" tal:attributes="value
+ request/login|nothing"/> password <input type="password"
+ name="password" id="password" /> <input type="submit"
+ name="login_submit" value="log in" /></form></li>
+ <tal:auth condition="not:anonymous">
+ <li><a tal:attributes="href
+ string:${view/application_url}/u/${request/principal/id}/addbookitems">add books</a></li>
+ <li><a tal:attributes="href python:view.application_url('logout')">logout</a></li>
+ </tal:auth>
+ </ul>
+ </span><!--/slot: user_menu-->
</span>
-
- </span>
+ </div>
</div>
<div class="content">
<div metal:define-slot="content">
Modified: Sandbox/luciano/kirbi/src/kirbi/book.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/book.py 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/book.py 2007-08-20 01:45:32 UTC (rev 79006)
@@ -38,6 +38,9 @@
"""A book record implementation.
>>> alice = Book()
+ >>> IBook.providedBy(alice)
+ True
+
>>> alice.title = u"Alice's Adventures in Wonderland"
>>> alice.title
u"Alice's Adventures in Wonderland"
@@ -255,6 +258,9 @@
def update(self, **kwargs):
for key, value in kwargs.items():
setattr(self,key,value)
+
+ def getCoverId(self):
+ return self.__name__
class Edit(grok.EditForm):
grok.require('kirbi.ManageBook')
@@ -267,10 +273,10 @@
pass
class Index(grok.View):
+ grok.context(IBook)
- def __init__(self, *args):
- # XXX: Is this super call really needed for a View sub-class?
- super(Index,self).__init__(*args)
+ def __init__(self, context, request):
+ super(Index, self).__init__(context, request)
# Note: this method was created because calling context properties
# from the template raises a traversal error
@@ -289,6 +295,6 @@
self.source_url = None
def coverUrl(self):
- cover_name = 'covers/large/'+self.context.__name__+'.jpg'
+ cover_name = 'covers/large/'+self.context.getCoverId()+'.jpg'
return self.static.get(cover_name,
self.static['covers/small-placeholder.jpg'])()
Modified: Sandbox/luciano/kirbi/src/kirbi/collection.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/collection.py 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/collection.py 2007-08-20 01:45:32 UTC (rev 79006)
@@ -21,8 +21,16 @@
from kirbi.isbn import toISBN13, InvalidISBN
from kirbi.item import Item
from kirbi.book import Book
+from zope.app.container.interfaces import INameChooser
class Collection(grok.Container):
+ """A collection of items (books, disks etc.) belonging to one user.
+
+ >>> myCollection = Collection('123')
+ >>> ICollection.providedBy(myCollection)
+ True
+
+ """
implements(ICollection)
def __init__(self, title, private=False):
super(Collection, self).__init__()
@@ -30,27 +38,36 @@
self.private = False ### XXX: implement private collections
def addItem(self, item):
- name = INameChooser(self).chooseName(book.isbn13, book)
- self[name] = book
- return book.__name__
+ name = INameChooser(self).chooseName('', item)
+ self[name] = item
+ return item.__name__
class Index(grok.View):
+ grok.context(Collection)
+
+ def __init__(self, context, request):
+ super(Index, self).__init__(context, request)
+ self.pac = grok.getSite()['pac']
+
def update(self, query=None):
- if not query:
- # XXX: if the query is empty, return all books; this should change
- # to some limited default search criteria or none at all
- results = self.context.values()
- self.results_title = 'All items'
+ results = self.context.values()
+ self.results_title = 'All items'
self.results = results
+
+ def coverUrl(self, item):
+ book = self.pac[item.manifestation_id]
+ cover_name = 'covers/large/'+book.__name__+'.jpg'
+ return self.static.get(cover_name,
+ self.static['covers/small-placeholder.jpg'])()
+
class AddBookItems(grok.View):
- grok.context(Collection)
invalid_isbns = []
def update(self, isbns=None, retry_isbns=None):
- self.pac = self.context.__parent__.__parent__['pac']
+ self.pac = grok.getSite()['pac']
self.invalid_isbns = []
if isbns is not None:
isbns = list(set(isbns.split()))
@@ -65,8 +82,8 @@
else:
book = Book(isbn13=isbn13)
self.pac.addBook(book)
- item = Item(book.__name__)
- self.context.addItem(item)
+ item = Item(book.__name__)
+ self.context.addItem(item)
if retry_isbns:
self.context.retryPending(retry_isbns)
Added: Sandbox/luciano/kirbi/src/kirbi/collection_templates/addbookitems.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/collection_templates/addbookitems.pt (rev 0)
+++ Sandbox/luciano/kirbi/src/kirbi/collection_templates/addbookitems.pt 2007-08-20 01:45:32 UTC (rev 79006)
@@ -0,0 +1,131 @@
+<html metal:use-macro="context/@@master/page">
+<head>
+ <title metal:fill-slot="title">
+ Public Catalog
+ </title>
+
+</head>
+<body>
+ <span metal:fill-slot="content_title">Collective catalog</span>
+ <div metal:fill-slot="content">
+ <table><tr>
+ <td valign="top">
+ <form tal:attributes="action view/url" method="post">
+ <p>Type or scan several ISBNs separated by spaces or newlines.<br />
+ Either 10 or 13-digit ISBNs can be used.</p>
+ <p class="error" tal:condition="view/invalidISBNs">
+ The numbers remaining in the field below are not valid ISBN-10
+ or ISBN-13.
+ </p>
+ <textarea name="isbns" rows="20" cols="40"
+ tal:content="view/invalidISBNs">
+ </textarea>
+ <br />
+ <input type="submit" value="Add books">
+ <br />
+ </form>
+ <hr />
+ <p>
+ <form tal:attributes="action python:view.url('importdemo')" method="post">
+ If you have no ISBNs on hand, you can
+ <input type="submit" value="Import a demo collection">
+ </form>
+ </p>
+
+ </td><td valign="top">
+
+ <div tal:condition="view/incompleteIsbns">
+ <h3>New Book Records Without Title</h3>
+ <table class="isbn_list">
+ <tr tal:repeat="item view/incompleteIsbns">
+ <th align="right" tal:content="repeat/item/number" />
+ <td tal:content="item/timestamp" />
+ <td>
+ <a tal:attributes="href python:view.url(item['isbn'])"
+ tal:content="item/isbn">9780123456789</a>
+
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <form tal:condition="view/pendingIsbns" method="post"
+ tal:attributes="action view/url">
+ <h3>Pending Book Searches</h3>
+ <table class="isbn_list">
+ <tr>
+ <th></th>
+ <th>#</th>
+ <th>Created</th>
+ <th>ISBN-13</th>
+ <th>
+ <a tal:attributes="href string:http://www.worldcatlibraries.org/"
+ title="WorldCat Libraries Search">
+ <img tal:attributes="src static/worldcat24.gif" />
+ </a>
+ </th>
+ <th>
+ <a tal:attributes="href string:http://www.alibris.com/search/search.cfm"
+ title="Alibris Book Search">
+ <img tal:attributes="src static/alibris24.gif" />
+ </a>
+ </th>
+ <th>
+ <a tal:attributes="href string:http://books.google.com/"
+ title="Google Book Search">
+ <img tal:attributes="src static/googlebook24.gif" />
+ </a>
+ </th>
+ <th>
+ <a tal:attributes="href string:http://google.com/"
+ title="Google Search">
+ <img tal:attributes="src static/google24.gif" />
+ </a>
+ </th>
+ </tr>
+ <tr tal:repeat="item view/pendingIsbns">
+ <td>
+ <input type="checkbox" name="retry_isbns:list"
+ tal:attributes="value item/isbn" />
+
+ </td>
+ <th align="right" tal:content="repeat/item/number" />
+ <td tal:content="item/timestamp" />
+ <td>
+ <a tal:attributes="href python:view.url(item['isbn'])"
+ tal:content="item/isbn">9780123456789</a>
+
+ </td>
+ <td>
+ <a tal:attributes="href string:http://www.worldcatlibraries.org/search?q=${item/isbn}"
+ title="WorldCat Libraries Search">
+ <img tal:attributes="src static/worldcat16.gif" />
+ </a>
+ </td>
+ <td>
+ <a tal:attributes="href string:http://www.alibris.com/search/search.cfm?wtit=${item/isbn}"
+ title="Alibris Book Search">
+ <img tal:attributes="src static/alibris16.gif" />
+ </a>
+ </td>
+ <td>
+ <a tal:attributes="href string:http://books.google.com/books?q=${item/isbn}"
+ title="Google Book Search">
+ <img tal:attributes="src static/google16.gif" />
+ </a>
+ </td>
+ <td>
+ <a tal:attributes="href string:http://google.com/search?q=${item/isbn}"
+ title="Google Search">
+ <img tal:attributes="src static/google16.gif" />
+ </a>
+
+ </td>
+ </tr>
+ </table>
+ <input type="submit" name="retry" value="Retry">
+ </form>
+
+ </div><!--/content-->
+</body>
+</html>
Modified: Sandbox/luciano/kirbi/src/kirbi/item.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/item.py 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/item.py 2007-08-20 01:45:32 UTC (rev 79006)
@@ -15,7 +15,7 @@
"""
import grok
-from interfaces import IItem, ILease
+from interfaces import IItem, IBook
from zope.interface import Interface, implements, invariant
from zope import schema
from datetime import datetime
@@ -24,14 +24,36 @@
"""An exemplar of a book.
See note at interfaces.IItem.
+
+ >>> it = Item('')
+ >>> IItem.providedBy(it)
+ True
+
+ Now let's make it provide IBook.
+
+ >>> from kirbi.book import Book
+ >>> book = Book('Any Book')
+ >>> it.manifestation = book
+
+ >>> IBook.providedBy(it)
+ True
+
"""
- implements(IItem)
+ implements(IItem, IBook)
- def __init__(self, manifestation, description=u'', catalog_datetime=None):
+ def __init__(self, manifestation_id, description=u'', catalog_datetime=None):
super(Item, self).__init__()
- self.manifestation = manifestation
+ self.manifestation_id = manifestation_id
+ if manifestation_id:
+ self.manifestation = grok.getSite()['pac'].get(manifestation_id)
self.description = description
if catalog_datetime is None:
self.catalog_datetime = datetime.now()
-
\ No newline at end of file
+
+ def getCoverId(self):
+ return self.manifestation.__name__
+
+ def __getattr__(self,name):
+ # XXX: this looks too easy... feels like cheating. Is it sane?
+ return getattr(self.manifestation, name)
\ No newline at end of file
Modified: Sandbox/luciano/kirbi/src/kirbi/pac.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/pac.py 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/pac.py 2007-08-20 01:45:32 UTC (rev 79006)
@@ -102,7 +102,7 @@
grok.context(Pac)
def coverUrl(self, book):
- cover_name = 'covers/large/'+book.isbn13+'.jpg'
+ cover_name = 'covers/large/'+book.__name__+'.jpg'
return self.static.get(cover_name,
self.static['covers/small-placeholder.jpg'])()
Modified: Sandbox/luciano/kirbi/src/kirbi/static/master.css
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/static/master.css 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/static/master.css 2007-08-20 01:45:32 UTC (rev 79006)
@@ -34,18 +34,39 @@
text-decoration: none;
}
.top ul {
- display: inline;
position: absolute;
- right: 10px;
top: 0px;
}
-.top li {
+ul.menu {
display: inline;
+ right: 10px;
+}
+
+.menu li {
+ display: inline;
line-height: 1.5;
margin-right: 10px;
padding-bottom: 1px;
border-bottom: 1px solid yellow;
}
+.menu li.noborder {
+ border-bottom: none;
+}
+
+.menu form {
+ display: inline;
+}
+
+.menu input {
+ display: inline;
+}
+
+form.login {
+ display: inline;
+ position: absolute;
+ right: 10px;
+}
+
h1, h2, h3, dt, .content_title {
font-family: sans-serif;
font-weight: bold;
@@ -73,16 +94,16 @@
font-family: sans-serif;
}
+span.user_menu {
+ position: absolute;
+ right: 10px;
+ font-family: sans-serif;
+}
+
div.content {
margin: 20px;
}
-form.search {
- display: inline;
- position: absolute;
- right: 10px;
-}
-
img.cover {
border: 1px solid lightgray;
margin-right: 10px;
Modified: Sandbox/luciano/kirbi/src/kirbi/tests/test_doctests.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/tests/test_doctests.py 2007-08-19 23:01:03 UTC (rev 79005)
+++ Sandbox/luciano/kirbi/src/kirbi/tests/test_doctests.py 2007-08-20 01:45:32 UTC (rev 79006)
@@ -2,7 +2,7 @@
import unittest
def test_suite():
- modules = ['app', 'pac', 'book', 'user']
+ modules = ['app','book','collection','interfaces','isbn','item','user']
suite = unittest.TestSuite()
for module in modules:
module_name = 'kirbi.' + module
More information about the Checkins
mailing list