[gen] More work on Refs with popup='true'.
This commit is contained in:
parent
a14bff45a7
commit
0bcd0055a3
|
@ -286,11 +286,8 @@ class Field:
|
|||
|
||||
def isMultiValued(self):
|
||||
'''Does this type definition allow to define multiple values?'''
|
||||
res = False
|
||||
maxOccurs = self.multiplicity[1]
|
||||
if (maxOccurs == None) or (maxOccurs > 1):
|
||||
res = True
|
||||
return res
|
||||
return (maxOccurs == None) or (maxOccurs > 1)
|
||||
|
||||
def isSortable(self, usage):
|
||||
'''Can fields of this type be used for sorting purposes (when sorting
|
||||
|
|
|
@ -1273,7 +1273,7 @@ class Ref(Field):
|
|||
# No object can be selected if the popup has not been opened yet.
|
||||
if 'semantics' not in rq:
|
||||
# In this case, display already linked objects if any.
|
||||
if not obj.isEmpty(self.name): return getattr(obj, self.name)
|
||||
if not obj.isEmpty(self.name): return self.getValue(obj.o)
|
||||
return res
|
||||
uids = rq['selected'].split(',')
|
||||
tool = obj.tool
|
||||
|
|
|
@ -24,16 +24,16 @@ from group import Group
|
|||
# ------------------------------------------------------------------------------
|
||||
class Search:
|
||||
'''Used for specifying a search for a given class.'''
|
||||
def __init__(self, name, group=None, sortBy='', sortOrder='asc', limit=None,
|
||||
default=False, colspan=1, translated=None, show=True,
|
||||
translatedDescr=None, checkboxes=False, checkboxesDefault=True,
|
||||
**fields):
|
||||
def __init__(self, name, group=None, sortBy='', sortOrder='asc',
|
||||
maxPerPage=30, default=False, colspan=1, translated=None,
|
||||
show=True, translatedDescr=None, checkboxes=False,
|
||||
checkboxesDefault=True, **fields):
|
||||
self.name = name
|
||||
# Searches may be visually grouped in the portlet.
|
||||
self.group = Group.get(group)
|
||||
self.sortBy = sortBy
|
||||
self.sortOrder = sortOrder
|
||||
self.limit = limit
|
||||
self.maxPerPage = maxPerPage
|
||||
# If this search is the default one, it will be triggered by clicking
|
||||
# on main link.
|
||||
self.default = default
|
||||
|
@ -188,4 +188,19 @@ class UiSearch:
|
|||
_ = tool.translate
|
||||
self.translated = label and _(label) or ''
|
||||
self.translatedDescr = labelDescr and _(labelDescr) or ''
|
||||
|
||||
def setInitiator(self, initiator, field):
|
||||
'''If the search is defined in an attribute Ref.select, we receive here
|
||||
the p_initiator object and its Ref p_field.'''
|
||||
self.initiator = initiator
|
||||
self.initiatorField = field
|
||||
|
||||
def showCheckboxes(self):
|
||||
'''If checkboxes are enabled for this search (and if an initiator field
|
||||
is there), they must be visible only if the initiator field is
|
||||
multivalued. Indeed, if it is not the case, it has no sense to select
|
||||
multiple objects. But in this case, we still want checkboxes to be in
|
||||
the DOM because they store object UIDs.'''
|
||||
if not self.search.checkboxes: return
|
||||
return not self.initiator or self.initiatorField.isMultiValued()
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -354,14 +354,17 @@ class ToolMixin(BaseMixin):
|
|||
# Use index "Allowed" if noSecurity is False
|
||||
if not noSecurity: params['Allowed'] = self.getAllowedValue()
|
||||
brains = self.getPath("/catalog")(**params)
|
||||
if brainsOnly:
|
||||
# Return brains only.
|
||||
if not maxResults or (maxResults == 'NO_LIMIT'): return brains
|
||||
else: return brains[:maxResults]
|
||||
# Compute maxResults
|
||||
if not maxResults:
|
||||
if refField: maxResults = refField.maxPerPage
|
||||
else: maxResults = self.appy().numberOfResultsPerPage
|
||||
elif maxResults == 'NO_LIMIT': maxResults = None
|
||||
else: maxResults = search.maxPerPage or \
|
||||
self.appy().numberOfResultsPerPage
|
||||
elif maxResults == 'NO_LIMIT':
|
||||
maxResults = None
|
||||
# Return brains only if required.
|
||||
if brainsOnly:
|
||||
if not maxResults: return brains
|
||||
else: return brains[:maxResults]
|
||||
res = gutils.SomeObjects(brains, maxResults, startNumber,
|
||||
noSecurity=noSecurity)
|
||||
res.brainsToObjects()
|
||||
|
@ -725,14 +728,18 @@ class ToolMixin(BaseMixin):
|
|||
def getSearch(self, className, name, ui=False):
|
||||
'''Gets the Search instance (or a UiSearch instance if p_ui is True)
|
||||
corresponding to the search named p_name, on class p_className.'''
|
||||
initiator = None
|
||||
if name == 'customSearch':
|
||||
# It is a custom search whose parameters are in the session.
|
||||
fields = self.REQUEST.SESSION['searchCriteria']
|
||||
res = Search('customSearch', **fields)
|
||||
elif ':' in name:
|
||||
# The search is defined in a Ref field with link=popup
|
||||
refObject, ref = name.split(':')
|
||||
res = getattr(self.getObject(refObject,appy=True).klass,ref).select
|
||||
# The search is defined in a Ref field with link=popup. Get the
|
||||
# search, the initiator object and the Ref field.
|
||||
uid, ref = name.split(':')
|
||||
initiator = self.getObject(uid, appy=True)
|
||||
initiatorField = initiator.getField(ref)
|
||||
res = getattr(initiator.klass, ref).select
|
||||
elif name:
|
||||
appyClass = self.getAppyClass(className)
|
||||
# Search among static searches
|
||||
|
@ -747,7 +754,9 @@ class ToolMixin(BaseMixin):
|
|||
# It is the search for every instance of p_className
|
||||
res = Search('allSearch')
|
||||
# Return a UiSearch if required.
|
||||
if ui: res = UiSearch(res, className, self)
|
||||
if ui:
|
||||
res = UiSearch(res, className, self)
|
||||
if initiator: res.setInitiator(initiator, initiatorField)
|
||||
return res
|
||||
|
||||
def advancedSearchEnabledFor(self, klass):
|
||||
|
|
|
@ -1041,7 +1041,6 @@ function onSelectObjects(nodeId, objectUrl, sortKey, sortOrder,
|
|||
return;
|
||||
}
|
||||
// Close the popup.
|
||||
var parent = window.parent;
|
||||
closePopup('iframePopup');
|
||||
/* Refresh the Ref edit widget to include the linked objects. All those
|
||||
parameters are needed to replay the query in the popup. */
|
||||
|
@ -1051,6 +1050,25 @@ function onSelectObjects(nodeId, objectUrl, sortKey, sortOrder,
|
|||
'filterValue': filterValue});
|
||||
}
|
||||
|
||||
function onSelectObject(tdId, nodeId, objectUrl) {
|
||||
/* In a Ref field with link="popup", a single object has been clicked. If
|
||||
multiple objects can be selected, simply update the corresponding checkbox
|
||||
status. Else, close the popup and return the selected object. p_tdId is
|
||||
the ID of the td that contains the checkbox. */
|
||||
var td = document.getElementById(tdId);
|
||||
// If the td is visible, simply click the checkbox.
|
||||
var checkbox = td.getElementsByTagName('input')[0];
|
||||
if (td.style.display == 'table-cell') { checkbox.click(); }
|
||||
else {
|
||||
/* Close the popup and directly refresh the initiator field with the
|
||||
selected object. */
|
||||
var uids=checkbox.value;
|
||||
closePopup('iframePopup');
|
||||
askField(':'+nodeId, objectUrl, 'edit', null, null, null, null, null,
|
||||
{'selected': uids, 'semantics': 'checked'});
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the focus on the correct element in some page.
|
||||
function initFocus(pageId){
|
||||
var id = pageId + '_title';
|
||||
|
|
|
@ -317,15 +317,18 @@ class ToolWrapper(AbstractWrapper):
|
|||
var2="navInfo='search.%s.%s.%d.%d' % \
|
||||
(className, searchName, startNumber+currentNumber, totalNumber);
|
||||
cssClass=zobj.getCssFor('title')">
|
||||
<x>::zobj.getSupTitle(navInfo)</x>
|
||||
<x var="sup=zobj.getSupTitle(navInfo)" if="sup">::sup</x>
|
||||
<a if="enableLinks" class=":cssClass"
|
||||
var2="linkInPopup=inPopup or (target.target != '_self')"
|
||||
target=":target.target" onclick=":target.openPopup"
|
||||
href=":zobj.getUrl(nav=navInfo, page=zobj.getDefaultViewPage(), \
|
||||
inPopup=linkInPopup)">:zobj.Title()</a><span
|
||||
if="not enableLinks" class=":cssClass">:zobj.Title()</span><span
|
||||
style=":showSubTitles and 'display:inline' or 'display:none'"
|
||||
name="subTitle">::zobj.getSubTitle()</span>
|
||||
inPopup=linkInPopup)">:zobj.Title()</a>
|
||||
<span if="not enableLinks"
|
||||
class=":not checkboxes and cssClass or ('%s clickable' % cssClass)"
|
||||
onclick=":checkboxes and ('onSelectObject(%s,%s,%s)' % (q(cbId), \
|
||||
q(rootHookId), q(uiSearch.initiator.url))) or ''">:obj.title</span>
|
||||
<span style=":showSubTitles and 'display:inline' or 'display:none'"
|
||||
name="subTitle" var="sub=zobj.getSubTitle()" if="sub">::sub</span>
|
||||
|
||||
<!-- Actions -->
|
||||
<table class="noStyle" if="not inPopup and zobj.mayAct()">
|
||||
|
@ -368,7 +371,9 @@ class ToolWrapper(AbstractWrapper):
|
|||
pxQueryResultList = Px('''
|
||||
<x var="showHeaders=showHeaders|True;
|
||||
checkboxes=uiSearch.search.checkboxes;
|
||||
checkboxesId=rootHookId + '_objs'">
|
||||
checkboxesId=rootHookId + '_objs';
|
||||
cbShown=uiSearch.showCheckboxes();
|
||||
cbDisplay=cbShown and 'display:table-cell' or 'display:none'">
|
||||
<table class="list" width="100%">
|
||||
<!-- Headers, with filters and sort arrows -->
|
||||
<tr if="showHeaders">
|
||||
|
@ -380,7 +385,7 @@ class ToolWrapper(AbstractWrapper):
|
|||
<x>::ztool.truncateText(_(field.labelId))</x>
|
||||
<x>:tool.pxSortAndFilter</x><x>:tool.pxShowDetails</x>
|
||||
</th>
|
||||
<th if="checkboxes" class="cbCell">
|
||||
<th if="checkboxes" class="cbCell" style=":cbDisplay">
|
||||
<img src=":url('checkall')" class="clickable"
|
||||
title=":_('check_uncheck')"
|
||||
onclick=":'toggleAllCbs(%s)' % q(checkboxesId)"/>
|
||||
|
@ -391,30 +396,29 @@ class ToolWrapper(AbstractWrapper):
|
|||
<tr if="not zobjects">
|
||||
<td colspan=":len(columns)+1">:_('query_no_result')</td>
|
||||
</tr>
|
||||
<tr for="zobj in zobjects" id="query_row" valign="top"
|
||||
<tr for="zobj in zobjects" valign="top"
|
||||
var2="@currentNumber=currentNumber + 1;
|
||||
obj=zobj.appy(); mayView=zobj.mayView()"
|
||||
obj=zobj.appy(); mayView=zobj.mayView();
|
||||
cbId='%s_%s' % (checkboxesId, currentNumber)"
|
||||
class=":loop.zobj.odd and 'even' or 'odd'">
|
||||
<td for="column in columns"
|
||||
var2="field=column.field" id=":'field_%s' % field.name"
|
||||
width=":column.width"
|
||||
align=":column.align">:tool.pxQueryField</td>
|
||||
<!-- A checkbox if required -->
|
||||
<td if="checkboxes" class="cbCell">
|
||||
<td if="checkboxes" class="cbCell" id=":cbId" style=":cbDisplay">
|
||||
<input type="checkbox" name=":checkboxesId" checked="checked"
|
||||
value=":zobj.id" onclick="toggleCb(this)"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- The button for selecting objects and closing the popup. -->
|
||||
<div if="inPopup" align=":dright">
|
||||
<div if="inPopup and cbShown" align=":dright">
|
||||
<input type="button" class="button"
|
||||
var="label=_('object_link_many');
|
||||
initiator=ztool.getObject(searchName.split(':')[0], \
|
||||
appy=True)"
|
||||
var="label=_('object_link_many')"
|
||||
value=":label"
|
||||
onclick=":'onSelectObjects(%s,%s,%s,%s,%s,%s)' % (q(rootHookId), \
|
||||
q(initiator.url), q(sortKey), q(sortOrder), \
|
||||
q(uiSearch.initiator.url),q(sortKey),q(sortOrder), \
|
||||
q(filterKey), q(filterValue))"
|
||||
style=":'%s; %s' % (url('linkMany', bg=True), \
|
||||
ztool.getButtonWidth(label))"/>
|
||||
|
|
|
@ -949,7 +949,7 @@ class AbstractWrapper(object):
|
|||
contentType = tool.getPortalType(klass)
|
||||
search = Search('customSearch', **fields)
|
||||
res = tool.executeQuery(contentType, search=search, brainsOnly=True,
|
||||
noSecurity=noSecurity)
|
||||
noSecurity=noSecurity, maxResults='NO_LIMIT')
|
||||
if res: return res._len # It is a LazyMap instance
|
||||
else: return 0
|
||||
|
||||
|
|
Loading…
Reference in a new issue