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