<tal:comment replace="nothing"> We begin with some sub-macros used within macro "show" defined below. </tal:comment> <metal:objectTitle define-macro="objectTitle"> <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 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 ui/view.</tal:comment> <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: test(appyType['isBack'], '', navInfo); pageName python: appyType['isBack'] and appyType['backd']['pageName'] or 'main'; fullUrl python: obj.getUrl(page=pageName, nav=navInfo)" tal:attributes="href fullUrl" tal:content="python: (not includeShownInfo) and obj.Title() or contextObj.getReferenceLabel(fieldName, obj.appy())"></a> </metal:objectTitle> <metal:objectActions define-macro="objectActions"> <tal:comment replace="nothing">Displays icons for triggering actions on a given referenced object (edit, delete, etc).</tal:comment> <table class="noStyle" tal:define="isBack appyType/isBack"> <tr> <tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment> <td tal:condition="python: not isBack and (len(objs)>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 > 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 < (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> <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);" tal:attributes="href python: obj.getUrl(mode='edit', page='main', nav=navInfo)"> <img tal:attributes="src string: $appUrl/ui/edit.gif; title python: _('object_edit')"/> </a> </td> <tal:comment replace="nothing">Delete</tal:comment> <td tal:condition="python: not isBack and appyType['delete'] and canWrite and obj.mayDelete()"> <img style="cursor:pointer" tal:attributes="src string: $appUrl/ui/delete.png; onClick python:'onDeleteObject(\'%s\')' % obj.UID(); title python: _('object_delete')"/> </td> <tal:comment replace="nothing">Unlink</tal:comment> <td tal:condition="python: not isBack and appyType['unlink'] and canWrite"> <img style="cursor:pointer" tal:attributes="src string: $appUrl/ui/unlink.png; onClick python:'onUnlinkObject(\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), appyType['name'], obj.UID()); title python: _('object_unlink')"/> </td> </tr> </table> </metal:objectActions> <metal:plusIcon define-macro="plusIcon"> <tal:comment replace="nothing">Displays the "plus" icon that allows to add new object through a reference widget. Indeed, If field was declared as "addable", we must provide an icon for creating a new linked object (at least if multiplicities allow it).</tal:comment> <img style="cursor:pointer" tal:condition="showPlusIcon" tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], 0, totalNumber); formCall python:'window.location=\'%s/do?action=Create&className=%s&nav=%s\'' % (folder.absolute_url(), linkedPortalType, navInfo); formCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', "%s", "%s")' % (formCall, addConfirmMsg), formCall); noFormCall python: navBaseCall.replace('**v**', '%d, \'CreateWithoutForm\'' % startNumber); noFormCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', "%s", "%s")' % (noFormCall, addConfirmMsg), noFormCall)" tal:attributes="src string:$appUrl/ui/plus.png; title python: _('add_ref'); onClick python: test(appyType['noForm'], noFormCall, formCall)"/> </metal:plusIcon> <tal:comment replace="nothing"> This macro displays, in a cell header from a ref table, icons for sorting the ref field according to the field that corresponds to this column. </tal:comment> <metal:sortIcons define-macro="sortIcons" tal:define="ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'SortReference\', {\'sortKey\':\'%s\', \'reverse\':\'**v**\'}' % (startNumber, widget['name']))" tal:condition="python: changeOrder and canWrite and tool.isSortable(widget['name'], objs[0].meta_type, 'ref')"> <img style="cursor:pointer" tal:attributes="src string:$appUrl/ui/sortAsc.png; onClick python: ajaxBaseCall.replace('**v**', 'False')"/> <img style="cursor:pointer" tal:attributes="src string:$appUrl/ui/sortDesc.png; onClick python: ajaxBaseCall.replace('**v**', 'True')"/> </metal:sortIcons> <tal:comment replace="nothing">View macro for a Ref.</tal:comment> <metal:view define-macro="view" tal:define="dummy python: request.set('fieldName', widget['name'])"> <metal:ref use-macro="app/ui/widgets/ref/macros/viewContent"/> </metal:view> <tal:comment replace="nothing"> This macro is called by a XmlHttpRequest (or directly by the macro above) for displaying the referred objects of a reference field. </tal:comment> <div metal:define-macro="viewContent" tal:define="fieldName request/fieldName; appyType python: contextObj.getAppyType(fieldName, asDict=True); innerRef python: test(request.get('innerRef', False)=='True', True, False); ajaxHookId python: contextObj.UID()+fieldName; startNumber python: int(request.get('%s_startNumber' % ajaxHookId, 0)); tool contextObj/getTool; _ python: tool.translate; refObjects python:contextObj.getAppyRefs(fieldName, startNumber); objs refObjects/objects; totalNumber refObjects/totalNumber; batchSize refObjects/batchSize; folder contextObj/getCreateFolder; linkedPortalType python: tool.getPortalType(appyType['klass']); canWrite python: not appyType['isBack'] and contextObj.allows(appyType['writePermission']); showPlusIcon python: contextObj.mayAddReference(fieldName); atMostOneRef python: (appyType['multiplicity'][1] == 1) and (len(objs)<=1); addConfirmMsg python: appyType['addConfirm'] and _('%s_addConfirm' % appyType['labelId']) or ''; navBaseCall python: 'askRefField(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, contextObj.absolute_url(), fieldName, innerRef); changeOrder python: contextObj.callField(fieldName, 'changeOrderEnabled', contextObj)" tal:attributes="id ajaxHookId"> <tal:comment replace="nothing">This macro displays the Reference widget on a "view" page. The definition of "atMostOneRef" above may sound strange: we shouldn't check the actual number of referenced objects. But for back references people often forget to specify multiplicities. So concretely, multiplicities (0,None) are coded as (0,1).</tal:comment> <tal:atMostOneReference condition="atMostOneRef"> <tal:comment replace="nothing">Display a simplified widget if maximum number of referenced objects is 1.</tal:comment> <table><tr valign="top"> <tal:comment replace="nothing">If there is no object...</tal:comment> <tal:noObject condition="not:objs"> <td class="discreet" tal:content="python: _('no_ref')"></td> <td><metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/></td> </tal:noObject> <tal:comment replace="nothing">If there is an object...</tal:comment> <tal:objectIsPresent condition="python: objs"> <tal:obj repeat="obj objs"> <td tal:define="includeShownInfo python:True"><metal:showObjectTitle use-macro="app/ui/widgets/ref/macros/objectTitle" /></td> </tal:obj> </tal:objectIsPresent> </tr></table> </tal:atMostOneReference> <tal:comment replace="nothing">Display a table in all other cases.</tal:comment> <tal:anyNumberOfReferences condition="not: atMostOneRef"> <div tal:condition="python: not innerRef or showPlusIcon"> (<span tal:replace="totalNumber"/>) <metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/> <tal:comment replace="nothing">The search icon if field is queryable</tal:comment> <a tal:condition="python: objs and appyType['queryable']" tal:attributes="href python: '%s/ui/search?className=%s&ref=%s:%s' % (tool.absolute_url(), linkedPortalType, contextObj.UID(), appyType['name'])"> <img src="search.gif" tal:attributes="title python: _('search_objects')"/></a> </div> <tal:comment replace="nothing">Appy (top) navigation</tal:comment> <metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/> <tal:comment replace="nothing">No object is present</tal:comment> <p class="discreet" tal:condition="not:objs" tal:content="python: _('no_ref')"></p> <table width="100%" tal:condition="python: objs" tal:attributes="class python:test(innerRef, 'innerAppyTable', '')"> <tr valign="bottom"><td> <tal:comment replace="nothing">Show forward or backward reference(s)</tal:comment> <table tal:attributes="class python:test(innerRef, '', 'list'); width python:test(innerRef, '100%', appyType['layouts']['view']['width']);"> <tal:widgets define="widgets python: objs[0].getAppyTypesFromNames(appyType['shownInfo'])"> <tr tal:condition="appyType/showHeaders"> <th tal:repeat="widget widgets"> <span tal:content="python: _(widget['labelId'])"></span> <metal:sortIcons use-macro="app/ui/widgets/ref/macros/sortIcons" /> </th> <th tal:content="python: _('ref_actions')"></th> </tr> <tal:row repeat="obj objs"> <tr valign="middle" tal:define="odd repeat/obj/odd" tal:attributes="class python:test(odd, 'even', 'odd')"> <td tal:repeat="widget widgets" tal:attributes="width python: appyType['shownInfoWidths'][repeat['widget'].index]"> <tal:title condition="python: widget['name'] == 'title'"> <metal:showObjectTitle use-macro="app/ui/widgets/ref/macros/objectTitle"/> </tal:title> <tal:state condition="python: widget['name'] == 'state'" content="python: _(obj.getWorkflowLabel())"> </tal:state> <tal:other condition="python: widget['name'] not in ('title', 'state')"> <tal:field define="contextObj python:obj; layoutType python: 'cell'; innerRef python:True"> <metal:field use-macro="app/ui/widgets/show/macros/field" /> </tal:field> </tal:other> </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> </tal:row> </tal:widgets> </table> </td></tr> </table> <tal:comment replace="nothing">Appy (bottom) navigation</tal:comment> <metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/> </tal:anyNumberOfReferences> </div> <tal:comment replace="nothing">Edit macro for an Ref.</tal:comment> <metal:editRef define-macro="edit" tal:condition="widget/link" tal:define="requestValue python: request.get(name, []); inRequest python: request.has_key(name); allObjects python: contextObj.getSelectableAppyRefs(name); refUids python: [o.UID() for o in contextObj.getAppyRefs(name)['objects']]; isBeingCreated python: contextObj.isTemporary() or ('/portal_factory/' in contextObj.absolute_url())"> <select tal:attributes="name name; size python: test(isMultiple, widget['height'], ''); multiple python: test(isMultiple, 'multiple', '')"> <option value="" tal:condition="not: isMultiple" tal:content="python: _('choose_a_value')"></option> <tal:ref repeat="refObj allObjects"> <option tal:define="uid python: contextObj.getReferenceUid(refObj)" tal:content="python: contextObj.getReferenceLabel(name, refObj)" tal:attributes="value uid; selected python:(inRequest and (uid in requestValue) or (not inRequest and ((uid in refUids)))) and True or False"> </option> </tal:ref> </select> </metal:editRef> <tal:comment replace="nothing">Cell macro for a Ref.</tal:comment> <metal:cell define-macro="cell"> <metal:call use-macro="app/ui/widgets/ref/macros/view"/> </metal:cell> <tal:comment replace="nothing">Search macro for a Ref.</tal:comment> <metal:search define-macro="search"> <label tal:attributes="for widgetName" tal:content="python: _(widget['labelId'])"></label><br> <tal:comment replace="nothing">The "and" / "or" radio buttons</tal:comment> <tal:operator define="operName python: 'o_%s' % name; orName python: '%s_or' % operName; andName python: '%s_and' % operName;" condition="python: widget['multiplicity'][1]!=1"> <input type="radio" tal:attributes="name operName; id orName" checked="checked" value="or"/> <label tal:attributes="for orName" tal:content="python: _('search_or')"></label> <input type="radio" tal:attributes="name operName; id andName" value="and"/> <label tal:attributes="for andName" tal:content="python: _('search_and')"></label><br/> </tal:operator> <tal:comment replace="nothing">The list of values</tal:comment> <select tal:attributes="name widgetName; size widget/height" multiple="multiple"> <tal:option repeat="v python: tool.getSearchValues(name, className)"> <option tal:define="uid python: v[0]; title python: tool.getReferenceLabel(name, v[1], className)" tal:attributes="value uid; title title" tal:content="python: tool.truncateValue(title, widget)"> </option> </tal:option> </select> </metal:search>