[Zope3-checkins] CVS: Products3/z3checkins - bookmark.pt:1.1 README:1.2 TODO:1.5 configure.zcml:1.5 container.pt:1.6 interfaces.py:1.4 message.py:1.7
Marius Gedminas
mgedmin@codeworks.lt
Wed, 16 Apr 2003 18:02:18 -0400
Update of /cvs-repository/Products3/z3checkins
In directory cvs.zope.org:/tmp/cvs-serv21560
Modified Files:
README TODO configure.zcml container.pt interfaces.py
message.py
Added Files:
bookmark.pt
Log Message:
z3checkins:
- updated README
- added three new TODO items
- store last 5 visits in a cookie and display them as bookmarks between
messages
=== Added File Products3/z3checkins/bookmark.pt ===
<hr />
=== Products3/z3checkins/README 1.1.1.1 => 1.2 ===
--- Products3/z3checkins/README:1.1.1.1 Thu Apr 3 03:19:59 2003
+++ Products3/z3checkins/README Wed Apr 16 18:01:48 2003
@@ -40,7 +40,9 @@
Replace username:password with the username and password of a Zope 3 user that
has zope.ManageContent permission in the 'zope3-checkins' folder.
-This script may be used to import archives in Maildir format.
+This script may be used to import archives in Maildir format. Or you can
+use formail or some other tool to split mbox folders available at
+http://mail.zope.org/pipermail/zope3-checkins/
Procmail
@@ -56,14 +58,6 @@
Replace username:password with the username and password of a Zope 3 user that
has zope.ManageContent permission in the 'zope3-checkins' folder.
-
-Mozilla sidebar
----------------
-
-Type the following in Mozilla address bar (as a single line):
-
- javascript:window.sidebar.addPanel('Zope 3 Checkins',
- 'http://localhost:8080/zope3-checkins/@@checkins.html', '')
RSS feed
--------
=== Products3/z3checkins/TODO 1.4 => 1.5 ===
--- Products3/z3checkins/TODO:1.4 Wed Apr 16 07:46:06 2003
+++ Products3/z3checkins/TODO Wed Apr 16 18:01:48 2003
@@ -2,16 +2,21 @@
- Highlight branch tags in message body
- Detect URLs in checkin comments and make those into <a> elements
-- Remember the last-seen message in a cookie and display a <hr> there. Perhaps
- keep a FIFO of, say, last 5 boundaries
- Detect several checkins with the same checkin comment and group them in some
way (e.g. display <em>(same checkin)</em> instead of repeating the comment)
- Include all messages sent to zope3-checkins, not just checkin messages
I'm not sure I'll find time for these:
+- Replace newlines with <br/> elements in checkin messages in message_part.pt
+- Shorten descriptions in message_part.pt to first 100 chars (words? sentences?
+ lines?)
- Add links to the specific versions of the files mentioned in the CVS web
interface
- Filtering (by branch, by author, etc)
- Verify how all this works in other browsers beside Mozilla
- Is storing all the messages in a single folder scalable enough?
+- Create an interface ICheckinsFolder extending IFolder and write a factory
+ to create folders marked with this interface. Register z3checkins container
+ views only for ICheckinsFolders. Perhaps wait until the interfacegheddon
+ before starting this.
=== Products3/z3checkins/configure.zcml 1.4 => 1.5 ===
--- Products3/z3checkins/configure.zcml:1.4 Wed Apr 16 07:32:58 2003
+++ Products3/z3checkins/configure.zcml Wed Apr 16 18:01:48 2003
@@ -78,6 +78,19 @@
permission="zope.View" />
<browser:page
+ for=".interfaces.ICheckinBookmark"
+ name="html"
+ template="bookmark.pt"
+ permission="zope.View" />
+
+ <browser:page
+ for=".interfaces.ICheckinBookmark"
+ name="html-sidebar"
+ template="bookmark.pt"
+ usage="sidebar"
+ permission="zope.View" />
+
+ <browser:page
for=".interfaces.ICheckinMessage"
name="index.html"
template="message.pt"
=== Products3/z3checkins/container.pt 1.5 => 1.6 ===
--- Products3/z3checkins/container.pt:1.5 Wed Apr 16 07:46:06 2003
+++ Products3/z3checkins/container.pt Wed Apr 16 18:01:48 2003
@@ -14,11 +14,14 @@
a.title { display: block; width: 100%; }
a:hover { background: #e0e6ff; }
img.icon { float: right; padding: 0ex; margin: 2px; border: none; }
+ hr { width: 60%; border: none; background: gray; height: 1px;
+ margin-top: 1ex; margin-bottom: 0ex; }
</style>
</head>
<body tal:define="sidebar usage/sidebar;
target python: sidebar and '_content' or None;
- msg_view python: sidebar and '@@html-sidebar' or '@@html'">
+ msg_view python: sidebar and '@@html-sidebar' or '@@html';
+ dummy view/placeBookmark">
<h1>Zope 3 Checkins</h1>
<div class="toolbar"
=== Products3/z3checkins/interfaces.py 1.3 => 1.4 ===
--- Products3/z3checkins/interfaces.py:1.3 Tue Apr 8 13:35:10 2003
+++ Products3/z3checkins/interfaces.py Wed Apr 16 18:01:48 2003
@@ -22,6 +22,10 @@
# Maybe store full headers as well?
+class ICheckinBookmark(Interface):
+ """Bookmark placed between checkin messages."""
+
+
class FormatError(Exception):
"""Ill-formed checkin message exception"""
=== Products3/z3checkins/message.py 1.6 => 1.7 ===
--- Products3/z3checkins/message.py:1.6 Wed Apr 16 07:32:58 2003
+++ Products3/z3checkins/message.py Wed Apr 16 18:01:48 2003
@@ -18,9 +18,10 @@
from zope.app.interfaces.container import IReadContainer
from zope.proxy.introspection import removeAllProxies
from zope.proxy.context import getWrapperContainer
+from zope.app.datetimeutils import parseDatetimetz, DateTimeError
from interfaces import ICheckinMessage, ICheckinMessageParser, FormatError
-from interfaces import ICheckinMessageArchive
+from interfaces import ICheckinMessageArchive, ICheckinBookmark
__metaclass__ = type
@@ -217,6 +218,10 @@
return self.messages.index(message)
+class CheckinBookmark:
+
+ __implements__ = ICheckinBookmark
+
#
# Browser views
@@ -239,6 +244,41 @@
class ContainerView:
"""View mixin for locating checkin messages in a container."""
+ max_bookmarks = 5
+
+ def bookmarks(self):
+ """Returns a list of bookmarks from a cookie. Each bookmark is
+ expressed as a datetime object.
+ """
+ bookmarks = []
+ cookie = self.request.get('bookmarks', '')
+ for item in cookie.split():
+ try:
+ bookmarks.append(parseDatetimetz(item))
+ except (DateTimeError, IndexError):
+ pass
+ return bookmarks
+
+ def placeBookmark(self):
+ """Place a new bookmark after the latest checkin message in a
+ cookie."""
+ if not hasattr(self, '_archive'):
+ self._archive = getAdapter(self.context, ICheckinMessageArchive)
+ if not self._archive:
+ return # No messages -- no bookmarks
+ bookmarks = self.bookmarks()
+ bookmarks.sort()
+ # Do not insert a bookmark if there were no checkins since the last
+ # bookmark
+ if (bookmarks and bookmarks[-1] >= self._archive[-1].date):
+ return
+ bookmarks.append(self._archive[-1].date)
+ if len(bookmarks) > self.max_bookmarks:
+ del bookmarks[:-self.max_bookmarks]
+ cookie = " ".join([dt.isoformat() for dt in bookmarks])
+ self.request.response.setCookie('bookmarks', cookie,
+ max_age=365*24*60*60) # 1 year
+
def checkins(self, start=None, size=None):
"""Returns a list of the last 'size' checkin messages in
self.context, newest first, skipping the first 'start' messages.
@@ -249,7 +289,29 @@
self._archive = getAdapter(self.context, ICheckinMessageArchive)
idx = len(self._archive) - start
items = self._archive[max(0, idx-size):idx]
- items = removeAllProxies(items) # needed for reverse
+ items = removeAllProxies(items)
+ # insert bookmarks
+ def bookmarkBetween(msg1, msg2, bookmarks=self.bookmarks()):
+ for b in bookmarks:
+ if msg1.date <= b < msg2.date:
+ return True
+ return False
+ n = 1
+ while n < len(items):
+ if bookmarkBetween(items[n-1], items[n]):
+ items.insert(n, CheckinBookmark())
+ n += 2
+ else:
+ n += 1
+ # insert bookmarks before the first/after the last batch item
+ if items:
+ before = self._archive[max(0, idx-size-1):max(0, idx-size)]
+ if before and bookmarkBetween(before[0], items[0]):
+ items.insert(0, CheckinBookmark())
+ after = self._archive[idx:idx+1]
+ if after and bookmarkBetween(items[-1], after[0]):
+ items.insert(len(items), CheckinBookmark())
+ # reverse order to present newest checkins first
items.reverse()
return items