Wrong index type for selection strings that are not multivalued.
This commit is contained in:
parent
7c2b8fed11
commit
9f4db88bdf
|
@ -402,11 +402,12 @@ class Type:
|
|||
res = True
|
||||
return res
|
||||
|
||||
def isSortable(self, usage='search'):
|
||||
def isSortable(self, usage):
|
||||
'''Can fields of this type be used for sorting purposes (when sorting
|
||||
search results (p_usage="search") or when sorting reference fields
|
||||
(p_usage="ref")?'''
|
||||
if usage == 'search': return self.indexed
|
||||
if usage == 'search':
|
||||
return self.indexed and not self.isMultiValued()
|
||||
elif usage == 'ref':
|
||||
return self.type in ('Integer', 'Float', 'Boolean', 'Date') or \
|
||||
((self.type == 'String') and (self.format == 0))
|
||||
|
|
|
@ -120,7 +120,7 @@ class Table(LayoutElement):
|
|||
'''Represents a table where to dispose graphical elements.'''
|
||||
simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
|
||||
'align')
|
||||
derivedRepls = {'view': 'hrv', 'cell': 'l'}
|
||||
derivedRepls = {'view': 'hrv', 'cell': 'ld'}
|
||||
def __init__(self, layoutString=None, style=None, css_class='',
|
||||
cellpadding=0, cellspacing=0, width='100%', align='left',
|
||||
other=None, derivedType=None):
|
||||
|
@ -191,7 +191,9 @@ class Table(LayoutElement):
|
|||
if char in rowDelimiters:
|
||||
valign = rowDelimiters[char]
|
||||
if self.isHeaderRow(rowContent):
|
||||
self.headerRow = Row(rowContent,valign,isHeader=True).get()
|
||||
if not self.headerRow:
|
||||
self.headerRow = Row(rowContent, valign,
|
||||
isHeader=True).get()
|
||||
else:
|
||||
self.rows.append(Row(rowContent, valign).get())
|
||||
rowContent = ''
|
||||
|
|
|
@ -451,7 +451,8 @@ class PloneInstaller:
|
|||
n = appyType.name
|
||||
indexName = 'get%s%s' % (n[0].upper(), n[1:])
|
||||
indexType = 'FieldIndex'
|
||||
if (appyType.type == 'String') and appyType.isSelect:
|
||||
if (appyType.type == 'String') and appyType.isSelect and \
|
||||
appyType.isMultiValued():
|
||||
indexType = 'ZCTextIndex'
|
||||
indexInfo[indexName] = indexType
|
||||
if indexInfo:
|
||||
|
|
|
@ -275,6 +275,14 @@ class ToolMixin(AbstractMixin):
|
|||
return value[:maxWidth] + '...'
|
||||
return value
|
||||
|
||||
def truncateText(self, text, width=15):
|
||||
'''Truncates p_text to max p_width chars. If the text is longer than
|
||||
p_width, the truncated part is put in a "acronym" html tag.'''
|
||||
if len(text) <= width: return text
|
||||
else:
|
||||
return '<acronym title="%s">%s</acronym>' % \
|
||||
(text, text[:width] + '...')
|
||||
|
||||
translationMapping = {'portal_path': ''}
|
||||
def translateWithMapping(self, label):
|
||||
'''Translates p_label in the application domain, with a default
|
||||
|
@ -336,15 +344,13 @@ class ToolMixin(AbstractMixin):
|
|||
res[means.id] = means.__dict__
|
||||
return res
|
||||
|
||||
def userMayAdd(self, rootClass):
|
||||
'''For deciding if a user may add a new instance of a class, beyond the
|
||||
permission-based check, we can have a custom method that proposes an
|
||||
additional condition. This method checks if there is such a custom
|
||||
method (must be named "mayCreate") define on p_rootClass, and calls
|
||||
it if yes. If no, it returns True.'''
|
||||
def userMaySearch(self, rootClass):
|
||||
'''This method checks if the currently logged user can trigger searches
|
||||
on a given p_rootClass. This is done by calling method "maySearch"
|
||||
on the class. If no such method exists, we return True.'''
|
||||
pythonClass = self.getAppyClass(rootClass)
|
||||
if 'mayCreate' in pythonClass.__dict__:
|
||||
return pythonClass.mayCreate(self.appy())
|
||||
if 'maySearch' in pythonClass.__dict__:
|
||||
return pythonClass.maySearch(self.appy())
|
||||
return True
|
||||
|
||||
def onImportObjects(self):
|
||||
|
@ -369,6 +375,12 @@ class ToolMixin(AbstractMixin):
|
|||
else:
|
||||
return False
|
||||
|
||||
def isSortable(self, name, className, usage):
|
||||
'''Is field p_name defined on p_metaType sortable for p_usage purposes
|
||||
(p_usage can be "ref" or "search")?'''
|
||||
appyType = self.getAppyType(name, className=className)
|
||||
return appyType.isSortable(usage=usage)
|
||||
|
||||
def _searchValueIsEmpty(self, key):
|
||||
'''Returns True if request value in key p_key can be considered as
|
||||
empty.'''
|
||||
|
|
|
@ -642,11 +642,6 @@ class AbstractMixin:
|
|||
reverse = rq.get('reverse') == 'True'
|
||||
self.appy().sort(fieldName, sortKey=sortKey, reverse=reverse)
|
||||
|
||||
def isRefSortable(self, fieldName):
|
||||
'''Can p_fieldName, which is a field defined on self, be used as a sort
|
||||
key in a reference field?'''
|
||||
return self.getAppyType(fieldName).isSortable(usage='ref')
|
||||
|
||||
def getWorkflow(self, appy=True):
|
||||
'''Returns the Appy workflow instance that is relevant for this
|
||||
object. If p_appy is False, it returns the DC workflow.'''
|
||||
|
@ -969,6 +964,7 @@ class AbstractMixin:
|
|||
if created and rq.get('nav', None):
|
||||
# Get the initiator
|
||||
splitted = rq['nav'].split('.')
|
||||
if splitted[0] == 'search': return # Not an initiator but a search.
|
||||
initiator = self.uid_catalog.searchResults(
|
||||
UID=splitted[1])[0].getObject()
|
||||
fieldName = splitted[2].split(':')[1]
|
||||
|
|
|
@ -54,18 +54,18 @@
|
|||
<tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment>
|
||||
|
||||
<th tal:define="fieldName python:'title'; sortable python:True; filterable python:True">
|
||||
<span tal:content="python: tool.translate('ref_name')"/>
|
||||
<span tal:replace="structure python: tool.truncateText(tool.translate('ref_name'))"/>
|
||||
<metal:sortAndFilter use-macro="here/skyn/navigate/macros/sortAndFilter"/>
|
||||
</th>
|
||||
|
||||
<tal:comment replace="nothing">Columns corresponding to other fields</tal:comment>
|
||||
<tal:columnHeader repeat="fieldDescr fieldDescrs">
|
||||
<th tal:define="fieldName fieldDescr/name|string:workflow_state;
|
||||
sortable fieldDescr/indexed|nothing;
|
||||
sortable python: tool.isSortable(fieldName, contentType, 'search');
|
||||
filterable fieldDescr/filterable|nothing;">
|
||||
<tal:comment replace="nothing">Display header for a "standard" field</tal:comment>
|
||||
<tal:standardField condition="python: fieldName != 'workflow_state'">
|
||||
<span tal:replace="python: tool.translate(fieldDescr['labelId'])"/>
|
||||
<span tal:replace="structure python: tool.truncateText(tool.translate(fieldDescr['labelId']))"/>
|
||||
</tal:standardField>
|
||||
<tal:comment replace="nothing">Display header for the workflow state</tal:comment>
|
||||
<tal:workflowState condition="python: fieldName == 'workflow_state'">
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
title allows to see all root objects in the database.</tal:comment>
|
||||
<table cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<a tal:condition="python: len(flavours)==1 and rootClasses"
|
||||
<td tal:define="titleIsClickable python: member.has_role('Manager') and rootClasses">
|
||||
<a tal:condition="titleIsClickable"
|
||||
tal:attributes="href python:'%s?type_name=%s&flavourNumber=1' % (queryUrl, ','.join(rootClasses))"
|
||||
tal:content="python: tool.translate(appName)"></a>
|
||||
<span tal:condition="python: len(flavours)>1 or not rootClasses"
|
||||
<span tal:condition="not: titleIsClickable"
|
||||
tal:replace="python: tool.translate(appName)"/>
|
||||
</td>
|
||||
<td align="right">
|
||||
|
@ -36,14 +36,13 @@
|
|||
<dt class="portletAppyItem"><metal:phases use-macro="here/skyn/portlet/macros/phases"/></dt>
|
||||
</tal:publishedObject>
|
||||
|
||||
<tal:comment replace="nothing">TODO: implement a widget for selecting the needed flavour.</tal:comment>
|
||||
|
||||
<tal:comment replace="nothing">Create a section for every root class.</tal:comment>
|
||||
<tal:section repeat="rootClass rootClasses"
|
||||
define="flavourNumber python:1;
|
||||
flavour python: tool.getFlavour('Dummy_%d' % flavourNumber)">
|
||||
<tal:comment replace="nothing">Section title, with action icons</tal:comment>
|
||||
<dt tal:attributes="class python:test((repeat['rootClass'].number()==1) and not contextObj, 'portletAppyItem', 'portletAppyItem portletSep')">
|
||||
<dt tal:condition="python: tool.userMaySearch(rootClass)"
|
||||
tal:attributes="class python:test((repeat['rootClass'].number()==1) and not contextObj, 'portletAppyItem', 'portletAppyItem portletSep')">
|
||||
<table width="100%" cellspacing="0" cellpadding="0" class="no-style-table">
|
||||
<tr>
|
||||
<td>
|
||||
|
@ -53,7 +52,7 @@
|
|||
</td>
|
||||
<td align="right"
|
||||
tal:define="addPermission python: '%s: Add %s' % (appName, rootClass);
|
||||
userMayAdd python: member.has_permission(addPermission, appFolder) and tool.userMayAdd(rootClass);
|
||||
userMayAdd python: member.has_permission(addPermission, appFolder);
|
||||
createMeans python: tool.getCreateMeans(rootClass)">
|
||||
<tal:comment replace="nothing">Create a new object from a web form</tal:comment>
|
||||
<img style="cursor:pointer"
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
ref field according to the field that corresponds to this column.
|
||||
</tal:comment>
|
||||
<metal:sortIcons define-macro="sortIcons"
|
||||
tal:define="ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'SortReference\', {\'sortKey\':\'%s\', \'reverse\':\'**v**\'}' % (startNumber, shownField))" tal:condition="python: canWrite and objs[0].isRefSortable(shownField)">
|
||||
tal:define="ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'SortReference\', {\'sortKey\':\'%s\', \'reverse\':\'**v**\'}' % (startNumber, shownField))" tal:condition="python: canWrite and tool.isSortable(shownField, objs[0].meta_type, 'ref')">
|
||||
<img style="cursor:pointer"
|
||||
tal:attributes="src string:$portal_url/skyn/sortAsc.png;
|
||||
onClick python: ajaxBaseCall.replace('**v**', 'False')"/>
|
||||
|
|
|
@ -46,7 +46,7 @@ class FlavourWrapper(AbstractWrapper):
|
|||
p_attrName.
|
||||
|
||||
"resultColumns"
|
||||
Stores the list of columns that must be show when displaying
|
||||
Stores the list of columns that must be shown when displaying
|
||||
instances of the a given root p_klass.
|
||||
|
||||
"enableAdvancedSearch"
|
||||
|
|
Loading…
Reference in a new issue