[Checkins] SVN: Sandbox/darrylcousins/tfws.website/src/tfws/website/ Finally committing some work on members views

Darryl Cousins darryl at darrylcousins.net.nz
Sun Aug 12 06:33:25 EDT 2007


Log message for revision 78765:
  Finally committing some work on members views

Changed:
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/BROWSER.txt
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/authentication.py
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/browser.py
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/index.pt
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/interfaces.py
  A   Sandbox/darrylcousins/tfws.website/src/tfws/website/members.py
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/permissions.py
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/site.py
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/site.txt
  A   Sandbox/darrylcousins/tfws.website/src/tfws/website/table.py
  A   Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/contents.pt
  A   Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/member.pt
  U   Sandbox/darrylcousins/tfws.website/src/tfws/website/tools/member.py

-=-
Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/BROWSER.txt
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/BROWSER.txt	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/BROWSER.txt	2007-08-12 10:33:25 UTC (rev 78765)
@@ -76,3 +76,22 @@
   >>> user.getControl('Login').click()
   >>> print user.url
   http://localhost/treefern/edit
+
+Members
+-------
+
+Views are provided for members folder and members.
+
+  >>> user.handleErrors = False
+  >>> user.open('http://localhost/treefern/members')
+  >>> user.getLink('Darryl Cousins').click()
+
+We now have the edit form for a member.
+
+  >>> user.getControl('First Name').value = u'Darryl Jon'
+  >>> user.getControl('Change Password').value = u'secret'
+  >>> user.getControl('Verify Password').value = u'osecret'
+  >>> user.getControl('Apply').click()
+  >>> print user.contents
+
+

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/authentication.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/authentication.py	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/authentication.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -6,6 +6,7 @@
 from zope.app.component import hooks
 from zope.app.authentication.session import SessionCredentialsPlugin
 from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.annotation.interfaces import IAttributeAnnotatable
 
 from z3c.authentication.simple import member
 from z3c.authentication.simple import group
@@ -89,7 +90,8 @@
 class WebSiteMember(member.Member):
     """An IMember for MemberContainer."""
 
-    zope.interface.implements(interfaces.IWebSiteMember)
+    zope.interface.implements(interfaces.IWebSiteMember, 
+                                             IAttributeAnnotatable)
 
     firstName = FieldProperty(interfaces.IWebSiteMember['firstName'])
     lastName = FieldProperty(interfaces.IWebSiteMember['lastName'])
@@ -106,3 +108,6 @@
     def __repr__(self):
         return '<%s %r>' %(self.__class__.__name__, self.title)
 
+    @property
+    def id(self):
+        return self.__name__

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/browser.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/browser.py	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/browser.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -3,17 +3,13 @@
 import zope.lifecycleevent
 from zope.traversing import api
 from zope.app.folder.interfaces import IRootFolder
-from zope.dublincore.interfaces import IZopeDublinCore
-from zope.pagetemplate.interfaces import IPageTemplate
-from zope.traversing.browser import absoluteURL
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
 
 from z3c.form import form, field, group, button
 from z3c.formui import layout
 from z3c.configurator import configurator
 
 from zc.table import column
-from zc.table import table
+from zc.table.table import AlternatingRowFormatter
 
 import grok
 
@@ -26,6 +22,7 @@
 from tfws.website import interfaces
 from tfws.website import permissions
 from tfws.website import site
+from tfws.website import table
 from tfws.website.browser import formatter
 from tfws.website.layer import IWebSiteLayer
 from tfws.website.i18n import MessageFactory as _
@@ -33,60 +30,35 @@
 
 mars.layer.layer(IWebSiteLayer)
 
-class CheckboxColumn(column.Column):
 
-    def renderCell(self, item, formatter):
-        widget = (u'<input type="checkbox" '
-                  u'name="selected:list" value="%s">')
-        return widget %api.getName(item)
-
-
-def getCreatedDate(item, formatter):
-    formatter = formatter.request.locale.dates.getFormatter('date', 'short')
-    return formatter.format(IZopeDublinCore(item).created)
-
-
-def getModifiedDate(item, formatter):
-    formatter = formatter.request.locale.dates.getFormatter('date', 'short')
-    return formatter.format(IZopeDublinCore(item).modified)
-
-
-def link(view='index', title=''):
-    def anchor(value, item, formatter):
-        url = absoluteURL(item, formatter.request) + '/' + view
-        return u'<a href="%s" title="%s">%s</a>' %(url, title, value)
-    return anchor
-
-
 class Index(mars.view.PageletView):
     grok.context(IRootFolder)
     grok.require(permissions.MANAGESITE)
+    title = _("Tree Fern Web Site Demo")
 
     columns = (
-        CheckboxColumn(_('Sel')),
+        table.CheckboxColumn(_('Sel')),
         column.GetterColumn(_('Id'), 
-                    lambda item, f: api.getName(item), link('index', _('View'))),
+                    lambda item, f: api.getName(item), table.link('index', _('View'))),
         column.GetterColumn(_('Title'), 
-                    lambda item, f: item.title, link('edit', _('Edit'))),
-        column.GetterColumn(_('Created On'), getCreatedDate),
-        column.GetterColumn(_('Modified On'), getModifiedDate),
+                    lambda item, f: item.title, table.link('edit', _('Edit'))),
+        column.GetterColumn(_('Created On'), table.getCreatedDate),
+        column.GetterColumn(_('Modified On'), table.getModifiedDate),
         )
 
     status = None
 
-    def sites(self):
-        return [obj
-                for obj in self.context.values()
-                if interfaces.IWebSite.providedBy(obj)]
-
     def table(self):
-        formatter = table.AlternatingRowFormatter(
-            self.context, self.request, self.sites(), columns=self.columns)
+        formatter = AlternatingRowFormatter(
+            self.context, self.request, self.items, columns=self.columns)
         formatter.widths=[25, 50, 300, 100, 100]
         formatter.cssClasses['table'] = 'list'
         return formatter()
 
     def update(self):
+        self.items = [obj
+                for obj in self.context.values()
+                if interfaces.IWebSite.providedBy(obj)]
         if 'ADD' in self.request:
             self.request.response.redirect('add')
         if 'DELETE' in self.request:

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/index.pt
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/index.pt	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/browser/index.pt	2007-08-12 10:33:25 UTC (rev 78765)
@@ -1,4 +1,4 @@
-<h1>Tree Fern Web Site Demo</h1>
+<h1 tal:content="view/title">Tree Fern Web Site Demo</h1>
 <div class="message"
      tal:condition="view/status"
      tal:content="view/status"
@@ -10,20 +10,20 @@
       tal:attributes="action request/URL">
 
   <tal:block
-      condition="view/sites"
+      condition="view/items"
       replace="structure view/table" />
 
   <div
-      tal:condition="not: view/sites"
+      tal:condition="not: view/items"
       i18n:translate="">
-    There are no sites.
+    There are no items to display.
   </div>
 
   <div id="actionsView">
     <span class="actionButtons">
       <input type="submit" class="button" name="ADD" value="Add"
              i18n:attributes="value" />
-      <tal:block condition="view/sites">
+      <tal:block condition="view/items">
         <input type="submit" class="button" name="DELETE" value="Delete"
                i18n:attributes="value" />
         <input type="text" id="confirm_delete" name="confirm_delete"

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/interfaces.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/interfaces.py	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/interfaces.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -76,4 +76,21 @@
         description=_(u'The email address of the administrator.'),
         required=True)
 
+class IMembers(zope.interface.Interface):
+    """Marker interface"""
 
+class IPassword(zope.interface.Interface):
+
+    change_password = zope.schema.Password(
+        title=_(u'Change Password'),
+        required=False)
+
+    verify_password = zope.schema.Password(
+        title=_(u'Verify Password'),
+        required=False)
+
+    @zope.interface.invariant
+    def areEqual(data):
+        if data.change_password != data.verify_password:
+            raise zope.interface.Invalid(_("Passwords do not match"))
+

Added: Sandbox/darrylcousins/tfws.website/src/tfws/website/members.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/members.py	                        (rev 0)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/members.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -0,0 +1,202 @@
+import zope.interface
+import zope.component
+import zope.lifecycleevent
+import zope.event
+from zope.traversing import api
+from zope.traversing.browser import absoluteURL
+from zope.app.security.interfaces import IAuthentication
+from zope.app.component import hooks
+
+from z3c.authentication.simple import member
+from z3c.formui import layout
+from z3c.form import form, field
+
+from zc.table import column
+from zc.table.table import AlternatingRowFormatter
+
+import grok
+
+import mars.view
+import mars.layer
+import mars.template
+
+from tfws.website import interfaces
+from tfws.website import permissions
+from tfws.website import table
+from tfws.website.layer import IWebSiteLayer
+from tfws.website.i18n import MessageFactory as _
+
+
+mars.layer.layer(IWebSiteLayer)
+
+class Members(grok.Model):
+    """Stub object generated when traversing site/members"""
+    title = _('Members')
+
+    def __init__(self, context=None):
+        """Make the object locatable"""
+        if not context: context = hooks.getSite()
+        self.__parent__ = context
+        self.__name__ = 'members'
+        self.description = _("Container for site members")
+        self.auth = zope.component.getUtility(IAuthentication, context=self.__parent__)
+
+    def traverse(self, name):
+        try:
+            member = self.auth['members'][name]
+        except KeyError:
+            return
+        return Member(member, parent=self)
+
+    @property
+    def members(self):
+        return [obj for obj in self.auth['members'].values()
+                    if interfaces.IWebSiteMember.providedBy(obj)]
+
+    def deleteMember(self, id):
+        del self.auth['members'][id]
+
+
+def link(view='index', title=''):
+    def anchor(value, item, formatter):
+        site = hooks.getSite()
+        url = '%s/members/%s/%s' % (absoluteURL(site, formatter.request),
+                                 api.getName(item), view)
+        return u'<a href="%s" title="%s">%s</a>' %(url, title, value)
+    return anchor
+
+
+# TODO add search field, batching and sortable columns
+class Index(mars.view.PageletView):
+    grok.context(Members) 
+    grok.require(permissions.VIEW)
+    title = _("Members Folder")
+    authAdd = authDelete = authActions = False
+
+    columns = (
+        table.CheckboxColumn(_('Sel')),
+        column.GetterColumn(_('Id'), 
+                    lambda item, f: item.login, link('index', _('View'))),
+        column.GetterColumn(_('Title'), 
+                    lambda item, f: item.title, link('edit', _('Edit'))),
+        column.GetterColumn(_('Created On'), table.getCreatedDate),
+        column.GetterColumn(_('Modified On'), table.getModifiedDate),
+        )
+
+    status = None
+
+    def table(self):
+        formatter = AlternatingRowFormatter(
+            self.context, self.request, self.items, columns=self.columns)
+        formatter.widths=[25, 50, 300, 100, 100]
+        formatter.cssClasses['table'] = 'list'
+        return formatter()
+
+    def update(self):
+        self.items = self.context.members
+        if 'ADD' in self.request:
+            self.request.response.redirect('add')
+        if 'DELETE' in self.request:
+            if self.request.get('confirm_delete') != 'yes':
+                self.status = _('You did not confirm the deletion correctly.')
+                return
+            if 'selected' in self.request:
+                for id in self.request['selected']:
+                    self.context.deleteMember(login)
+                self.status = _('Members were successfully deleted.')
+            else:
+                self.status = _('No members were selected.')
+
+        site = hooks.getSite()
+        perms = permissions.permsForPrincipal(site, self.request.principal)
+        if permissions.MANAGEUSERS in perms:
+            self.authAdd = self.authDelete = True
+        self.authActions = self.authAdd and True or self.authDelete
+
+class IndexTemplate(mars.template.TemplateFactory):
+    """layout template for `home`"""
+    grok.context(Index)
+    grok.template('templates/contents.pt') 
+    
+
+class Member(grok.Model):
+    """Stub object generated when traversing site/members"""
+    grok.implements(interfaces.IWebSiteMember, interfaces.IPassword)
+    verify_password = u''
+
+    def __init__(self, context, parent=None):
+        """Make the object locatable"""
+        if parent == None:
+            self.__parent__ = Members()
+        else:
+            self.__parent__ = parent
+        self.__name__ = context.__name__
+        self.context = context
+
+    @property
+    def email(self):
+        return self.context.email
+
+    @property
+    def login(self):
+        return self.context.login
+
+    @property
+    def change_password(self):
+        return u''
+
+    @property
+    def verify_password(self):
+        return u''
+
+    @property
+    def title(self):
+        return self.context.title
+
+    @property
+    def firstName(self):
+        return self.context.firstName
+
+    @property
+    def lastName(self):
+        return self.context.lastName
+
+class MemberIndex(mars.form.FormView, layout.FormLayoutSupport, 
+                                                 form.DisplayForm):
+    grok.name('index')
+    grok.context(Member) 
+    grok.require(permissions.VIEW)
+    fields = field.Fields(interfaces.IWebSiteMember).select('login',
+                                                           'title',
+                                                           'email')
+    
+class MemberIndexTemplate(mars.template.TemplateFactory):
+    grok.context(MemberIndex)
+    grok.template('templates/member.pt') 
+    
+
+class MemberEdit(mars.form.FormView, layout.FormLayoutSupport, form.EditForm):
+    grok.name('edit')
+    grok.context(Member) 
+    grok.require(permissions.MANAGEUSERS)
+    label = _('Edit Member')
+    fields = field.Fields(interfaces.IWebSiteMember).select('login',
+                                                           'firstName',
+                                                           'lastName',
+                                                           'email')
+    fields += field.Fields(interfaces.IPassword)
+
+    def applyChanges(self, data):
+        content = self.getContent().context
+        change_password = data['change_password']
+        del data['change_password']
+        del data['verify_password']
+        changed = form.applyChanges(self, content, data)
+        if content.password != change_password:
+            content.password = change_password
+            changed = True
+        if changed:
+            zope.event.notify(
+                zope.lifecycleevent.ObjectModifiedEvent(content))
+        return changed
+


Property changes on: Sandbox/darrylcousins/tfws.website/src/tfws/website/members.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/permissions.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/permissions.py	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/permissions.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -1,11 +1,38 @@
 # Allows to edit content.
 MANAGECONTENT = 'tfws.website.ManageContent'
-
 # Allows to edit site components.
 MANAGESITE = 'tfws.website.ManageSite'
-
 # Allows to manage all users.
 MANAGEUSERS = 'tfws.website.ManageUsers'
-
 # Allows to view site
 VIEW = 'tfws.website.View'
+
+ALL = [VIEW, MANAGECONTENT, MANAGEUSERS, MANAGESITE]
+
+import zope.interface
+import zope.component
+from zope.security.interfaces import IParticipation
+from zope.security.management import getSecurityPolicy
+from zope.app.security.interfaces import IAuthentication
+
+def permsForPrincipal(context, principal):
+    """Return a list of permissions allowed for principal."""
+    permission_bits = hasPermissions(ALL, context,
+                                     principal)
+    return [perm for perm, has in zip(ALL, permission_bits)
+            if has]
+
+class ProbeParticipation:
+    """A stub participation for use in hasPermissions."""
+    zope.interface.implements(IParticipation)
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
+def hasPermissions(permissions, object, principal):
+    """Test if the principal has access according to the security policy."""
+    participation = ProbeParticipation(principal)
+    interaction = getSecurityPolicy()(participation)
+    return [interaction.checkPermission(permission, object)
+            for permission in permissions]

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/site.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/site.py	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/site.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -44,6 +44,7 @@
 from tfws.website import authentication
 from tfws.website import permissions
 from tfws.website import roles
+from tfws.website import members
 from tfws.website.catalog import setup_catalog
 from tfws.website.layer import IWebSiteLayer
 from tfws.website.i18n import MessageFactory as _
@@ -87,6 +88,9 @@
     def __repr__(self):
         return '<%s %r>' % (self.__class__.__name__, self.__name__)
 
+    def traverse(self, name):
+        if name == 'members':
+            return members.Members(self)
 
 class Index(mars.view.PageletView):
     """Temp display view for site"""

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/site.txt
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/site.txt	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/site.txt	2007-08-12 10:33:25 UTC (rev 78765)
@@ -99,9 +99,6 @@
     >>> darryl
     <AuthenticatedPrincipal...>
 
-    >>> #IAuthenticatedPrincipal.providedBy(bob)
-    True
-
 we get an authenticated principal.
 
 Catalog
@@ -136,21 +133,19 @@
     >>> interfaces.IFolderIndex.providedBy(page)
     False
 
-View the site
--------------
+Members
+-------
 
-I haven't figure a way to ``grok`` in the tests except to do it explicitly so
-here we grok the view we want to test.
+Members are a stub object to provide views to the members in the authentication
+utility.
 
-    >>> from mars.view.meta import PageletViewGrokker
-    >>> PageletViewGrokker().grok('', site.Index, WebSite, module_info, None)
-    True
-    >>> from mars.template.meta import TemplateFactoryGrokker
-    >>> TemplateFactoryGrokker().grok('', site.IndexTemplate, None, module_info, None)
-    True
-    >>> from mars.template.meta import LayoutFactoryGrokker
-    >>> module_info.path = skin.__file__
-    >>> LayoutFactoryGrokker().grok('', skin.Layout, None, module_info, None)
-    True
-    >>> view = zope.component.getMultiAdapter((website, request), name='index')
-    >>> #print view()
+    >>> from tfws.website.members import Members
+    >>> members = Members(context=website)
+
+We can traverse Members to a website member.
+
+    >>> tmember = members.traverse(member.__name__)
+    >>> print (tmember.login, tmember.title, tmember.email, tmember.password)
+    (u'darryl', u'Darryl Cousins', u'darryl at tfws.org.nz', 'tfws')
+
+

Added: Sandbox/darrylcousins/tfws.website/src/tfws/website/table.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/table.py	                        (rev 0)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/table.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -0,0 +1,30 @@
+from zope.traversing import api
+from zope.dublincore.interfaces import IZopeDublinCore
+from zope.traversing.browser import absoluteURL
+
+from zc.table import column
+
+class CheckboxColumn(column.Column):
+
+    def renderCell(self, item, formatter):
+        widget = (u'<input type="checkbox" '
+                  u'name="selected:list" value="%s">')
+        return widget %api.getName(item)
+
+
+def getCreatedDate(item, formatter):
+    formatter = formatter.request.locale.dates.getFormatter('date', 'short')
+    return formatter.format(IZopeDublinCore(item).created)
+
+
+def getModifiedDate(item, formatter):
+    formatter = formatter.request.locale.dates.getFormatter('date', 'short')
+    return formatter.format(IZopeDublinCore(item).modified)
+
+
+def link(view='index', title=''):
+    def anchor(value, item, formatter):
+        url = absoluteURL(item, formatter.request) + '/' + view
+        return u'<a href="%s" title="%s">%s</a>' %(url, title, value)
+    return anchor
+


Property changes on: Sandbox/darrylcousins/tfws.website/src/tfws/website/table.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/contents.pt
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/contents.pt	                        (rev 0)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/contents.pt	2007-08-12 10:33:25 UTC (rev 78765)
@@ -0,0 +1,42 @@
+<h1 tal:content="view/title">Tree Fern Web Site Demo</h1>
+<div class="message"
+     tal:condition="view/status"
+     tal:content="view/status"
+     i18n:translate="">
+  Something happened.
+</div>
+
+<form action="" method="post"
+      tal:attributes="action request/URL">
+
+  <tal:block
+      condition="view/items"
+      replace="structure view/table" />
+
+  <div
+      tal:condition="not: view/items"
+      i18n:translate="">
+    There are no items to display.
+  </div>
+
+  <div id="actionsView" tal:condition="view/authActions">
+    <span class="actionButtons">
+      <tal:block condition="view/authAdd">
+      <input type="submit" class="button" name="ADD" value="Add"
+             i18n:attributes="value" />
+    </tal:block>
+      <tal:block condition="view/items">
+      <tal:block condition="view/authDelete">
+        <input type="submit" class="button" name="DELETE" value="Delete"
+               i18n:attributes="value" />
+        <input type="text" id="confirm_delete" name="confirm_delete"
+               size="5" />
+        <label for="confirm_delete" i18n:translate="">
+          (Type "yes" to delete.)
+        </label>
+    </tal:block>
+    </tal:block>
+    </span>
+  </div>
+
+</form>

Added: Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/member.pt
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/member.pt	                        (rev 0)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/templates/member.pt	2007-08-12 10:33:25 UTC (rev 78765)
@@ -0,0 +1,21 @@
+<h1 tal:content="context/title">Tree Fern</h1>
+
+<tal:block repeat="widget view/widgets/values">
+  <div id="" class="row"
+       tal:attributes="id string:${widget/id}-row"
+       tal:condition="python:widget.mode != 'hidden'">
+    <metal:block define-macro="widget-row">
+      <div class="label">
+        <label tal:attributes="for widget/id">
+          <span i18n:translate=""
+              tal:content="widget/label">label</span>
+          <span class="required"
+                tal:condition="widget/required">*</span>
+        </label>
+      </div>
+      <div class="widget" tal:content="structure widget/render">
+        The widget.
+      </div>
+    </metal:block>
+  </div>
+</tal:block>

Modified: Sandbox/darrylcousins/tfws.website/src/tfws/website/tools/member.py
===================================================================
--- Sandbox/darrylcousins/tfws.website/src/tfws/website/tools/member.py	2007-08-12 10:24:49 UTC (rev 78764)
+++ Sandbox/darrylcousins/tfws.website/src/tfws/website/tools/member.py	2007-08-12 10:33:25 UTC (rev 78765)
@@ -70,7 +70,7 @@
              'selected': u''
             })
     
-        action = site_url + '/edit-account'
+        action = '%s/members/%s/edit' % (site_url, self.request.principal.id)
         result.append(
             {'title': _("Edit Account"),
              'action': action,
@@ -78,7 +78,7 @@
              'selected': request_url.endswith(action) and u'selected' or u''
             })
     
-        action = site_url + '/account'
+        action = '%s/members/%s/index' % (site_url, self.request.principal.id)
         result.append(
             {'title': _("Account"),
              'action': action,



More information about the Checkins mailing list