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.