Wrong index type for selection strings that are not multivalued.

This commit is contained in:
Gaetan Delannay 2010-09-20 11:33:54 +02:00
parent 7c2b8fed11
commit 9f4db88bdf
9 changed files with 41 additions and 30 deletions

View file

@ -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))

View file

@ -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 = ''

View file

@ -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:

View file

@ -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.'''

View file

@ -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]

View file

@ -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'">

View file

@ -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)&gt;1 or not rootClasses"
<span tal:condition="not: titleIsClickable"
tal:replace="python: tool.translate(appName)"/>
</td>
<td align="right">
@ -35,15 +35,14 @@
</dt>
<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"

View file

@ -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')"/>

View file

@ -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"