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:
parent
7ff56a6520
commit
96a592f125
22 changed files with 141 additions and 179 deletions
|
@ -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)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue