Inter-object navigation.

This commit is contained in:
Gaetan Delannay 2009-11-17 10:05:19 +01:00
parent 7cdc3c1ed6
commit d9484b104e
10 changed files with 247 additions and 48 deletions

View file

@ -124,6 +124,7 @@ class Generator(AbstractGenerator):
msg('goto_previous', '', msg.GOTO_PREVIOUS), msg('goto_previous', '', msg.GOTO_PREVIOUS),
msg('goto_next', '', msg.GOTO_NEXT), msg('goto_next', '', msg.GOTO_NEXT),
msg('goto_last', '', msg.GOTO_LAST), msg('goto_last', '', msg.GOTO_LAST),
msg('goto_source', '', msg.GOTO_SOURCE),
] ]
# Create basic files (config.py, Install.py, etc) # Create basic files (config.py, Install.py, etc)
self.generateTool() self.generateTool()

View file

@ -98,9 +98,15 @@ class ToolMixin(AbstractMixin):
def showPortlet(self): def showPortlet(self):
return not self.portal_membership.isAnonymousUser() return not self.portal_membership.isAnonymousUser()
def getObject(self, uid, appy=False):
'''Allows to retrieve an object from its p_uid.'''
res = self.uid_catalog(UID=uid)
if res: return res[0].getObject()
return None
_sortFields = {'title': 'sortable_title'} _sortFields = {'title': 'sortable_title'}
def executeQuery(self, contentType, flavourNumber=1, searchName=None, def executeQuery(self, contentType, flavourNumber=1, searchName=None,
startNumber=0, search=None): startNumber=0, search=None, remember=False):
'''Executes a query on a given p_contentType (or several, separated '''Executes a query on a given p_contentType (or several, separated
with commas) in Plone's portal_catalog. Portal types are from the with commas) in Plone's portal_catalog. Portal types are from the
flavour numbered p_flavourNumber. If p_searchName is specified, it flavour numbered p_flavourNumber. If p_searchName is specified, it
@ -147,6 +153,21 @@ class ToolMixin(AbstractMixin):
brains = self.portal_catalog.searchResults(**params) brains = self.portal_catalog.searchResults(**params)
res = SomeObjects(brains, self.getNumberOfResultsPerPage(), startNumber) res = SomeObjects(brains, self.getNumberOfResultsPerPage(), startNumber)
res.brainsToObjects() 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
# to navigate within elements without re-triggering the query every
# time a page for an element is consulted.
if remember:
if not searchName:
# It is the global search for all objects pf p_contentType
searchName = contentType
s = self.REQUEST.SESSION
uids = {}
i = -1
for obj in res.objects:
i += 1
uids[startNumber+i] = obj.UID()
s['search_%s_%s' % (flavourNumber, searchName)] = uids
return res.__dict__ return res.__dict__
def getResultColumnsNames(self, contentType): def getResultColumnsNames(self, contentType):
@ -373,12 +394,122 @@ class ToolMixin(AbstractMixin):
if cookieValue: return cookieValue.value if cookieValue: return cookieValue.value
return default return default
def getQueryUrl(self, contentType, flavourNumber, searchName): def getQueryUrl(self, contentType, flavourNumber, searchName, ajax=True,
startNumber=None):
'''This method creates the URL that allows to perform an ajax GET '''This method creates the URL that allows to perform an ajax GET
request for getting queried objects from a search named p_searchName request for getting queried objects from a search named p_searchName
on p_contentType from flavour numbered p_flavourNumber.''' on p_contentType from flavour numbered p_flavourNumber. If p_ajax
return self.getAppFolder().absolute_url() + '/skyn/ajax?objectUid=%s' \ is False, it returns the non-ajax URL.'''
'&page=macros&macro=queryResult&contentType=%s&flavourNumber=%s' \ baseUrl = self.getAppFolder().absolute_url() + '/skyn'
'&searchName=%s&startNumber=' % (self.UID(), contentType, baseParams = 'type_name=%s&flavourNumber=%s'%(contentType,flavourNumber)
flavourNumber, searchName) # Manage start number
rq = self.REQUEST
if startNumber != None:
baseParams += '&startNumber=%s' % startNumber
elif rq.has_key('startNumber'):
baseParams += '&startNumber=%s' % rq['startNumber']
# Manage search name
if searchName or ajax: baseParams += '&search=%s' % searchName
if ajax:
return '%s/ajax?objectUid=%s&page=macros&macro=queryResult&%s' % \
(baseUrl, self.UID(), baseParams)
else:
return '%s/query?%s' % (baseUrl, baseParams)
def computeStartNumberFrom(self, currentNumber, totalNumber, batchSize):
'''Returns the number (start at 0) of the first element in a list
containing p_currentNumber (starts at 0) whose total number is
p_totalNumber and whose batch size is p_batchSize.'''
startNumber = 0
res = startNumber
while (startNumber < totalNumber):
if (currentNumber < startNumber + batchSize):
return startNumber
else:
startNumber += batchSize
return startNumber
def getNavigationInfo(self):
'''Extracts navigation information from request/nav and returns a dict
with the info that a page can use for displaying object
navigation.'''
res = {}
t,d1,d2,currentNumber,totalNumber = self.REQUEST.get('nav').split('.')
res['currentNumber'] = int(currentNumber)
res['totalNumber'] = int(totalNumber)
newNav = '%s.%s.%s.%%d.%s' % (t, d1, d2, totalNumber)
# Among, first, previous, next and last, which one do I need?
previousNeeded = False # Previous ?
previousIndex = res['currentNumber'] - 2
if (previousIndex > -1) and (res['totalNumber'] > previousIndex):
previousNeeded = True
nextNeeded = False # Next ?
nextIndex = res['currentNumber']
if nextIndex < res['totalNumber']: nextNeeded = True
firstNeeded = False # First ?
firstIndex = 0
if previousIndex > 0: firstNeeded = True
lastNeeded = False # Last ?
lastIndex = res['totalNumber'] - 1
if (nextIndex < lastIndex): lastNeeded = True
# Get the list of available UIDs surrounding the current object
if t == 'ref': # Manage navigation from a reference
fieldName = d2
masterObj = self.getObject(d1)
batchSize = masterObj.getAppyType(fieldName)['maxPerPage']
uids = getattr(masterObj, '_appy_%s' % fieldName)
# In the case of a reference, we retrieve ALL surrounding objects.
# Display the reference widget at the page where the current object
# lies.
startNumberKey = '%s%s_startNumber' % (masterObj.UID(), fieldName)
startNumber = self.computeStartNumberFrom(res['currentNumber']-1,
res['totalNumber'], batchSize)
res['sourceUrl'] = '%s?%s=%s' % (masterObj.getUrl(),
startNumberKey, startNumber)
else: # Manage navigation from a search
contentType, flavourNumber = d1.split(':')
flavourNumber = int(flavourNumber)
searchName = keySuffix = d2
batchSize = self.getNumberOfResultsPerPage()
if not searchName: keySuffix = contentType
s = self.REQUEST.SESSION
searchKey = 'search_%s_%s' % (flavourNumber, keySuffix)
if s.has_key(searchKey): uids = s[searchKey]
else: uids = {}
# In the case of a search, we retrieve only a part of all
# surrounding objects, those that are stored in the session.
if (previousNeeded and not uids.has_key(previousIndex)) or \
(nextNeeded and not uids.has_key(nextIndex)):
# I do not have this UID in session. I will need to
# retrigger the query by querying all objects surrounding
# this one.
newStartNumber = (res['currentNumber']-1) - (batchSize / 2)
if newStartNumber < 0: newStartNumber = 0
self.executeQuery(contentType, flavourNumber,
searchName=searchName, startNumber=newStartNumber,
remember=True)
uids = s[searchKey]
# For the moment, for first and last, we get them only if we have
# them in session.
if not uids.has_key(0): firstNeeded = False
if not uids.has_key(lastIndex): lastNeeded = False
# Compute URL of source object
startNumber = self.computeStartNumberFrom(res['currentNumber']-1,
res['totalNumber'], batchSize)
res['sourceUrl'] = self.getQueryUrl(contentType, flavourNumber,
searchName, ajax=False, startNumber=startNumber)
# Compute URLs
for urlType in ('previous', 'next', 'first', 'last'):
exec 'needIt = %sNeeded' % urlType
urlKey = '%sUrl' % urlType
res[urlKey] = None
if needIt:
exec 'index = %sIndex' % urlType
brain = self.uid_catalog(UID=uids[index])
if brain:
baseUrl = brain[0].getObject().getUrl()
navUrl = baseUrl + '/?nav=' + newNav % (index + 1)
res['%sUrl' % urlType] = navUrl
return res
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -1079,11 +1079,15 @@ class AbstractMixin:
'''This method returns various URLs about this object.''' '''This method returns various URLs about this object.'''
baseUrl = self.absolute_url() baseUrl = self.absolute_url()
params = '' params = ''
rq = self.REQUEST
for k, v in kwargs.iteritems(): params += '&%s=%s' % (k, v) for k, v in kwargs.iteritems(): params += '&%s=%s' % (k, v)
params = params[1:] params = params[1:]
if t == 'showRef': if t == 'showRef':
chunk = '/skyn/ajax?objectUid=%s&page=ref&' \ chunk = '/skyn/ajax?objectUid=%s&page=ref&' \
'macro=showReferenceContent&' % self.UID() 'macro=showReferenceContent&' % self.UID()
startKey = '%s%s_startNumber' % (self.UID(), kwargs['fieldName'])
if rq.has_key(startKey) and not kwargs.has_key(startKey):
params += '&%s=%s' % (startKey, rq[startKey])
return baseUrl + chunk + params return baseUrl + chunk + params
else: # We consider t=='view' else: # We consider t=='view'
return baseUrl + '/skyn/view' + params return baseUrl + '/skyn/view' + params

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View file

@ -475,7 +475,7 @@
<div metal:define-macro="showPageHeader" <div metal:define-macro="showPageHeader"
tal:define="appyPages python: contextObj.getAppyPages(phase); tal:define="appyPages python: contextObj.getAppyPages(phase);
showCommonInfo python: not isEdit" showCommonInfo python: not isEdit"
tal:condition="python: not contextObj.portal_factory.isTemporary(contextObj)"> tal:condition="not: contextObj/isTemporary">
<tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment> <tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment>
<table width="100%" tal:condition="showCommonInfo" class="appyCommonInfo"> <table width="100%" tal:condition="showCommonInfo" class="appyCommonInfo">
@ -499,7 +499,7 @@
</td> </td>
</tr> </tr>
<tr tal:define="descrLabel python: contextObj.translate('%s_edit_descr' % contextObj.portal_type)" <tr tal:define="descrLabel python: contextObj.translate('%s_edit_descr' % contextObj.portal_type)"
tal:condition="descrLabel" > tal:condition="descrLabel/strip" >
<tal:comment replace="nothing">Content type description</tal:comment> <tal:comment replace="nothing">Content type description</tal:comment>
<td colspan="2" class="discreet" tal:content="descrLabel"/> <td colspan="2" class="discreet" tal:content="descrLabel"/>
</tr> </tr>
@ -526,6 +526,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<metal:nav use-macro="here/skyn/macros/macros/objectNavigate"/>
<tal:comment replace="nothing">Tabs</tal:comment> <tal:comment replace="nothing">Tabs</tal:comment>
<ul class="contentViews appyTabs" tal:condition="python: len(appyPages)&gt;1"> <ul class="contentViews appyTabs" tal:condition="python: len(appyPages)&gt;1">
@ -585,26 +586,41 @@
</div> </div>
<metal:queryResults define-macro="queryResult" <metal:queryResults define-macro="queryResult"
tal:define="tool python: contextObj; tal:define="tool python: contextObj;
contentType request/contentType; contentType request/type_name;
flavourNumber python: int(request['flavourNumber']); flavourNumber python: int(request['flavourNumber']);
startNumber python:test(request['startNumber']=='', '0', request['startNumber']); startNumber request/startNumber|python:'0';
startNumber python: int(startNumber); startNumber python: int(startNumber);
searchName request/searchName; searchName request/search;
severalTypes python: contentType and (contentType.find(',') != -1); searchLabel python: '%s_search_%s' % (contentType, searchName);
queryResult python: tool.executeQuery(contentType, flavourNumber, searchName, startNumber); searchDescr python: '%s_descr' % searchLabel;
objs queryResult/objects; severalTypes python: contentType and (contentType.find(',') != -1);
totalNumber queryResult/totalNumber; queryResult python: tool.executeQuery(contentType, flavourNumber, searchName, startNumber, remember=True);
batchSize queryResult/batchSize; objs queryResult/objects;
ajaxHookId python:'queryResult'; totalNumber queryResult/totalNumber;
baseUrl python: tool.getQueryUrl(contentType, flavourNumber, searchName)"> batchSize queryResult/batchSize;
ajaxHookId python:'queryResult';
baseUrl python: tool.getQueryUrl(contentType, flavourNumber, searchName, startNumber='**v**')">
<tal:result condition="objs"> <tal:result condition="objs">
<tal:comment replace="nothing">Appy (top) navigation</tal:comment> <fieldset>
<metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/> <legend>
<span tal:replace="structure python: test(searchName, tool.translate(searchLabel), test(severalTypes, tool.translate(tool.getAppName()), tool.translate('%s_plural' % contentType)))"/>
(<span tal:replace="totalNumber"/>)
</legend>
<table tal:define="fieldDescrs python: tool.getResultColumns(objs[0], contentType)" <table cellpadding="0" cellspacing="0" width="100%"><tr>
<td><span class="discreet" tal:define="descr python: tool.translate(searchDescr)"
tal:condition="python: searchName and descr" tal:content="descr"></span><br/><br/>
</td>
<td align="right">
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
<metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/>
</td>
</tr></table>
<table tal:define="fieldDescrs python: tool.getResultColumns(objs[0], contentType)"
class="vertical listing" width="100%" cellpadding="0" cellspacing="0"> class="vertical listing" width="100%" cellpadding="0" cellspacing="0">
<tal:comment replace="nothing">Every item in fieldDescr is a FieldDescr instance, <tal:comment replace="nothing">Every item in fieldDescr is a FieldDescr instance,
excepted for workflow state (which is not a field): in this case it is simply the excepted for workflow state (which is not a field): in this case it is simply the
@ -662,7 +678,9 @@
<tr tal:repeat="obj objs" id="query_row"> <tr tal:repeat="obj objs" id="query_row">
<tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment> <tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment>
<td id="field_title"><a tal:content="obj/Title" tal:attributes="href obj/getUrl"></a></td> <td id="field_title"><a
tal:define="navInfo python:'nav=search.%s:%d.%s.%d.%d' % (contentType, flavourNumber, searchName, repeat['obj'].number()+startNumber, totalNumber);"
tal:content="obj/Title" tal:attributes="href python: obj.getUrl() + '/?' + navInfo"></a></td>
<tal:comment replace="nothing">Columns corresponding to other fields</tal:comment> <tal:comment replace="nothing">Columns corresponding to other fields</tal:comment>
<tal:otherFields repeat="fieldDescr fieldDescrs"> <tal:otherFields repeat="fieldDescr fieldDescrs">
@ -709,10 +727,11 @@
</table> </table>
</td> </td>
</tr> </tr>
</table> </table>
<tal:comment replace="nothing">Appy (bottom) navigation</tal:comment> <tal:comment replace="nothing">Appy (bottom) navigation</tal:comment>
<metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/> <metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/>
</fieldset>
</tal:result> </tal:result>
<span tal:condition="not: objs" <span tal:condition="not: objs"
@ -932,13 +951,13 @@
<td><img style="cursor:pointer" tal:condition="python: (startNumber != 0) and (startNumber != batchSize)" <td><img style="cursor:pointer" tal:condition="python: (startNumber != 0) and (startNumber != batchSize)"
tal:attributes="src string: $portal_url/skyn/arrowLeftDouble.png; tal:attributes="src string: $portal_url/skyn/arrowLeftDouble.png;
title python: tool.translate('goto_first'); title python: tool.translate('goto_first');
onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl+'0')"/></td> onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl.replace('**v**', '0'))"/></td>
<tal:comment replace="nothing">Go to the previous page</tal:comment> <tal:comment replace="nothing">Go to the previous page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: startNumber != 0" <td><img style="cursor:pointer" tal:condition="python: startNumber != 0"
tal:define="sNumber python: startNumber - batchSize" tal:define="sNumber python: startNumber - batchSize"
tal:attributes="src string: $portal_url/skyn/arrowLeftSimple.png; tal:attributes="src string: $portal_url/skyn/arrowLeftSimple.png;
title python: tool.translate('goto_previous'); title python: tool.translate('goto_previous');
onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl+str(sNumber))"/></td> onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl.replace('**v**', str(sNumber)))"/></td>
<tal:comment replace="nothing">Explain which elements are currently shown</tal:comment> <tal:comment replace="nothing">Explain which elements are currently shown</tal:comment>
<td class="discreet" valign="middle">&nbsp; <td class="discreet" valign="middle">&nbsp;
<span tal:replace="python: startNumber+1"/> <span tal:replace="python: startNumber+1"/>
@ -946,13 +965,12 @@
<span tal:replace="python: startNumber+len(objs)"/>&nbsp;<b>//</b> <span tal:replace="python: startNumber+len(objs)"/>&nbsp;<b>//</b>
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp; <span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</td> </td>
<tal:comment replace="nothing">Go to the next page</tal:comment> <tal:comment replace="nothing">Go to the next page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: sNumber &lt; totalNumber" <td><img style="cursor:pointer" tal:condition="python: sNumber &lt; totalNumber"
tal:define="sNumber python: startNumber + batchSize" tal:define="sNumber python: startNumber + batchSize"
tal:attributes="src string: $portal_url/skyn/arrowRightSimple.png; tal:attributes="src string: $portal_url/skyn/arrowRightSimple.png;
title python: tool.translate('goto_next'); title python: tool.translate('goto_next');
onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl+str(sNumber))"/></td> onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl.replace('**v**', str(sNumber)))"/></td>
<tal:comment replace="nothing">Go to the last page</tal:comment> <tal:comment replace="nothing">Go to the last page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: (startNumber != sNumber) and (startNumber != sNumber-batchSize)" <td><img style="cursor:pointer" tal:condition="python: (startNumber != sNumber) and (startNumber != sNumber-batchSize)"
tal:define="lastPageIsIncomplete python: totalNumber % batchSize; tal:define="lastPageIsIncomplete python: totalNumber % batchSize;
@ -961,7 +979,51 @@
sNumber python: (nbOfCountedPages*batchSize)" sNumber python: (nbOfCountedPages*batchSize)"
tal:attributes="src string: $portal_url/skyn/arrowRightDouble.png; tal:attributes="src string: $portal_url/skyn/arrowRightDouble.png;
title python: tool.translate('goto_last'); title python: tool.translate('goto_last');
onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl+str(sNumber))"/></td> onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, baseUrl.replace('**v**', str(sNumber)))"/></td>
</tr>
</table>
</div>
<div metal:define-macro="objectNavigate" tal:condition="request/nav|nothing" align="right">
<tal:comment replace="nothing">
Buttons for going to next/previous elements if this one is among bunch of referenced or searched objects.
currentNumber starts with 1.
</tal:comment>
<table cellpadding="0" cellspacing="0"
tal:define="navInfo tool/getNavigationInfo;
currentNumber navInfo/currentNumber;
totalNumber navInfo/totalNumber;
firstUrl navInfo/firstUrl;
previousUrl navInfo/previousUrl;
nextUrl navInfo/nextUrl;
lastUrl navInfo/lastUrl;
sourceUrl navInfo/sourceUrl">
<tr>
<tal:comment replace="nothing">Go to the source URL (search or referred object)</tal:comment>
<td><a tal:condition="sourceUrl" tal:attributes="href sourceUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/gotoSource.png;
title python: tool.translate('goto_source')"/></a></td>
<tal:comment replace="nothing">Go to the first page</tal:comment>
<td><a tal:condition="firstUrl" tal:attributes="href firstUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowLeftDouble.png;
title python: tool.translate('goto_first')"/></a></td>
<tal:comment replace="nothing">Go to the previous page</tal:comment>
<td><a tal:condition="previousUrl" tal:attributes="href previousUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowLeftSimple.png;
title python: tool.translate('goto_previous')"/></a></td>
<tal:comment replace="nothing">Explain which element is currently shown</tal:comment>
<td class="discreet" valign="middle">&nbsp;
<span tal:replace="python: currentNumber"/>&nbsp;<b>//</b>
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</td>
<tal:comment replace="nothing">Go to the next page</tal:comment>
<td><a tal:condition="python: nextUrl" tal:attributes="href nextUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowRightSimple.png;
title python: tool.translate('goto_next')"/></a></td>
<tal:comment replace="nothing">Go to the last page</tal:comment>
<td><a tal:condition="lastUrl" tal:attributes="href lastUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowRightDouble.png;
title python: tool.translate('goto_last')"/></a></td>
</tr> </tr>
</table> </table>
</div> </div>

View file

@ -17,10 +17,7 @@
tool python: portal.get('portal_%s' % appName.lower()); tool python: portal.get('portal_%s' % appName.lower());
contentType python:context.REQUEST.get('type_name'); contentType python:context.REQUEST.get('type_name');
flavourNumber python:int(context.REQUEST.get('flavourNumber')); flavourNumber python:int(context.REQUEST.get('flavourNumber'));
searchName python:context.REQUEST.get('search', ''); searchName python:context.REQUEST.get('search', '')">
searchLabel python: '%s_search_%s' % (contentType, searchName);
searchDescr python: '%s_descr' % searchLabel;
severalTypes python: contentType and (contentType.find(',') != -1)">
<div metal:use-macro="here/skyn/macros/macros/pagePrologue"/> <div metal:use-macro="here/skyn/macros/macros/pagePrologue"/>
<script language="javascript"> <script language="javascript">
@ -143,11 +140,6 @@
--> -->
</script> </script>
<tal:comment replace="nothing">Query title and description</tal:comment>
<h1 tal:content="structure python: test(searchName, tool.translate(searchLabel), test(severalTypes, tool.translate(appName), tool.translate('%s_plural' % contentType)))"></h1>
<div class="discreet" tal:condition="searchName"
tal:content="structure python: tool.translate(searchDescr)+'<br/><br/>'"></div>
<tal:comment replace="nothing">Query result</tal:comment> <tal:comment replace="nothing">Query result</tal:comment>
<div id="queryResult"></div> <div id="queryResult"></div>

View file

@ -4,9 +4,12 @@
<metal:objectTitle define-macro="objectTitle"> <metal:objectTitle define-macro="objectTitle">
<tal:comment replace="nothing">Displays the title of a referenced object, with a link on <tal:comment replace="nothing">Displays the title of a referenced object, with a link on
it to reach the consult view for this object. If we are on a back reference, the link it to reach the consult view for this object. If we are on a back reference, the link
allows to reach the correct page where the forward reference is defined.</tal:comment> allows to reach the correct page where the forward reference is defined. If we are
on a forward reference, the "nav" parameter is added to the URL for allowing to navigate
from one object to the next/previous on skyn/view.</tal:comment>
<a tal:define="viewUrl obj/getUrl; <a tal:define="viewUrl obj/getUrl;
fullUrl python: test(isBack, viewUrl + '/?pageName=%s&phase=%s' % (appyType['page'], appyType['phase']), viewUrl)" navInfo python:'nav=ref.%s.%s.%d.%d' % (contextObj.UID(), fieldName, repeat['obj'].number()+startNumber, totalNumber);
fullUrl python: test(isBack, viewUrl + '/?pageName=%s&phase=%s' % (appyType['page'], appyType['phase']), viewUrl + '/?' + navInfo)"
tal:attributes="href fullUrl" tal:content="obj/Title"></a> tal:attributes="href fullUrl" tal:content="obj/Title"></a>
</metal:objectTitle> </metal:objectTitle>
@ -72,7 +75,7 @@
- descrId (string) the i18n id of the reference field description - descrId (string) the i18n id of the reference field description
</tal:comment> </tal:comment>
<div metal:define-macro="showReference" <div metal:define-macro="showReference"
tal:define="ajaxHookId python: contextObj.UID()+fieldName; tal:define="ajaxHookId python: contextObj.UID() + fieldName;
ajaxUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId})" ajaxUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId})"
tal:attributes="id ajaxHookId"> tal:attributes="id ajaxHookId">
<script language="javascript" <script language="javascript"
@ -108,7 +111,7 @@
atMostOneRef python: (multiplicity[1] == 1) and (len(objs)&lt;=1); atMostOneRef python: (multiplicity[1] == 1) and (len(objs)&lt;=1);
label python: tool.translate(labelId); label python: tool.translate(labelId);
description python: tool.translate(descrId); description python: tool.translate(descrId);
baseUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId}) + '&%s_startNumber=' % ajaxHookId"> baseUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId, '%s_startNumber' % ajaxHookId: '**v**'})">
<tal:comment replace="nothing">This macro displays the Reference widget on a "consult" page. <tal:comment replace="nothing">This macro displays the Reference widget on a "consult" page.
@ -130,7 +133,7 @@
<tal:comment replace="nothing">If there is an object...</tal:comment> <tal:comment replace="nothing">If there is an object...</tal:comment>
<tal:objectIsPresent condition="python: len(objs) == 1"> <tal:objectIsPresent condition="python: len(objs) == 1">
<tal:obj define="obj python:objs[0]"> <tal:obj repeat="obj objs">
<td><metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle" /></td> <td><metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle" /></td>
<td tal:condition="not: isBack"> <td tal:condition="not: isBack">
<metal:showObjectActions use-macro="here/skyn/ref/macros/objectActions" /> <metal:showObjectActions use-macro="here/skyn/ref/macros/objectActions" />
@ -145,6 +148,7 @@
<fieldset tal:attributes="class python:test(innerRef, 'innerAppyFieldset', '')"> <fieldset tal:attributes="class python:test(innerRef, 'innerAppyFieldset', '')">
<legend tal:condition="python: not innerRef or showPlusIcon"> <legend tal:condition="python: not innerRef or showPlusIcon">
<span tal:condition="not: innerRef" tal:content="label"/> <span tal:condition="not: innerRef" tal:content="label"/>
(<span tal:replace="totalNumber"/>)
<metal:plusIcon use-macro="here/skyn/ref/macros/plusIcon"/> <metal:plusIcon use-macro="here/skyn/ref/macros/plusIcon"/>
</legend> </legend>

View file

@ -113,7 +113,7 @@
background-color: &dtml-evenRowBackgroundColor;; background-color: &dtml-evenRowBackgroundColor;;
border-style: solid; border-style: solid;
border-width: 2px; border-width: 2px;
margin-bottom: 1em; margin-bottom: 0.5em;
} }
.appyWorkflow { .appyWorkflow {

View file

@ -9,4 +9,8 @@ class ToolWrapper:
if initiatorUid: if initiatorUid:
res = self.o.uid_catalog(UID=initiatorUid)[0].getObject().appy() res = self.o.uid_catalog(UID=initiatorUid)[0].getObject().appy()
return res return res
def getObject(self, uid):
'''Allow to retrieve an object from its unique identifier p_uid.'''
return self.o.getObject(uid, appy=True)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -85,6 +85,7 @@ class PoMessage:
GOTO_PREVIOUS = 'Go to previous' GOTO_PREVIOUS = 'Go to previous'
GOTO_NEXT = 'Go to next' GOTO_NEXT = 'Go to next'
GOTO_LAST = 'Go to end' GOTO_LAST = 'Go to end'
GOTO_SOURCE = 'Go back'
def __init__(self, id, msg, default, fuzzy=False, comments=[]): def __init__(self, id, msg, default, fuzzy=False, comments=[]):
self.id = id self.id = id