[gen] For Strings with validator=String.URL, an HTML link is rendered in view layouts; added a 'real' 'state' field to any Appy class, allowing to use it in search screens for example; added 2 hook methods: getIcons and getSubTitles, allowing to add, in lists of objects (Refs or queries), icons besides the title and anything below it; optimized query.pt: for every new query, 1 server request is done (previously, one standard request + one ajax request were done); removed columns 'actions' (Refs, query): action icons are not included in the column containing the title (we avoid having empty columns whhen no action is available).

This commit is contained in:
Gaetan Delannay 2012-10-31 21:17:31 +01:00
parent 7240561f7f
commit 4a69a3beb2
20 changed files with 142 additions and 131 deletions

View file

@ -1157,6 +1157,7 @@ class String(Type):
# field of format CAPTCHA by page, because the captcha challenge is # field of format CAPTCHA by page, because the captcha challenge is
# stored in the session at some global key. # stored in the session at some global key.
self.format = format self.format = format
self.isUrl = validator == String.URL
# When format is XHTML, the list of styles that the user will be able to # When format is XHTML, the list of styles that the user will be able to
# select in the styles dropdown is defined hereafter. # select in the styles dropdown is defined hereafter.
self.styles = styles self.styles = styles
@ -1225,6 +1226,8 @@ class String(Type):
return {'view': 'l-f', 'edit': 'lrv-f'} return {'view': 'l-f', 'edit': 'lrv-f'}
def getValue(self, obj): def getValue(self, obj):
# Cheat if this field represents p_obj's state
if self.name == 'state': return obj.State()
value = Type.getValue(self, obj) value = Type.getValue(self, obj)
if not value: if not value:
if self.isMultiValued(): return emptyTuple if self.isMultiValued(): return emptyTuple

View file

@ -404,7 +404,6 @@ class ZopeGenerator(Generator):
msg('modified_field', '', msg.MODIFIED_FIELD), msg('modified_field', '', msg.MODIFIED_FIELD),
msg('previous_value', '', msg.PREVIOUS_VALUE), msg('previous_value', '', msg.PREVIOUS_VALUE),
msg('phase', '', msg.PHASE), msg('phase', '', msg.PHASE),
msg('root_type', '', msg.ROOT_TYPE),
msg('workflow_comment', '', msg.WORKFLOW_COMMENT), msg('workflow_comment', '', msg.WORKFLOW_COMMENT),
msg('choose_a_value', '', msg.CHOOSE_A_VALUE), msg('choose_a_value', '', msg.CHOOSE_A_VALUE),
msg('choose_a_doc', '', msg.CHOOSE_A_DOC), msg('choose_a_doc', '', msg.CHOOSE_A_DOC),
@ -412,7 +411,6 @@ class ZopeGenerator(Generator):
msg('max_ref_violated', '', msg.MAX_REF_VIOLATED), msg('max_ref_violated', '', msg.MAX_REF_VIOLATED),
msg('no_ref', '', msg.REF_NO), msg('no_ref', '', msg.REF_NO),
msg('add_ref', '', msg.REF_ADD), msg('add_ref', '', msg.REF_ADD),
msg('ref_actions', '', msg.REF_ACTIONS),
msg('action_ok', '', msg.ACTION_OK), msg('action_ok', '', msg.ACTION_OK),
msg('action_ko', '', msg.ACTION_KO), msg('action_ko', '', msg.ACTION_KO),
msg('move_up', '', msg.REF_MOVE_UP), msg('move_up', '', msg.REF_MOVE_UP),

View file

@ -545,6 +545,11 @@ class ToolMixin(BaseMixin):
appyType = self.getAppyType(name, className=className) appyType = self.getAppyType(name, className=className)
if appyType: return appyType.isSortable(usage=usage) if appyType: return appyType.isSortable(usage=usage)
def subTitleIsUsed(self, className):
'''Does class named p_className define a method "getSubTitle"?'''
klass = self.getAppyClass(className)
return hasattr(klass, 'getSubTitle')
def _searchValueIsEmpty(self, key): def _searchValueIsEmpty(self, key):
'''Returns True if request value in key p_key can be considered as '''Returns True if request value in key p_key can be considered as
empty.''' empty.'''

View file

@ -687,12 +687,6 @@ class BaseMixin:
'''Gets the Appy types named p_fieldNames.''' '''Gets the Appy types named p_fieldNames.'''
res = [] res = []
for name in fieldNames: for name in fieldNames:
if name == 'state':
# We do not return a appyType if the attribute is not a *real*
# attribute, but the workfow state.
res.append({'name': name, 'labelId': 'workflow_state',
'filterable': False})
else:
appyType = self.getAppyType(name, asDict) appyType = self.getAppyType(name, asDict)
if appyType: res.append(appyType) if appyType: res.append(appyType)
else: else:
@ -820,6 +814,18 @@ class BaseMixin:
else: else:
return res return res
def getIcons(self):
'''Gets the icons that can be shown besides the title of an object.'''
appyObj = self.appy()
if hasattr(appyObj, 'getIcons'): return appyObj.getIcons()
return ''
def getSubTitle(self):
'''Gets the content that must appear below the title of an object.'''
appyObj = self.appy()
if hasattr(appyObj, 'getSubTitle'): return appyObj.getSubTitle()
return ''
def getPreviousPage(self, phase, page): def getPreviousPage(self, phase, page):
'''Returns the page that precedes p_page which is in p_phase.''' '''Returns the page that precedes p_page which is in p_phase.'''
try: try:

View file

@ -40,7 +40,6 @@ class PoMessage:
POD_ASKACTION = 'Trigger related action' POD_ASKACTION = 'Trigger related action'
REF_NO = 'No object.' REF_NO = 'No object.'
REF_ADD = 'Add a new one' REF_ADD = 'Add a new one'
REF_ACTIONS = 'Actions'
REF_MOVE_UP = 'Move up' REF_MOVE_UP = 'Move up'
REF_MOVE_DOWN = 'Move down' REF_MOVE_DOWN = 'Move down'
REF_INVALID_INDEX = 'No move occurred: please specify a valid number.' REF_INVALID_INDEX = 'No move occurred: please specify a valid number.'
@ -69,7 +68,6 @@ class PoMessage:
MODIFIED_FIELD = 'Modified field' MODIFIED_FIELD = 'Modified field'
PREVIOUS_VALUE = 'Previous value' PREVIOUS_VALUE = 'Previous value'
PHASE = 'phase' PHASE = 'phase'
ROOT_TYPE = 'type'
CHOOSE_A_VALUE = ' - ' CHOOSE_A_VALUE = ' - '
CHOOSE_A_DOC = '[ Documents ]' CHOOSE_A_DOC = '[ Documents ]'
MIN_REF_VIOLATED = 'You must choose more elements here.' MIN_REF_VIOLATED = 'You must choose more elements here.'

View file

@ -92,11 +92,12 @@ img { border: 0; vertical-align: middle}
.list { border: 1px solid grey; margin-bottom: 3px;} .list { border: 1px solid grey; margin-bottom: 3px;}
.list td, .list th { border: 1px solid grey; .list td, .list th { border: 1px solid grey;
padding-left: 5px; padding-right: 5px; padding-top: 3px;} padding-left: 5px; padding-right: 5px; padding-top: 3px;}
.list th { background-color: #d7dee4; font-style: italic; font-weight: normal;} .list th { background-color: #d7dee4; font-style: italic; font-weight: normal;
text-align: left }
.grid th { font-style: italic; font-weight: normal; .grid th { font-style: italic; font-weight: normal;
border-bottom: 2px solid grey; padding: 2px 2px;} border-bottom: 2px solid grey; padding: 2px 2px }
.grid td { padding-right: 5px; } .grid td { padding-right: 5px }
.cellGap { padding-right: 0.4em; } .cellGap { padding-right: 0.4em }
.cellDashed { border: 1px dashed grey !important } .cellDashed { border: 1px dashed grey !important }
.noStyle { border: 0 !important; padding: 0 !important; margin: 0 !important; } .noStyle { border: 0 !important; padding: 0 !important; margin: 0 !important; }
.noStyle td { border:0 !important; padding:0 !important; margin:0 !important; } .noStyle td { border:0 !important; padding:0 !important; margin:0 !important; }

View file

@ -200,6 +200,26 @@ function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
else hidden.value = 'False'; else hidden.value = 'False';
} }
// Function that sets a value for showing/hiding sub-titles.
function setSubTitles(value) {
createCookie('showSubTitles', value);
// Get the sub-titles
var subTitles = document.getElementsByName('subTitle');
if (subTitles.length == 0) return;
for (var i=0; i < subTitles.length; i++) {
if (value == 'true') subTitles[i].style.display = 'block';
else subTitles[i].style.display = 'none';
}
}
// Function that toggles the value for showing/hiding sub-titles.
function toggleSubTitles() {
var value = readCookie('showSubTitles');
var newValue = 'true';
if (value == 'true') newValue = 'false';
setSubTitles(newValue);
}
// Functions used for master/slave relationships between widgets // Functions used for master/slave relationships between widgets
function getSlaveInfo(slave, infoType) { function getSlaveInfo(slave, infoType) {
// Returns the appropriate info about slavery, depending on p_infoType. // Returns the appropriate info about slavery, depending on p_infoType.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 B

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

After

Width:  |  Height:  |  Size: 470 B

View file

@ -70,11 +70,11 @@
style="cursor:pointer" onClick="toggleViewableElements()" align="left" /> style="cursor:pointer" onClick="toggleViewableElements()" align="left" />
<span tal:replace="columnHeader"/> <span tal:replace="columnHeader"/>
</th> </th>
<th tal:content="python: _('ref_actions')"></th> <th></th>
<th width="20px"><img <th width="20px"><img
tal:attributes="src string: $appUrl/ui/select_elems.png; tal:attributes="src string: $appUrl/ui/select_elems.png;
title python: _('select_delesect')" title python: _('select_delesect')"
onClick="toggleCheckboxes()" style="cursor:pointer"/> onClick="toggleCheckboxes()" style="cursor:pointer"></th>
</tr> </tr>
<tal:row repeat="row python: importElems[1]"> <tal:row repeat="row python: importElems[1]">
<tr tal:define="alreadyImported python: tool.isAlreadyImported(className, row[0]); <tr tal:define="alreadyImported python: tool.isAlreadyImported(className, row[0]);

View file

@ -115,3 +115,9 @@
style="cursor:pointer"/> style="cursor:pointer"/>
</tal:filter> </tal:filter>
</metal:sortAndFilter> </metal:sortAndFilter>
<tal:comment replace="nothing">Icon for hiding/showing details below the title</tal:comment>
<metal:details define-macro="showDetails" tal:condition="python: tool.subTitleIsUsed(className)">
<img tal:condition="python: widget['name'] == 'title'" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/toggleDetails.png" onClick="toggleSubTitles()"/>
</metal:details>

View file

@ -206,8 +206,10 @@
<table width="100%" class="summary"> <table width="100%" class="summary">
<tr> <tr>
<tal:comment replace="nothing">Title</tal:comment> <tal:comment replace="nothing">Title</tal:comment>
<td colspan="2" class="objectTitle" <td colspan="2" class="objectTitle">
tal:content="python: contextObj.getFieldValue('title', layoutType='view')"></td> <tal:icons replace="structure contextObj/getIcons"/>
<span tal:content="python: contextObj.getFieldValue('title', layoutType='view')"></span>
</td>
</tr> </tr>
<tr class="underTitle"> <tr class="underTitle">
<td colspan="2" class="by"> <td colspan="2" class="by">

View file

@ -3,15 +3,8 @@
<metal:fill fill-slot="content" <metal:fill fill-slot="content"
tal:define="className request/className; tal:define="className request/className;
searchName request/search|python:''"> searchName request/search|python:''">
<div metal:use-macro="context/ui/page/macros/prologue"/> <div metal:use-macro="context/ui/page/macros/prologue"/>
<tal:comment replace="nothing">Query result</tal:comment> <metal:result use-macro="tool/ui/result/macros/queryResult"/>
<div id="queryResult"></div>
<script type="text/javascript"
tal:define="ajaxUrl python: tool.getQueryUrl(className, searchName)"
tal:content="python: 'askQueryResult(\'queryResult\', \'%s\',\'%s\',\'%s\',0)' % (tool.absolute_url(), className, searchName)">
</script>
</metal:fill> </metal:fill>
</html> </html>
</tal:main> </tal:main>

View file

@ -1,4 +1,4 @@
<metal:queryResults define-macro="queryResult" <div id="queryResult" metal:define-macro="queryResult"
tal:define="_ python: tool.translate; tal:define="_ python: tool.translate;
className request/className; className request/className;
refInfo tool/getRefInfo; refInfo tool/getRefInfo;
@ -11,7 +11,6 @@
labelId python: searchName and ('%s_search_%s' % (className, searchName)) or ''; labelId python: searchName and ('%s_search_%s' % (className, searchName)) or '';
labelId python: (searchName == '_advanced') and 'search_results' or labelId; labelId python: (searchName == '_advanced') and 'search_results' or labelId;
searchLabel python: labelId and _(labelId) or ''; searchLabel python: labelId and _(labelId) or '';
severalTypes python: className and (className.find(',') != -1);
sortKey request/sortKey| python:''; sortKey request/sortKey| python:'';
sortOrder request/sortOrder| python:'asc'; sortOrder request/sortOrder| python:'asc';
filterKey request/filterKey| python:''; filterKey request/filterKey| python:'';
@ -22,10 +21,10 @@
batchSize queryResult/batchSize; batchSize queryResult/batchSize;
ajaxHookId python:'queryResult'; ajaxHookId python:'queryResult';
navBaseCall python: 'askQueryResult(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, tool.absolute_url(), className, searchName); navBaseCall python: 'askQueryResult(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, tool.absolute_url(), className, searchName);
newSearchUrl python: '%s/ui/search?className=%s%s' % (tool.absolute_url(), className, refUrlPart)"> newSearchUrl python: '%s/ui/search?className=%s%s' % (tool.absolute_url(), className, refUrlPart);
showSubTitles python: request.get('showSubTitles', 'true') == 'true'">
<tal:result condition="objs"> <tal:result condition="objs">
<tal:comment replace="nothing">Display here POD templates if required.</tal:comment> <tal:comment replace="nothing">Display here POD templates if required.</tal:comment>
<table tal:define="widgets python: tool.getResultPodFields(className); <table tal:define="widgets python: tool.getResultPodFields(className);
layoutType python:'view'" layoutType python:'view'"
@ -40,7 +39,7 @@
<tal:comment replace="nothing">The title of the search.</tal:comment> <tal:comment replace="nothing">The title of the search.</tal:comment>
<p> <p>
<span tal:replace="structure python: test(searchName, searchLabel, test(severalTypes, _(tool.getAppName()), _('%s_plural' % className)))"/> <span tal:replace="structure python: test(searchName, searchLabel, _('%s_plural' % className))"/>
(<span tal:replace="totalNumber"/>) (<span tal:replace="totalNumber"/>)
<tal:newSearch condition="python: searchName == '_advanced'"> <tal:newSearch condition="python: searchName == '_advanced'">
&nbsp;&mdash;&nbsp;<i><a tal:attributes="href newSearchUrl" &nbsp;&mdash;&nbsp;<i><a tal:attributes="href newSearchUrl"
@ -72,37 +71,42 @@
filterable widget/filterable|nothing;"> filterable widget/filterable|nothing;">
<span tal:replace="structure python: tool.truncateText(_(widget['labelId']))"/> <span tal:replace="structure python: tool.truncateText(_(widget['labelId']))"/>
<metal:icons use-macro="context/ui/navigate/macros/sortAndFilter"/> <metal:icons use-macro="context/ui/navigate/macros/sortAndFilter"/>
<metal:details use-macro="context/ui/navigate/macros/showDetails"/>
</th> </th>
</tal:header> </tal:header>
<tal:comment replace="nothing">Object type, shown if instances of several types are shown</tal:comment>
<th tal:condition="severalTypes">
<span tal:replace="python: _('root_type')"></span>
</th>
<tal:comment replace="nothing">Actions</tal:comment>
<th tal:content="python: _('ref_actions')"></th>
</tr> </tr>
<tal:comment replace="nothing">Results</tal:comment> <tal:comment replace="nothing">Results</tal:comment>
<tal:row repeat="obj objs"> <tal:row repeat="obj objs">
<tr id="query_row" tal:define="odd repeat/obj/odd" <tr id="query_row" valign="top" tal:define="odd repeat/obj/odd"
tal:attributes="class python:test(odd, 'even', 'odd')"> tal:attributes="class python:test(odd, 'even', 'odd')">
<tal:fields repeat="widget widgets"> <tal:fields repeat="widget widgets">
<tal:comment replace="nothing">Title</tal:comment> <tal:comment replace="nothing">Title</tal:comment>
<td id="field_title" <td id="field_title"
tal:condition="python: widget['name'] == 'title'"> tal:condition="python: widget['name'] == 'title'">
<tal:icons replace="structure obj/getIcons"/>
<a tal:define="navInfo python:'search.%s.%s.%d.%d' % (className, searchName, repeat['obj'].number()+startNumber, totalNumber);" <a tal:define="navInfo python:'search.%s.%s.%d.%d' % (className, searchName, repeat['obj'].number()+startNumber, totalNumber);"
tal:content="obj/Title" tal:attributes="href python: obj.getUrl(nav=navInfo, page=obj.getDefaultViewPage())"></a> tal:content="obj/Title" tal:attributes="href python: obj.getUrl(nav=navInfo, page=obj.getDefaultViewPage())"></a>
</td> <div name="subTitle" tal:content="structure obj/getSubTitle"
tal:attributes="style python: showSubTitles and 'display:block' or 'display:none'"></div>
<tal:comment replace="nothing">Workflow state</tal:comment> <tal:comment replace="nothing">Actions: edit, delete</tal:comment>
<td id="field_workflow_state" <div tal:attributes="align dright" tal:condition="obj/mayAct">
tal:condition="python: widget['name'] == 'state'" <a tal:define="navInfo python:'search.%s.%s.%d.%d' % (className, searchName, repeat['obj'].number()+startNumber, totalNumber);"
tal:content="python: _(obj.getWorkflowLabel())"> tal:attributes="href python: obj.getUrl(mode='edit', page=obj.getDefaultEditPage(), nav=navInfo)"
tal:condition="obj/mayEdit">
<img tal:attributes="src string: $appUrl/ui/edit.gif;
title python: _('object_edit')"/></a><img
tal:condition="obj/mayDelete" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/delete.png;
title python: _('object_delete');
onClick python:'onDeleteObject(\'%s\')' % obj.UID()"/>
</div>
</td> </td>
<tal:comment replace="nothing">Any other field</tal:comment> <tal:comment replace="nothing">Any other field</tal:comment>
<td tal:condition="python: widget['name'] not in ('title', 'state')" <td tal:condition="python: widget['name'] != 'title'"
tal:attributes="id python:'field_%s' % widget['name']"> tal:attributes="id python:'field_%s' % widget['name']">
<tal:field define="contextObj python:obj; <tal:field define="contextObj python:obj;
layoutType python:'cell'; layoutType python:'cell';
@ -112,33 +116,6 @@
</tal:field> </tal:field>
</td> </td>
</tal:fields> </tal:fields>
<tal:comment replace="nothing">Column "Object type", shown if instances of several types are shown</tal:comment>
<td tal:condition="severalTypes" id="field_root_type"
tal:content="python: _(obj.portal_type)"></td>
<tal:comment replace="nothing">Column "Actions"</tal:comment>
<td tal:attributes="align dright">
<table class="noStyle" tal:condition="obj/mayAct">
<tr>
<tal:comment replace="nothing">Edit the element</tal:comment>
<td>
<a tal:define="navInfo python:'search.%s.%s.%d.%d' % (className, searchName, repeat['obj'].number()+startNumber, totalNumber);"
tal:attributes="href python: obj.getUrl(mode='edit', page=obj.getDefaultEditPage(), nav=navInfo)"
tal:condition="obj/mayEdit">
<img tal:attributes="src string: $appUrl/ui/edit.gif;
title python: _('object_edit')"/>
</a></td>
<tal:comment replace="nothing">Delete the element</tal:comment>
<td>
<img tal:condition="obj/mayDelete" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/delete.png;
title python: _('object_delete');
onClick python:'onDeleteObject(\'%s\')' % obj.UID()"/>
</td>
</tr>
</table>
</td>
</tr> </tr>
</tal:row> </tal:row>
</table> </table>
@ -154,4 +131,4 @@
tal:content="python: _('search_new')"></a></i> tal:content="python: _('search_new')"></a></i>
</tal:newSearch> </tal:newSearch>
</tal:noResult> </tal:noResult>
</metal:queryResults> </div>

BIN
gen/ui/toggleDetails.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 B

After

Width:  |  Height:  |  Size: 231 B

View file

@ -8,6 +8,7 @@
allows to reach the correct page where the forward reference is defined. If we are 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 on a forward reference, the "nav" parameter is added to the URL for allowing to navigate
from one object to the next/previous on ui/view.</tal:comment> from one object to the next/previous on ui/view.</tal:comment>
<tal:icons replace="structure obj/getIcons"/>
<a tal:define="includeShownInfo includeShownInfo | python:False; <a tal:define="includeShownInfo includeShownInfo | python:False;
navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber); navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);
navInfo python: test(appyType['isBack'], '', navInfo); navInfo python: test(appyType['isBack'], '', navInfo);
@ -22,24 +23,6 @@
<table class="noStyle" <table class="noStyle"
tal:define="isBack appyType/isBack"> tal:define="isBack appyType/isBack">
<tr> <tr>
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
<td tal:condition="python: not isBack and (len(objs)&gt;1) and changeOrder and canWrite">
<tal:moveRef define="objectIndex python: contextObj.getAppyRefIndex(fieldName, obj);
ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'ChangeRefOrder\', {\'refObjectUid\':\'%s\', \'move\':\'**v**\'}' % (startNumber, obj.UID()))">
<tal:comment replace="nothing">Move up</tal:comment>
<img tal:condition="python: objectIndex &gt; 0"
tal:attributes="src string: $appUrl/ui/arrowUp.png;
title python: _('move_up');
onClick python: ajaxBaseCall.replace('**v**', 'up')"
style="cursor:pointer"/>
<tal:comment replace="nothing">Move down</tal:comment>
<img tal:condition="python: objectIndex &lt; (totalNumber-1)"
tal:attributes="src string: $appUrl/ui/arrowDown.png;
title python: _('move_down');
onClick python: ajaxBaseCall.replace('**v**', 'down')"
style="cursor:pointer"/>
</tal:moveRef>
</td>
<tal:comment replace="nothing">Edit</tal:comment> <tal:comment replace="nothing">Edit</tal:comment>
<td tal:condition="python: not appyType['noForm'] and obj.mayEdit() and appyType['delete']"> <td tal:condition="python: not appyType['noForm'] and obj.mayEdit() and appyType['delete']">
<a tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);" <a tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);"
@ -62,6 +45,20 @@
onClick python:'onUnlinkObject(\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), appyType['name'], obj.UID()); onClick python:'onUnlinkObject(\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), appyType['name'], obj.UID());
title python: _('object_unlink')"/> title python: _('object_unlink')"/>
</td> </td>
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
<td tal:condition="python: not isBack and (len(objs)&gt;1) and changeOrder and canWrite">
<tal:moveRef define="objectIndex python: contextObj.getAppyRefIndex(fieldName, obj);
ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'ChangeRefOrder\', {\'refObjectUid\':\'%s\', \'move\':\'**v**\'}' % (startNumber, obj.UID()))">
<img tal:condition="python: objectIndex &gt; 0" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/arrowUp.png;
title python: _('move_up');
onClick python: ajaxBaseCall.replace('**v**', 'up')"/><img style="cursor:pointer"
tal:condition="python: objectIndex &lt; (totalNumber-1)"
tal:attributes="src string: $appUrl/ui/arrowDown.png;
title python: _('move_down');
onClick python: ajaxBaseCall.replace('**v**', 'down')"/>
</tal:moveRef>
</td>
</tr> </tr>
</table> </table>
</metal:objectActions> </metal:objectActions>
@ -125,7 +122,8 @@
atMostOneRef python: (appyType['multiplicity'][1] == 1) and (len(objs)&lt;=1); atMostOneRef python: (appyType['multiplicity'][1] == 1) and (len(objs)&lt;=1);
addConfirmMsg python: appyType['addConfirm'] and _('%s_addConfirm' % appyType['labelId']) or ''; addConfirmMsg python: appyType['addConfirm'] and _('%s_addConfirm' % appyType['labelId']) or '';
navBaseCall python: 'askRefField(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, contextObj.absolute_url(), fieldName, innerRef); navBaseCall python: 'askRefField(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, contextObj.absolute_url(), fieldName, innerRef);
changeOrder python: contextObj.callField(fieldName, 'changeOrderEnabled', contextObj)" changeOrder python: contextObj.callField(fieldName, 'changeOrderEnabled', contextObj);
showSubTitles python: request.get('showSubTitles', 'true') == 'true'"
tal:attributes="id ajaxHookId"> tal:attributes="id ajaxHookId">
<tal:comment replace="nothing">This macro displays the Reference widget on a "view" page. <tal:comment replace="nothing">This macro displays the Reference widget on a "view" page.
@ -181,21 +179,25 @@
<th tal:repeat="widget widgets"> <th tal:repeat="widget widgets">
<span tal:content="python: _(widget['labelId'])"></span> <span tal:content="python: _(widget['labelId'])"></span>
<metal:sortIcons use-macro="app/ui/widgets/ref/macros/sortIcons" /> <metal:sortIcons use-macro="app/ui/widgets/ref/macros/sortIcons" />
<tal:sd define="className linkedPortalType">
<metal:details use-macro="context/ui/navigate/macros/showDetails"/>
</tal:sd>
</th> </th>
<th tal:content="python: _('ref_actions')"></th>
</tr> </tr>
<tal:row repeat="obj objs"> <tal:row repeat="obj objs">
<tr valign="middle" tal:define="odd repeat/obj/odd" <tr valign="top" tal:define="odd repeat/obj/odd"
tal:attributes="class python:test(odd, 'even', 'odd')"> tal:attributes="class python:test(odd, 'even', 'odd')">
<td tal:repeat="widget widgets" <td tal:repeat="widget widgets"
tal:attributes="width python: appyType['shownInfoWidths'][repeat['widget'].index]"> tal:attributes="width python: appyType['shownInfoWidths'][repeat['widget'].index]">
<tal:title condition="python: widget['name'] == 'title'"> <tal:title condition="python: widget['name'] == 'title'">
<metal:showObjectTitle use-macro="app/ui/widgets/ref/macros/objectTitle"/> <metal:showObjectTitle use-macro="app/ui/widgets/ref/macros/objectTitle"/>
<div name="subTitle" tal:content="structure obj/getSubTitle"
tal:attributes="style python: showSubTitles and 'display:block' or 'display:none'"></div>
<div tal:attributes="align dright" tal:condition="obj/mayAct">
<metal:showObjectActions use-macro="app/ui/widgets/ref/macros/objectActions" />
</div>
</tal:title> </tal:title>
<tal:state condition="python: widget['name'] == 'state'" <tal:other condition="python: widget['name'] != 'title'">
content="python: _(obj.getWorkflowLabel())">
</tal:state>
<tal:other condition="python: widget['name'] not in ('title', 'state')">
<tal:field define="contextObj python:obj; <tal:field define="contextObj python:obj;
layoutType python: 'cell'; layoutType python: 'cell';
innerRef python:True"> innerRef python:True">
@ -203,12 +205,6 @@
</tal:field> </tal:field>
</tal:other> </tal:other>
</td> </td>
<tal:comment replace="nothing">Actions</tal:comment>
<td tal:attributes="align dright">
<tal:show condition="obj/mayAct">
<metal:showObjectActions use-macro="app/ui/widgets/ref/macros/objectActions" />
</tal:show>
</td>
</tr> </tr>
</tal:row> </tal:row>
</tal:widgets> </tal:widgets>

View file

@ -1,13 +1,19 @@
<tal:comment replace="nothing">View macro for a String.</tal:comment> <tal:comment replace="nothing">View macro for a String.</tal:comment>
<metal:view define-macro="view" <metal:view define-macro="view"
tal:define="fmt widget/format"> tal:define="fmt widget/format; isUrl widget/isUrl">
<span tal:condition="python: fmt in (0, 3)"> <span tal:condition="python: fmt in (0, 3)">
<ul tal:condition="python: value and isMultiple"> <ul tal:condition="python: value and isMultiple">
<li tal:repeat="sv value"><i tal:content="structure sv"></i></li> <li tal:repeat="sv value"><i tal:content="structure sv"></i></li>
</ul> </ul>
<tal:singleValue condition="python: value and not isMultiple"> <tal:singleValue condition="python: value and not isMultiple">
<span tal:condition="python: fmt != 3" tal:replace="structure value"/> <tal:comment replace="nothing">A password</tal:comment>
<span tal:condition="python: fmt == 3">********</span> <span tal:condition="python: fmt == 3">********</span>
<tal:comment replace="nothing">A URL</tal:comment>
<a tal:condition="python: (fmt != 3) and isUrl" target="_blank"
tal:attributes="href value" tal:content="value"></a>
<tal:comment replace="nothing">Any other value</tal:comment>
<span tal:condition="python: (fmt != 3) and not isUrl"
tal:replace="structure value"/>
</tal:singleValue> </tal:singleValue>
</span> </span>
<tal:comment replace="nothing">Text</tal:comment> <tal:comment replace="nothing">Text</tal:comment>