From ccf7e44eef9d1d60070127ba0d8f052c7b0a3be6 Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Wed, 22 Oct 2014 22:17:26 +0200 Subject: [PATCH] [gen] [gen] Action field: param confirm can be 'text': in this case, the confirm popup contains a textarea whose content is passed as param to the method speficied in param 'action'. Action fields can now be defined in a new layout 'buttons' (show='buttons') in order to appear, on the view layout, besides the extsting series of buttons (edit, next/previous pages...). --- fields/__init__.py | 2 +- fields/action.py | 29 +++-- gen/mail.py | 4 +- gen/mixins/__init__.py | 6 +- gen/ui/appy.css | 1 + gen/wrappers/__init__.py | 229 ++++++++++++++++++++++----------------- 6 files changed, 157 insertions(+), 114 deletions(-) diff --git a/fields/__init__.py b/fields/__init__.py index 61be700..b30c685 100644 --- a/fields/__init__.py +++ b/fields/__init__.py @@ -350,7 +350,7 @@ class Field: for r in res: if r == layoutType: return True return - elif res in ('view', 'edit', 'result'): + elif res in ('view', 'edit', 'result', 'buttons'): return res == layoutType return bool(res) diff --git a/fields/action.py b/fields/action.py index 7614f27..1170e15 100644 --- a/fields/action.py +++ b/fields/action.py @@ -29,18 +29,22 @@ class Action(Field): pxView = pxCell = Px('''
- + + onclick=":'askConfirm(%s,%s,%s,%s)' % (q('form'), q(formId), \ + q(labelConfirm), commentParam)"/>
''') @@ -78,13 +82,24 @@ class Action(Field): def getDefaultLayouts(self): return {'view': 'l-f', 'edit': 'lrv-f'} + def callAction(self, obj, method, hasParam, param): + '''Calls p_method on p_obj. m_method can be the single action as defined + in self.action or one of them is self.action contains several + methods. Calling m_method can be done with a p_param (when p_hasParam + is True), ie, when self.confirm is "text".''' + if hasParam: return method(obj, param) + else: return method(obj) + def __call__(self, obj): '''Calls the action on p_obj.''' + # Must we call the method(s) with a param ? + hasParam = self.confirm == 'text' + param = hasParam and obj.request.get('comment', None) if type(self.action) in sutils.sequenceTypes: # There are multiple Python methods res = [True, ''] for act in self.action: - actRes = act(obj) + actRes = self.callAction(obj, act, hasParam, param) if type(actRes) in sutils.sequenceTypes: res[0] = res[0] and actRes[0] if self.result.startswith('file'): @@ -95,7 +110,7 @@ class Action(Field): res[0] = res[0] and actRes else: # There is only one Python method - actRes = self.action(obj) + actRes = self.callAction(obj, self.action, hasParam, param) if type(actRes) in sutils.sequenceTypes: res = list(actRes) else: diff --git a/gen/mail.py b/gen/mail.py index ab52213..9d7125b 100644 --- a/gen/mail.py +++ b/gen/mail.py @@ -57,8 +57,8 @@ def sendMail(config, to, subject, body, attachments=None, log=None): else: msg = '' if log: - log('mail disabled%s: should send mail from %s to %s.' % \ - (msg, fromAddress, str(to))) + log('mail disabled%s: should send mail from %s to %d ' \ + 'recipient(s): %s.' % (msg, fromAddress, len(to), str(to))) log('subject: %s' % subject) log('body: %s' % body) if attachments and log: log('%d attachment(s).' % len(attachments)) diff --git a/gen/mixins/__init__.py b/gen/mixins/__init__.py index 849aa6e..6f65124 100644 --- a/gen/mixins/__init__.py +++ b/gen/mixins/__init__.py @@ -816,13 +816,15 @@ class BaseMixin: cssJs['js'] = js or () return res - def getAppyTypes(self, layoutType, pageName): + def getAppyTypes(self, layoutType, pageName, type=None): '''Returns the list of fields that belong to a given page (p_pageName) for a given p_layoutType. If p_pageName is None, fields of all pages - are returned.''' + are returned. If p_type is defined, only fields of this p_type are + returned. ''' res = [] for field in self.getAllAppyTypes(): if pageName and (field.page.name != pageName): continue + if type and (field.type != type): continue if not field.isShowable(self, layoutType): continue res.append(field) return res diff --git a/gen/ui/appy.css b/gen/ui/appy.css index a6393f5..5403495 100644 --- a/gen/ui/appy.css +++ b/gen/ui/appy.css @@ -72,6 +72,7 @@ input.buttonSmall { width: 100px !important; font-size: 85%; height: 18px; .help { cursor: help } .refLink { font-style: italic; padding-left: 5px; font-size: 90%; color: grey } .buttons { margin-left: 4px } +.objectButtons { margin-top: 5px } .message { position: absolute; top: -40px; left: 50%; font-size: 90%; width: 600px; border: 1px #F0C36D solid; padding: 6px; background-color: #F9EDBE; text-align: center; margin-left: -300px; diff --git a/gen/wrappers/__init__.py b/gen/wrappers/__init__.py index 1b3a385..2a12f10 100644 --- a/gen/wrappers/__init__.py +++ b/gen/wrappers/__init__.py @@ -381,22 +381,19 @@ class AbstractWrapper(object): pxTransitions = Px('''
+ id=":formId" action=":targetObj.absolute_url() + '/do'" + style="display: inline"> - - - - -
- - :transition.pxView - :uiGroup.px -
+ + + :transition.pxView + :uiGroup.px +
''') # Displays header information about an object: title, workflow-related info, @@ -458,103 +455,107 @@ class AbstractWrapper(object): # Shows the range of buttons (next, previous, save,...) and the workflow # transitions for a given object. pxButtons = Px(''' - - - - - - +
+ + + + + + + + + + + + + + - -
- - - + - - + value=":label"/> + + + + + - - - -
- - - - - - - - - - - - - - - - + + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + - :obj.pxTransitions
''') + + :obj.pxTransitions + + + +
+ :field.pxRender
+
''') # Displays the fields of a given page for a given object. pxFields = Px(''' @@ -1199,4 +1200,28 @@ class AbstractWrapper(object): return localRoles def raiseUnauthorized(self, msg=None): return self.o.raiseUnauthorized(msg) + + def sendMailIf(self, privilege, subject, body, attachments=None, + isRole=False): + '''Sends a mail related to this object to any active user having + p_privilege on it. If p_isRole is False, p_privilege is a permission. + Else, it is a role.''' + # Determine the list of recipients based on active users having + # p_privilege on p_self. + recipients = [] + for user in self.tool.users: + if (user.state == 'inactive'): continue + # Check if the user has p_privilege on this object + hasPrivilege = isRole and user.has_role or user.has_permission + if not hasPrivilege(privilege, self): continue + # Get the mail recipient for this user + recipient = user.getMailRecipient() + if not recipient: continue + recipients.append(recipient) + if recipients: + self.tool.sendMail(recipients, subject, body, attachments) + else: + name = isRole and 'role' or 'permission' + self.log('no recipient for sending mail about %s with %s %s.' % \ + (self.id, name, privilege)) # ------------------------------------------------------------------------------