Some macros and images were improved, enhanced search capabilities.
This commit is contained in:
parent
7435ff1601
commit
253e61612d
|
@ -12,7 +12,8 @@ import appy.gen
|
|||
import appy.gen.descriptors
|
||||
from appy.gen.po import PoMessage
|
||||
from appy.gen import Date, String, State, Transition, Type, Search
|
||||
from appy.gen.utils import GroupDescr, PageDescr, produceNiceMessage
|
||||
from appy.gen.utils import GroupDescr, PageDescr, produceNiceMessage, \
|
||||
sequenceTypes
|
||||
TABS = 4 # Number of blanks in a Python indentation.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -100,6 +101,9 @@ class ArchetypeFieldDescriptor:
|
|||
self.fieldType = 'LinesField'
|
||||
self.widgetType = 'MultiSelectionWidget'
|
||||
self.fieldParams['multiValued'] = True
|
||||
if (type(self.appyType.validator) in sequenceTypes) and \
|
||||
len(self.appyType.validator) <= 5:
|
||||
self.widgetParams['format'] = 'checkbox'
|
||||
else:
|
||||
self.fieldType = 'StringField'
|
||||
self.widgetType = 'SelectionWidget'
|
||||
|
|
|
@ -106,7 +106,8 @@ class ToolMixin(AbstractMixin):
|
|||
|
||||
_sortFields = {'title': 'sortable_title'}
|
||||
def executeQuery(self, contentType, flavourNumber=1, searchName=None,
|
||||
startNumber=0, search=None, remember=False):
|
||||
startNumber=0, search=None, remember=False,
|
||||
brainsOnly=False, maxResults=None):
|
||||
'''Executes a query on a given p_contentType (or several, separated
|
||||
with commas) in Plone's portal_catalog. Portal types are from the
|
||||
flavour numbered p_flavourNumber. If p_searchName is specified, it
|
||||
|
@ -115,7 +116,16 @@ class ToolMixin(AbstractMixin):
|
|||
p_startNumber. If p_search is defined, it corresponds to a custom
|
||||
Search instance (instead of a predefined named search like in
|
||||
p_searchName). If both p_searchName and p_search are given, p_search
|
||||
is ignored.'''
|
||||
is ignored. This method returns a list of objects in the form of the
|
||||
__dict__ attribute of an instance of SomeObjects (see in
|
||||
appy.gen.utils). We return the __dict__ attribute instead of real
|
||||
instance: that way, it can be used in ZPTs without security problems.
|
||||
If p_brainsOnly is True, it returns a list of brains instead (can be
|
||||
useful for some usages like knowing the number of objects without
|
||||
needing to get information about them). If no p_maxResults is
|
||||
specified, the method returns maximum
|
||||
self.getNumberOfResultsPerPage(). p_maxResults is ignored if
|
||||
p_brainsOnly is True.'''
|
||||
# Is there one or several content types ?
|
||||
if contentType.find(',') != -1:
|
||||
# Several content types are specified
|
||||
|
@ -125,7 +135,8 @@ class ToolMixin(AbstractMixin):
|
|||
for pt in portalTypes]
|
||||
else:
|
||||
portalTypes = contentType
|
||||
params = {'portal_type': portalTypes, 'batch': True}
|
||||
params = {'portal_type': portalTypes}
|
||||
if not brainsOnly: params['batch'] = True
|
||||
# Manage additional criteria from a search when relevant
|
||||
if searchName or search:
|
||||
# In this case, contentType must contain a single content type.
|
||||
|
@ -151,7 +162,9 @@ class ToolMixin(AbstractMixin):
|
|||
if self._sortFields.has_key(sb): sb = self._sortFields[sb]
|
||||
params['sort_on'] = sb
|
||||
brains = self.portal_catalog.searchResults(**params)
|
||||
res = SomeObjects(brains, self.getNumberOfResultsPerPage(), startNumber)
|
||||
if brainsOnly: return brains
|
||||
if not maxResults: maxResults = self.getNumberOfResultsPerPage()
|
||||
res = SomeObjects(brains, maxResults, startNumber)
|
||||
res.brainsToObjects()
|
||||
# In some cases (p_remember=True), we need to keep some information
|
||||
# about the query results in the current user's session, allowing him
|
||||
|
|
|
@ -54,9 +54,8 @@ class AbstractMixin:
|
|||
pass
|
||||
# Manage "add" permissions
|
||||
obj._appy_managePermissions()
|
||||
# Re/unindex object
|
||||
if obj._appy_meta_type == 'tool': self.unindexObject()
|
||||
else: obj.reindexObject()
|
||||
# Reindex object
|
||||
obj.reindexObject()
|
||||
return obj
|
||||
|
||||
def delete(self):
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 232 B |
Binary file not shown.
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 232 B |
BIN
gen/plone25/skin/delete.png
Normal file
BIN
gen/plone25/skin/delete.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 239 B |
|
@ -118,8 +118,8 @@
|
|||
<metal:showDate define-macro="showDateField"
|
||||
tal:define="v python: field.getAccessor(contextObj)()">
|
||||
<span tal:condition="showLabel" tal:content="label" class="appyLabel"></span>
|
||||
<span tal:content="python: v.strftime('%d/%m/') + str(v.year())"></span>
|
||||
<span tal:condition="python: appyType['format'] == 0"
|
||||
<span tal:condition="v" tal:content="python: v.strftime('%d/%m/') + str(v.year())"></span>
|
||||
<span tal:condition="python: v and (appyType['format'] == 0)"
|
||||
tal:content="python: v.strftime('%H:%M')"></span>
|
||||
</metal:showDate>
|
||||
|
||||
|
@ -132,7 +132,7 @@
|
|||
<span tal:condition="showLabel" tal:content="label" class="appyLabel"
|
||||
tal:attributes="class python: 'appyLabel ' + contextObj.getCssClasses(appyType, asSlave=False);
|
||||
id python: v"></span>
|
||||
<tal:severalValues condition="severalValues">
|
||||
<tal:severalValues condition="python: v and severalValues">
|
||||
<ul class="appyList">
|
||||
<tal:items repeat="sv v">
|
||||
<tal:select condition="appyType/isSelect">
|
||||
|
@ -146,7 +146,7 @@
|
|||
</tal:items>
|
||||
</ul>
|
||||
</tal:severalValues>
|
||||
<tal:singleValue condition="not: severalValues">
|
||||
<tal:singleValue condition="python: v and not severalValues">
|
||||
<tal:select condition="appyType/isSelect">
|
||||
<span tal:replace="python: tool.translate('%s_%s_list_%s' % (contextObj.meta_type, field.getName(), v))"/>
|
||||
</tal:select>
|
||||
|
@ -617,7 +617,7 @@
|
|||
tal:condition="python: searchName and descr">
|
||||
<span class="discreet" tal:content="descr"></span><br/><br/>
|
||||
</td>
|
||||
<td align="right">
|
||||
<td align="right" width="25%">
|
||||
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
|
||||
<metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/>
|
||||
</td>
|
||||
|
@ -723,8 +723,9 @@
|
|||
<tal:comment replace="nothing">Delete the element</tal:comment>
|
||||
<td class="noPadding">
|
||||
<img tal:condition="python: member.has_permission('Delete objects', obj)"
|
||||
src="delete_icon.gif" title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
|
||||
tal:attributes="onClick python:'javascript:onDeleteObject(\'%s\')' % obj.UID()"/>
|
||||
title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
|
||||
tal:attributes="src string: $portal_url/skyn/delete.png;
|
||||
onClick python:'javascript:onDeleteObject(\'%s\')' % obj.UID()"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -18,17 +18,6 @@
|
|||
referenced object (edit, delete, etc).</tal:comment>
|
||||
<table class="no-style-table" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<tal:comment replace="nothing">Edit the element</tal:comment>
|
||||
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/skyn/edit'"
|
||||
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
||||
<img src="edit.gif" title="label_edit" i18n:domain="plone" i18n:attributes="title" />
|
||||
</a></td>
|
||||
<tal:comment replace="nothing">Delete the element</tal:comment>
|
||||
<td class="noPadding">
|
||||
<img tal:condition="python: member.has_permission('Delete objects', obj)"
|
||||
src="delete_icon.gif" title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
|
||||
tal:attributes="onClick python:'javascript:onDeleteObject(\'%s\')' % obj.UID()"/>
|
||||
</td>
|
||||
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
|
||||
<td class="noPadding" tal:condition="python: (len(objs)>1) and member.has_permission('Modify portal content', obj)">
|
||||
<tal:moveRef define="objectIndex python:contextObj.getAppyRefIndex(fieldName, obj);
|
||||
|
@ -47,6 +36,18 @@
|
|||
style="cursor:pointer"/>
|
||||
</tal:moveRef>
|
||||
</td>
|
||||
<tal:comment replace="nothing">Edit the element</tal:comment>
|
||||
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/skyn/edit'"
|
||||
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
||||
<img src="edit.gif" title="label_edit" i18n:domain="plone" i18n:attributes="title" />
|
||||
</a></td>
|
||||
<tal:comment replace="nothing">Delete the element</tal:comment>
|
||||
<td class="noPadding">
|
||||
<img tal:condition="python: member.has_permission('Delete objects', obj)"
|
||||
title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
|
||||
tal:attributes="src string: $portal_url/skyn/delete.png;
|
||||
onClick python:'javascript:onDeleteObject(\'%s\')' % obj.UID()"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</metal:objectActions>
|
||||
|
|
|
@ -97,6 +97,10 @@ class AbstractWrapper:
|
|||
klass = property(get_klass)
|
||||
def get_url(self): return self.o.absolute_url()+'/skyn/view'
|
||||
url = property(get_url)
|
||||
def get_history(self):
|
||||
key = self.o.workflow_history.keys()[0]
|
||||
return self.o.workflow_history[key]
|
||||
history = property(get_history)
|
||||
|
||||
def link(self, fieldName, obj):
|
||||
'''This method links p_obj to this one through reference field
|
||||
|
@ -245,19 +249,33 @@ class AbstractWrapper:
|
|||
replaced with normal chars.'''
|
||||
return unicodedata.normalize('NFKD', s).encode("ascii","ignore")
|
||||
|
||||
def search(self, klass, sortBy='', **fields):
|
||||
def search(self, klass, sortBy='', maxResults=None, **fields):
|
||||
'''Searches objects of p_klass. p_sortBy must be the name of an indexed
|
||||
field (declared with indexed=True); every param in p_fields must
|
||||
take the name of an indexed field and take a possible value of this
|
||||
field.'''
|
||||
field. You can optionally specify a maximum number of results in
|
||||
p_maxResults.'''
|
||||
# Find the content type corresponding to p_klass
|
||||
flavour = self.flavour
|
||||
contentType = flavour.o.getPortalType(klass)
|
||||
# Create the Search object
|
||||
search = Search('customSearch', sortBy=sortBy, **fields)
|
||||
res = self.tool.o.executeQuery(contentType,flavour.number,search=search)
|
||||
res = self.tool.o.executeQuery(contentType,flavour.number,search=search,
|
||||
maxResults=maxResults)
|
||||
return [o.appy() for o in res['objects']]
|
||||
|
||||
def count(self, klass, **fields):
|
||||
'''Identical to m_search above, but returns the number of objects that
|
||||
match the search instead of returning the objects themselves. Use
|
||||
this method instead of writing len(self.search(...)).'''
|
||||
flavour = self.flavour
|
||||
contentType = flavour.o.getPortalType(klass)
|
||||
search = Search('customSearch', **fields)
|
||||
res = self.tool.o.executeQuery(contentType,flavour.number,search=search,
|
||||
brainsOnly=True)
|
||||
if res: return res._len # It is a LazyMap instance
|
||||
else: return 0
|
||||
|
||||
def reindex(self):
|
||||
'''Asks a direct object reindexing. In most cases you don't have to
|
||||
reindex objects "manually" with this method. When an object is
|
||||
|
|
Loading…
Reference in a new issue