Author: whit
Date: 2007-06-13 10:17:21 -0400 (Wed, 13 Jun 2007)
New Revision: 6313

Added:
   opencore/trunk/opencore/nui/formhandler.py
Modified:
   opencore/trunk/opencore/nui/README.txt
   opencore/trunk/opencore/nui/base.py
   opencore/trunk/opencore/nui/project/view.py
   opencore/trunk/opencore/nui/wiki/configure.zcml
Log:

* move all formhandling decorators to formhandler.py

* fix test for new member_info

* fill dict rather than set lots of vars in member_info_for_id

Modified: opencore/trunk/opencore/nui/README.txt
===================================================================
--- opencore/trunk/opencore/nui/README.txt      2007-06-12 22:51:14 UTC (rev 
6312)
+++ opencore/trunk/opencore/nui/README.txt      2007-06-13 14:17:21 UTC (rev 
6313)
@@ -106,13 +106,20 @@
     'http://nohost/plone/people/test_user_1_/test_user_1_'
 
     >>> pprint(pview.member_info)
-    {'fullname': '',
+    {'affiliations': '',
+     'background': '',
+     'favorites': '',
+     'fullname': '',
      'id': 'test_user_1_',
-     'lastlogin': DateTime('2000/01/01'),
+     'lastlogin': 'January 1, 2000',
+     'location': '',
+     'membersince': 'Today',
+     'portrait_url': '++resource++img/default-portrait.jpg',
+     'skills': '',
+     'statement': '',
      'url': 'http://nohost/plone/people/test_user_1_'}
 
 
-
 include
 -------
 

Modified: opencore/trunk/opencore/nui/base.py
===================================================================
--- opencore/trunk/opencore/nui/base.py 2007-06-12 22:51:14 UTC (rev 6312)
+++ opencore/trunk/opencore/nui/base.py 2007-06-13 14:17:21 UTC (rev 6313)
@@ -22,6 +22,7 @@
 from topp.utils.pretty_date import prettyDate
 from topp.utils.pretty_text import truncate
 from zope.component import getMultiAdapter, adapts, adapter
+from opencore.nui.formhandler import button, post_only, anon_only, octopus
 
 view.memoizedproperty = lambda func: property(view.memoize(func))
 view.mcproperty = lambda func: property(view.memoize_contextless(func))
@@ -130,57 +131,42 @@
         return self.member_info_for_member(self.viewedmember())
 
     def member_info_for_member(self, member):
-        result = {}
         if member is not None:
             if IReMember.providedBy(member):
-                id = member.getId()
-                fullname = member.getFullname()
-                membersince = prettyDate(member.getRawCreation_date())
-                lastlogin = prettyDate(member.getLast_login_time())
-                location = member.getLocation()
-                statement = member.getStatement()
-                skills = member.getSkills()
-                affiliations = member.getAffiliations()
-                background = member.getBackground()
-                favorites = member.getFavorites()
+                result = dict(
+                    id = member.getId(),
+                    fullname = member.getFullname(),
+                    membersince = prettyDate(member.getRawCreation_date()),
+                    lastlogin = prettyDate(member.getLast_login_time()),
+                    location = member.getLocation(),
+                    statement = member.getStatement(),
+                    skills = member.getSkills(),
+                    affiliations = member.getAffiliations(),
+                    background = member.getBackground(),
+                    favorites = member.getFavorites(),
+                    url='')
             else:
-                # XXX TODO
+                # XXX TODO 
                 # we're an old school member object, e.g. an admin user
-                id = member.id
-                fullname = member.fullname
-                membersince = '' #prettyDate(member.creation_date)
-                lastlogin = '' #prettyDate(member.last_login_time)
-                location = '' #member.location
-                statement = ''
-                skills = ''
-                affiliations = ''
-                background = ''
-                favorites = ''
-                
-            url = ''
-            folder = self.membertool.getHomeFolder(id)
-            if folder:
-                url = folder.absolute_url()
+                result = dict(id = member.id,
+                    fullname = member.fullname)
 
+                for key in 'membersince', 'lastlogin','location', \
+                        'statement', 'affiliations', 'skills',\
+                        'background',  'url', 'favorites',:
+                    result[key]=''
+
+            folder = self.membertool.getHomeFolder(result['id'])
+            if folder:
+                result["url"] = folder.absolute_url()
+                
+            result['portrait_url'] = self.defaultPortraitURL
             portrait = member.getProperty('portrait', None)
-            portraiturl = portrait and portrait.absolute_url() or 
self.defaultPortraitURL
+            if portrait:
+                result['portrait_url'] = portrait.absolute_url()
 
-            result.update(id=id,
-                          url=url,
-                          portraiturl=portraiturl,
-                          fullname=fullname,
-                          membersince=membersince,
-                          lastlogin=lastlogin,
-                          location=location,
-                          statement=statement,
-                          skills=skills,
-                          affiliations=affiliations,
-                          background=background,
-                          favorites=favorites,
-                         )
         return result
 
-
     @view.mcproperty
     def project_info(self):
         """
@@ -336,29 +322,7 @@
     def _clear_instance_memos(self):
         pass
 
-def button(name=None):
-    def curry(handle_request):
-        def new_method(self):
-            if self.request.get(name):
-                return handle_request(self)
-            return None
-        return new_method
-    return curry
 
-
-def post_only(raise_=True):
-    def inner_post_only(func):
-        """usually wrapped by a button"""
-        def new_method(self):
-            if self.request.environ['REQUEST_METHOD'] == 'GET':
-                if raise_:
-                    raise Forbidden('GET is not allowed here')
-                return
-            return func(self)
-        return new_method
-    return inner_post_only
-
-
 def aq_iface(obj, iface):
     obj = aq_inner(obj)
     while obj is not None and not iface.providedBy(obj):
@@ -366,18 +330,6 @@
     return obj
 
 
-def anon_only(redirect_to=None):
-    def inner_anon_only(func):
-        def new_method(self, *args, **kw):
-            redirect_path = redirect_to
-            if not redirect_path:
-                redirect_path = self.came_from
-            if self.loggedin:
-                return self.redirect(redirect_path)
-            return func(self, *args, **kw)
-        return new_method
-    return inner_anon_only
-
 def static_txt(fname):
     """module level cache?"""
     def new_func(self):

Added: opencore/trunk/opencore/nui/formhandler.py
===================================================================
--- opencore/trunk/opencore/nui/formhandler.py                          (rev 0)
+++ opencore/trunk/opencore/nui/formhandler.py  2007-06-13 14:17:21 UTC (rev 
6313)
@@ -0,0 +1,88 @@
+"""Decorators for working with form submission"""
+
+from zExceptions import Forbidden
+
+def button(name=None):
+    def curry(handle_request):
+        def new_method(self):
+            if self.request.get(name):
+                return handle_request(self)
+            return None
+        return new_method
+    return curry
+
+
+def post_only(raise_=True):
+    def inner_post_only(func):
+        """usually wrapped by a button"""
+        def new_method(self):
+            if self.request.environ['REQUEST_METHOD'] == 'GET':
+                if raise_:
+                    raise Forbidden('GET is not allowed here')
+                return
+            return func(self)
+        return new_method
+    return inner_post_only
+
+
+def anon_only(redirect_to=None):
+    def inner_anon_only(func):
+        def new_method(self, *args, **kw):
+            redirect_path = redirect_to
+            if not redirect_path:
+                redirect_path = self.came_from
+            if self.loggedin:
+                return self.redirect(redirect_path)
+            return func(self, *args, **kw)
+        return new_method
+    return inner_anon_only
+
+
+def octopus(func):
+    """
+    A (hopefully) generic decorator to handle complex forms with
+    multiple actions and multiple items which can be acted upon
+    either singly or in a batch, with the call made either 
+    asynchronously or synchronously with javascript disabled.
+
+    This method expects to decorate a method which takes, in order,
+      * an action to apply (a unique identifier for a method to
+                            delegate to or an action to perform),
+      * a list of targets (unique identifiers for items to act upon),
+      * a list of fields (a dict of fieldname:values to apply to the
+                          targets, in the same order as the targets)
+
+    It expects to be returned a value to be sent, unmodified, directly
+    to the client in the case of an AJAX request.
+
+    It expects a very specific format for the request; this is 
+    documented in opencore.nui.project/contents.txt
+    """
+    def inner(self):
+        # XXX todo don't rely on underscore special character
+        target, action = self.request.form.get("task").split("_")
+
+        if target == 'batch' and self.request.form.get('batch[]'):
+            target = self.request.form.get("batch[]")
+        if not isinstance(target, (tuple, list)):
+            target = [target]
+
+        # grab items' fields from request and fill dicts in an ordered list
+        fields = []
+        for item in target:
+            itemdict = {}
+            filterby = item + '_'
+            keys = [key for key in self.request.form if 
key.startswith(filterby)]
+            for key in keys:
+                itemdict[key.replace(filterby, '')] = 
self.request.form.get(key)
+            fields.append(itemdict)
+
+        ret = func(self, action, target, fields)
+        mode = self.request.form.get("mode")
+        if mode == "async":
+            return ret
+        return self.redirect(self.request.environ['HTTP_REFERER'])
+
+    return inner
+
+

Modified: opencore/trunk/opencore/nui/project/view.py
===================================================================
--- opencore/trunk/opencore/nui/project/view.py 2007-06-12 22:51:14 UTC (rev 
6312)
+++ opencore/trunk/opencore/nui/project/view.py 2007-06-13 14:17:21 UTC (rev 
6313)
@@ -1,72 +1,21 @@
-from zope import event
-from zExceptions import BadRequest
-from zExceptions import Redirect
-
 from Acquisition import aq_parent
-
-from plone.memoize.view import memoize
-from plone.memoize.view import memoize_contextless
-from plone.memoize.instance import memoizedproperty
-
-from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
 from Products.CMFCore.utils import getToolByName
 from Products.CMFCore.permissions import DeleteObjects
 from Products.CMFPlone.utils import transaction_note
-
-from opencore.interfaces.event import AfterProjectAddedEvent, 
AfterSubProjectAddedEvent
+from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
 from opencore.interfaces import IAddProject, IAddSubProject 
-from opencore.project.utils import get_featurelets
-from opencore.nui.base import BaseView, button
+from opencore.interfaces.event import AfterProjectAddedEvent, 
AfterSubProjectAddedEvent
+from opencore.nui import formhandler
+from opencore.nui.base import BaseView
 from opencore.nui.main import SearchView
+from opencore.project.utils import get_featurelets
+from plone.memoize.instance import memoize, memoizedproperty
+from plone.memoize.view import memoize_contextless
+from zExceptions import BadRequest
+from zExceptions import Redirect
+from zope import event
 
-def octopus_form_handler(func):
-    """
-    A (hopefully) generic decorator to handle complex forms with
-    multiple actions and multiple items which can be acted upon
-    either singly or in a batch, with the call made either 
-    asynchronously or synchronously with javascript disabled.
 
-    This method expects to decorate a method which takes, in order,
-      * an action to apply (a unique identifier for a method to
-                            delegate to or an action to perform),
-      * a list of targets (unique identifiers for items to act upon),
-      * a list of fields (a dict of fieldname:values to apply to the
-                          targets, in the same order as the targets)
-
-    It expects to be returned a value to be sent, unmodified, directly
-    to the client in the case of an AJAX request.
-
-    It expects a very specific format for the request; this is 
-    documented in contents.txt
-    """
-    def inner(self):
-        # XXX todo don't rely on underscore special character
-        target, action = self.request.form.get("task").split("_")
-
-        if target == 'batch' and self.request.form.get('batch[]'):
-            target = self.request.form.get("batch[]")
-        if not isinstance(target, (tuple, list)):
-            target = [target]
-
-        # grab items' fields from request and fill dicts in an ordered list
-        fields = []
-        for item in target:
-            itemdict = {}
-            filterby = item + '_'
-            keys = [key for key in self.request.form if 
key.startswith(filterby)]
-            for key in keys:
-                itemdict[key.replace(filterby, '')] = 
self.request.form.get(key)
-            fields.append(itemdict)
-
-        ret = func(self, action, target, fields)
-        mode = self.request.form.get("mode")
-        if mode == "async":
-            return ret
-        return self.redirect(self.request.environ['HTTP_REFERER'])
-
-    return inner
-
-
 class ProjectContentsView(BaseView):
     
     contents_row_snippet = ZopeTwoPageTemplateFile('item_row.pt')
@@ -183,7 +132,7 @@
                 parent = self.context.restrictedTraverse(parent)
                 parent.manage_delObjects(child_ids)
 
-    @octopus_form_handler
+    @formhandler.octopus
     def modify_contents(self, action, sources, fields=None):
         item_type = self.request.form.get("item_type")
 
@@ -212,7 +161,7 @@
 
 class ProjectPreferencesView(BaseView):
         
-    @button('update')
+    @formhandler.button('update')
     def handle_request(self):
         self.context.validate(REQUEST=self.request,
                               errors=self.errors, data=1, metadata=0)
@@ -223,7 +172,7 @@
 
 class ProjectAddView(BaseView):
 
-    @button('add')
+    @formhandler.button('add')
     def handle_request(self):
         putils = getToolByName(self.context, 'plone_utils')
         self.request.set('__initialize_project__', True)
@@ -291,7 +240,7 @@
         self.active_states = team.getActiveStates()
         self.sort_by = None
    
-    @button('sort')
+    @formhandler.button('sort')
     def handle_request(self):
         self.sort_by = self.request.get('sort_by', None)
 
@@ -302,18 +251,18 @@
                  sort_on='made_active_date',
                  sort_order='descending',
                  )
+        
         membership_brains = self.catalog(**query)
         mem_ids = [b.getId for b in membership_brains]
+        
         query = dict(portal_type='OpenMember',
                      getId=mem_ids,
                      )
+        
         member_brains = self.membranetool(**query)
-        lookup_dict = dict((b.getId, b) for b in member_brains)
+        lookup_dict = dict((b.getId, b) for b in member_brains if b.getId)
 
-        results = [lookup_dict.get(b.getId, None) for b in membership_brains]
-        # filter out None's, which appear for admins that are not openmembers
-        results = filter(None, results)
-        return self._get_batch(results)
+        return self._get_batch(lookup_dict.get(b.getId) for b in 
membership_brains)
 
     def handle_sort_location(self):
         query = dict(portal_type='OpenMembership',
@@ -346,8 +295,7 @@
         results = self.membranetool(**query)
         return self._get_batch(results)
 
-    @property
-    @memoize
+    @memoizedproperty
     def memberships(self):
         try:
             sort_fn = getattr(self, 'handle_sort_%s' % self.sort_by)

Modified: opencore/trunk/opencore/nui/wiki/configure.zcml
===================================================================
--- opencore/trunk/opencore/nui/wiki/configure.zcml     2007-06-12 22:51:14 UTC 
(rev 6312)
+++ opencore/trunk/opencore/nui/wiki/configure.zcml     2007-06-13 14:17:21 UTC 
(rev 6313)
@@ -100,5 +100,4 @@
      permission="cmf.ModifyPortalContent"
      />
 
-
 </configure>



--
Archive: 
http://www.openplans.org/projects/opencore/lists/openplans-svn/archive/2007/06/1181744242066
To unsubscribe send an email with subject unsubscribe to [EMAIL PROTECTED]  
Please contact [EMAIL PROTECTED] for questions.

Reply via email to