Improved management of indexes; always provide str and not unicode strings as index values; search screen may now include javascripts and css like those required by the date chooser; removed CSS parser, basic XmlUnmarshaller can do it by itself.

This commit is contained in:
Gaetan Delannay 2010-12-17 14:46:55 +01:00
parent 2124cffa5e
commit a30949a621
15 changed files with 213 additions and 132 deletions

View file

@ -165,10 +165,12 @@ class ToolMixin(BaseMixin):
return res
def getSearchInfo(self, contentType, refInfo=None):
'''Returns a tuple:
1) The list of searchable fields (ie fields among all indexed fields)
2) The number of columns for layouting those fields.'''
'''Returns, as a dict:
- the list of searchable fields (= some fields among all indexed
fields);
- the number of columns for layouting those fields.'''
fields = []
fieldDicts = []
if refInfo:
# The search is triggered from a Ref field.
refField = self.getRefInfo(refInfo)[1]
@ -180,9 +182,12 @@ class ToolMixin(BaseMixin):
fieldNames = getattr(at, 'searchFieldsFor%s' % contentType,())
nbOfColumns = getattr(at, 'numberOfSearchColumnsFor%s' %contentType)
for name in fieldNames:
appyType = self.getAppyType(name, asDict=True,className=contentType)
appyType = self.getAppyType(name,asDict=False,className=contentType)
appyDict = self.getAppyType(name, asDict=True,className=contentType)
fields.append(appyType)
return fields, nbOfColumns
fieldDicts.append(appyDict)
return {'fields': fields, 'nbOfColumns': nbOfColumns,
'fieldDicts': fieldDicts}
def getImportElements(self, contentType):
'''Returns the list of elements that can be imported from p_path for
@ -336,13 +341,12 @@ class ToolMixin(BaseMixin):
if not searchName:
# It is the global search for all objects pf p_contentType
searchName = contentType
s = self.REQUEST.SESSION
uids = {}
i = -1
for obj in res.objects:
i += 1
uids[startNumber+i] = obj.UID()
s['search_%s' % searchName] = uids
self.REQUEST.SESSION['search_%s' % searchName] = uids
return res.__dict__
def getResultColumnsNames(self, contentType, refField):
@ -452,15 +456,6 @@ class ToolMixin(BaseMixin):
return pythonClass.maySearch(self.appy())
return True
def userMayNavigate(self, obj):
'''This method checks if the currently logged user can display the
navigation panel within the portlet. This is done by calling method
"mayNavigate" on the currently shown object. If no such method
exists, we return True.'''
appyObj = obj.appy()
if hasattr(appyObj, 'mayNavigate'): return appyObj.mayNavigate()
return True
def onImportObjects(self):
'''This method is called when the user wants to create objects from
external data.'''
@ -614,7 +609,7 @@ class ToolMixin(BaseMixin):
field, this method returns information about this reference: the
source content type and the Ref field (Appy type). If p_refInfo is
not given, we search it among search criteria in the session.'''
if not refInfo:
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)
@ -847,6 +842,8 @@ class ToolMixin(BaseMixin):
session.invalidate()
from Products.CMFPlone import transaction_note
transaction_note('Logged out')
self.getProductConfig().logger.info('User "%s" has been logged out.' % \
userId)
# Remove user from variable "loggedUsers"
from appy.gen.plone25.installer import loggedUsers
if loggedUsers.has_key(userId): del loggedUsers[userId]

View file

@ -276,16 +276,22 @@ class BaseMixin:
res[appyType.name] = appyType.getValue(self)
return res
def addDataChange(self, changes):
def addDataChange(self, changes, notForPreviouslyEmptyValues=False):
'''This method allows to add "manually" a data change into the objet's
history. Indeed, data changes are "automatically" recorded only when
a HTTP form is uploaded, not if, in the code, a setter is called on
a field. The method is also called by the method historizeData below,
that performs "automatic" recording when a HTTP form is uploaded.'''
a field. The method is also called by m_historizeData below, that
performs "automatic" recording when a HTTP form is uploaded. Field
changes for which the previous value was empty are not recorded into
the history if p_notForPreviouslyEmptyValues is True.'''
# Add to the p_changes dict the field labels
for fieldName in changes.iterkeys():
for fieldName in changes.keys():
appyType = self.getAppyType(fieldName)
changes[fieldName] = (changes[fieldName], appyType.labelId)
if notForPreviouslyEmptyValues and \
appyType.isEmptyValue(changes[fieldName], self):
del changes[fieldName]
else:
changes[fieldName] = (changes[fieldName], appyType.labelId)
# Create the event to record in the history
DateTime = self.getProductConfig().DateTime
state = self.portal_workflow.getInfoFor(self, 'review_state')
@ -474,21 +480,23 @@ class BaseMixin:
res.append(appyType)
return res
def getCssAndJs(self, layoutType, page):
'''Returns the CSS and Javascript files that need to be loaded by the
p_page for the given p_layoutType.'''
def getCssAndJs(self, fields, layoutType):
'''Gets the list of Javascript and CSS files required by Appy types
p_fields when shown on p_layoutType.'''
# lists css and js below are not sets, because order of Javascript
# inclusion can be important, and this could be losed by using sets.
css = []
js = []
for appyType in self.getAppyTypes(layoutType, page):
typeCss = appyType.getCss(layoutType)
if typeCss:
for tcss in typeCss:
if tcss not in css: css.append(tcss)
typeJs = appyType.getJs(layoutType)
if typeJs:
for tjs in typeJs:
if tjs not in js: js.append(tjs)
return css, js
for field in fields:
fieldCss = field.getCss(layoutType)
if fieldCss:
for fcss in fieldCss:
if fcss not in css: css.append(fcss)
fieldJs = field.getJs(layoutType)
if fieldJs:
for fjs in fieldJs:
if fjs not in js: js.append(fjs)
return {'css':css, 'js':js}
def getAppyTypesFromNames(self, fieldNames, asDict=True, addTitle=True):
'''Gets the Appy types named p_fieldNames. If 'title' is not among
@ -766,12 +774,27 @@ class BaseMixin:
res = True
return res
def mayNavigate(self):
'''May the currently logged user see the navigation panel linked to
this object?'''
appyObj = self.appy()
if hasattr(appyObj, 'mayNavigate'): return appyObj.mayNavigate()
return True
def mayDelete(self):
'''May the currently logged user delete this object? This condition
comes as an addition/refinement to the corresponding workflow
permission.'''
appyObj = self.appy()
if hasattr(appyObj, 'mayDelete'): return appyObj.mayDelete()
return True
def executeAppyAction(self, actionName, reindex=True):
'''Executes action with p_fieldName on this object.'''
appyType = self.getAppyType(actionName)
actionRes = appyType(self.appy())
if self.getParentNode().get(self.id):
# Else, it means that the action has led to self's removal.
# Else, it means that the action has led to self's deletion.
self.reindexObject()
return appyType.result, actionRes
@ -869,7 +892,17 @@ class BaseMixin:
blank value is prepended to the list. If no p_className is defined,
the field is supposed to belong to self's class'''
appyType = self.getAppyType(name, className=className)
return appyType.getPossibleValues(self,withTranslations,withBlankValue)
if className:
# We need an instance of className, but self can be an instance of
# another class. So here we will search such an instance.
brains = self.executeQuery(className, maxResults=1, brainsOnly=True)
if brains:
obj = brains[0].getObject()
else:
obj = self
else:
obj = self
return appyType.getPossibleValues(obj, withTranslations, withBlankValue)
def appy(self):
'''Returns a wrapper object allowing to manipulate p_self the Appy