appy.pod: bugfix when importing images under Windows (https://answers.launchpad.net/appy/+question/171611); appy.gen: bugfix while validating file fields which are mandatory; stopped using uid_catalog and added index 'UID' in portal_catalog; bugfix while searching objects in the limits of a Ref field; display user info in the main template (name, id, roles); when creating an object from a reference, after creation, appy brings the user back to the view page where the Ref field was.

This commit is contained in:
Gaetan Delannay 2011-09-20 19:21:48 +02:00
parent 7ff56a6520
commit 96a592f125
22 changed files with 141 additions and 179 deletions

View file

@ -87,7 +87,7 @@ class ToolMixin(BaseMixin):
if appyType.name == 'title': continue # Will be included by default.
res.append((appyType.name, self.translate(appyType.labelId)))
# Add object state
res.append(('workflowState', self.translate('workflow_state')))
res.append(('state', self.translate('workflow_state')))
return res
def _appy_getSearchableFields(self, contentType):
@ -108,7 +108,8 @@ class ToolMixin(BaseMixin):
fieldDicts = []
if refInfo:
# The search is triggered from a Ref field.
refField = self.getRefInfo(refInfo)[1]
refObject, fieldName = self.getRefInfo(refInfo)
refField = refObject.getAppyType(fieldName)
fieldNames = refField.queryFields or ()
nbOfColumns = refField.queryNbCols
else:
@ -172,7 +173,7 @@ class ToolMixin(BaseMixin):
def getObject(self, uid, appy=False):
'''Allows to retrieve an object from its p_uid.'''
res = self.uid_catalog(UID=uid)
res = self.portal_catalog(UID=uid)
if res:
res = res[0].getObject()
if appy:
@ -183,10 +184,10 @@ class ToolMixin(BaseMixin):
search=None, remember=False, brainsOnly=False,
maxResults=None, noSecurity=False, sortBy=None,
sortOrder='asc', filterKey=None, filterValue=None,
refField=None):
refObject=None, refField=None):
'''Executes a query on a given p_contentType (or several, separated
with commas) in Plone's portal_catalog. If p_searchName is specified,
it corresponds to:
with commas) in portal_catalog. If p_searchName is specified, it
corresponds to:
1) a search defined on p_contentType: additional search criteria
will be added to the query, or;
2) "_advanced": in this case, additional search criteria will also
@ -221,8 +222,8 @@ class ToolMixin(BaseMixin):
to take into account: the corresponding search value is in
p_filterValue.
If p_refField is given, the query is limited to the objects that are
referenced through it.'''
If p_refObject and p_refField are given, the query is limited to the
objects that are referenced from p_refObject through p_refField.'''
# Is there one or several content types ?
if contentType.find(',') != -1:
portalTypes = contentType.split(',')
@ -267,6 +268,9 @@ class ToolMixin(BaseMixin):
# TODO This value needs to be merged with an existing one if already
# in params, or, in a first step, we should avoid to display the
# corresponding filter widget on the screen.
if refObject:
refField = refObject.getAppyType(refField)
params['UID'] = refObject._appy_getSortedField(refField.name).data
# Determine what method to call on the portal catalog
if noSecurity: catalogMethod = 'unrestrictedSearchResults'
else: catalogMethod = 'searchResults'
@ -297,12 +301,14 @@ class ToolMixin(BaseMixin):
self.REQUEST.SESSION['search_%s' % searchName] = uids
return res.__dict__
def getResultColumnsNames(self, contentType, refField):
def getResultColumnsNames(self, contentType, refInfo):
contentTypes = contentType.strip(',').split(',')
resSet = None # Temporary set for computing intersections.
res = [] # Final, sorted result.
fieldNames = None
appyTool = self.appy()
refField = None
if refInfo[0]: refField = refInfo[0].getAppyType(refInfo[1])
for cType in contentTypes:
if refField:
fieldNames = refField.shownInfo
@ -432,7 +438,7 @@ class ToolMixin(BaseMixin):
def isSortable(self, name, className, usage):
'''Is field p_name defined on p_className sortable for p_usage purposes
(p_usage can be "ref" or "search")?'''
if (',' in className) or (name == 'workflowState'): return False
if (',' in className) or (name == 'state'): return False
appyType = self.getAppyType(name, className=className)
if appyType: return appyType.isSortable(usage=usage)
@ -567,9 +573,10 @@ class ToolMixin(BaseMixin):
if not refInfo and (self.REQUEST.get('search', None) == '_advanced'):
criteria = self.REQUEST.SESSION.get('searchCriteria', None)
if criteria and criteria.has_key('_ref'): refInfo = criteria['_ref']
if not refInfo: return ('', None)
sourceContentType, refField = refInfo.split(':')
return refInfo, self.getAppyType(refField, className=sourceContentType)
if not refInfo: return (None, None)
objectUid, fieldName = refInfo.split(':')
obj = self.getObject(objectUid)
return obj, fieldName
def getSearches(self, contentType):
'''Returns the list of searches that are defined for p_contentType.
@ -663,7 +670,7 @@ class ToolMixin(BaseMixin):
res['backText'] = self.translate(label)
else:
fieldName, pageName = d2.split(':')
sourceObj = self.uid_catalog(UID=d1)[0].getObject()
sourceObj = self.portal_catalog(UID=d1)[0].getObject()
label = '%s_%s' % (sourceObj.meta_type, fieldName)
res['backText'] = '%s : %s' % (sourceObj.Title(),
self.translate(label))
@ -739,7 +746,7 @@ class ToolMixin(BaseMixin):
except KeyError: pass
except IndexError: pass
if uid:
brain = self.uid_catalog(UID=uid)
brain = self.portal_catalog(UID=uid)
if brain:
sibling = brain[0].getObject()
res[urlKey] = sibling.getUrl(nav=newNav % (index + 1),
@ -860,4 +867,15 @@ class ToolMixin(BaseMixin):
if ',' in contentType: return ()
return [f.__dict__ for f in self.getAllAppyTypes(contentType) \
if (f.type == 'Pod') and (f.show == 'result')]
def getUserLine(self, user):
'''Returns a one-line user info as shown on every page.'''
res = [user.getId()]
name = user.getProperty('fullname')
if name: res.insert(0, name)
rolesToShow = [r for r in user.getRoles() \
if r not in ('Authenticated', 'Member')]
if rolesToShow:
res.append(', '.join([self.translate(r) for r in rolesToShow]))
return ' | '.join(res)
# ------------------------------------------------------------------------------

View file

@ -37,8 +37,8 @@ class BaseMixin:
rq = self.REQUEST
obj = self
if created:
obj = self.portal_factory.doCreate(self, self.id) # portal_factory
# creates the final object from the temp object.
# portal_factory creates the final object from the temp object.
obj = self.portal_factory.doCreate(self, self.id)
previousData = None
if not created: previousData = self.rememberPreviousData()
# Perform the change on the object, unless self is a tool being created.
@ -61,7 +61,7 @@ class BaseMixin:
# Get the initiator
splitted = rq['nav'].split('.')
if splitted[0] == 'search': return # Not an initiator but a search.
initiator = self.uid_catalog(UID=splitted[1])[0].getObject()
initiator = self.getTool().getObject(splitted[1])
fieldName = splitted[2].split(':')[0]
initiator.appy().link(fieldName, obj)
@ -174,20 +174,24 @@ class BaseMixin:
errorMessage = self.translate(
'Please correct the indicated errors.', domain='plone')
isNew = rq.get('is_new') == 'True'
# Go back to the consult view if the user clicked on 'Cancel'
# If this object is created from an initiator, get info about him.
initiator = None
initiatorPage = None
if rq.get('nav', '').startswith('ref.'):
splitted = rq['nav'].split('.')
initiator = tool.getObject(splitted[1])
initiatorPage = splitted[2].split(':')[1]
# If the user clicked on 'Cancel', go back to the previous page.
if rq.get('buttonCancel.x', None):
if isNew:
if rq.get('nav', ''):
# We can go back to the initiator page.
splitted = rq['nav'].split('.')
initiator = tool.getObject(splitted[1])
initiatorPage = splitted[2].split(':')[1]
urlBack = initiator.getUrl(page=initiatorPage, nav='')
else:
# Go back to the root of the site.
urlBack = tool.getSiteUrl()
if initiator:
# Go back to the initiator page.
urlBack = initiator.getUrl(page=initiatorPage, nav='')
else:
urlBack = self.getUrl()
if isNew:
# Go back to the root of the site.
urlBack = tool.getSiteUrl()
else:
urlBack = self.getUrl()
self.say(self.translate('Changes canceled.', domain='plone'))
return self.goto(urlBack)
@ -236,9 +240,11 @@ class BaseMixin:
if not obj.allows('View'):
return self.goto(tool.getSiteUrl(), msg)
if rq.get('buttonOk.x', None) or saveConfirmed:
# Go to the consult view for this object
obj.say(msg)
return self.goto(obj.getUrl())
if isNew and initiator:
return self.goto(initiator.getUrl(page=initiatorPage, nav=''))
else:
return self.goto(obj.getUrl())
if rq.get('buttonPrevious.x', None):
# Go to the previous page for this object.
# We recompute the list of phases and pages because things