2009-06-29 07:06:01 -05:00
<tal:comment replace="nothing"> We begin with some sub-macros used within
macro "showReference" defined below.</tal:comment>
2009-10-18 07:52:27 -05:00
<metal:objectTitle define-macro="objectTitle">
2009-06-29 07:06:01 -05:00
<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
2009-11-17 03:05:19 -06:00
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>
2009-10-18 07:52:27 -05:00
<a tal:define="viewUrl obj/getUrl;
2009-11-17 03:05:19 -06:00
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)"
2009-06-29 07:06:01 -05:00
tal:attributes="href fullUrl" tal:content="obj/Title"></a>
</metal:objectTitle>
2009-10-18 07:52:27 -05:00
<metal:objectActions define-macro="objectActions">
2009-06-29 07:06:01 -05:00
<tal:comment replace="nothing">Displays icons for triggering actions on a given
referenced object (edit, delete, etc).</tal:comment>
<table class="no-style-table" cellpadding="0" cellspacing="0">
<tr>
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
2009-10-25 15:42:08 -05:00
<td class="noPadding" tal:condition="python: (len(objs)>1) and member.has_permission('Modify portal content', obj)">
<tal:moveRef define="objectIndex python:contextObj.getAppyRefIndex(fieldName, obj);
baseUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId, '%s_startNumber' % ajaxHookId: startNumber, 'action':'ChangeRefOrder', 'refObjectUid': obj.UID()})">
<tal:comment replace="nothing">Move up</tal:comment>
<img tal:define="ajaxUrl python: baseUrl + '&move=up'" tal:condition="python: objectIndex > 0"
tal:attributes="src string: $portal_url/skyn/arrowUp.png;
title python: tool.translate('move_up');
onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, ajaxUrl)"
style="cursor:pointer"/>
<tal:comment replace="nothing">Move down</tal:comment>
<img tal:define="ajaxUrl python: baseUrl + '&move=down'" tal:condition="python: objectIndex < (totalNumber-1)"
tal:attributes="src string: $portal_url/skyn/arrowDown.png;
title python: tool.translate('move_down');
onClick python: 'askAjaxChunk(\'%s\', \'%s\')' % (ajaxHookId, ajaxUrl)"
style="cursor:pointer"/>
</tal:moveRef>
2009-06-29 07:06:01 -05:00
</td>
2009-11-24 15:41:42 -06:00
<tal:comment replace="nothing">Edit the element</tal:comment>
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/skyn/edit'"
tal:condition="python: member.has_permission('Modify portal content', obj)">
2009-11-25 13:37:22 -06:00
<img title="label_edit" i18n:domain="plone" i18n:attributes="title"
tal:attributes="src string: $portal_url/skyn/edit.gif"/>
2009-11-24 15:41:42 -06:00
</a></td>
<tal:comment replace="nothing">Delete the element</tal:comment>
<td class="noPadding">
<img tal:condition="python: member.has_permission('Delete objects', obj)"
title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/delete.png;
onClick python:'javascript:onDeleteObject(\'%s\')' % obj.UID()"/>
</td>
2009-06-29 07:06:01 -05:00
</tr>
</table>
</metal:objectActions>
2009-10-18 07:52:27 -05:00
<metal:plusIcon define-macro="plusIcon">
2009-06-29 07:06:01 -05:00
<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>
2009-10-18 07:52:27 -05:00
<img style="cursor:pointer" tal:condition="showPlusIcon"
tal:attributes="src string:$portal_url/skyn/plus.png;
title python: tool.translate('add_ref');
2009-10-25 15:42:08 -05:00
onClick python: 'href: window.location=\'%s/skyn/do?action=Create&initiator=%s&field=%s&type_name=%s\'' % (folder.absolute_url(), contextObj.UID(), fieldName, linkedPortalType)"/>
2009-06-29 07:06:01 -05:00
</metal:plusIcon>
2009-10-25 15:42:08 -05:00
<tal:comment replace="nothing">
This macro shows a reference field. More precisely, it shows nothing, but calls
a Javascript function that will asynchonously call (via a XmlHttpRequest object) the
macro 'showReferenceContent' defined below, that will really show content.
It requires:
- isBack (bool) Is the reference a backward or forward reference?
- fieldName (string) The name of the reference field (if it is a forward reference)
or the name of the Archetypes relationship (if it is a backward reference)
- innerRef (bool) Are we rendering a reference within a reference or not?
- contextObj (object) the object from which the reference starts
- labelId (string) the i18n id of the reference field label
- descrId (string) the i18n id of the reference field description
</tal:comment>
2009-10-18 07:52:27 -05:00
<div metal:define-macro="showReference"
2009-11-17 03:05:19 -06:00
tal:define="ajaxHookId python: contextObj.UID() + fieldName;
2009-10-25 15:42:08 -05:00
ajaxUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId})"
tal:attributes="id ajaxHookId">
<script language="javascript"
tal:content="python: 'askAjaxChunk(\'%s\',\'%s\')' % (ajaxHookId, ajaxUrl)">
</script>
</div>
<tal:comment replace="nothing">
This macro is called by a XmlHttpRequest for displaying the paginated referred objects
of a reference field.
</tal:comment>
<div metal:define-macro="showReferenceContent"
tal:define="fieldName request/fieldName;
isBack python: test(request['isBack']=='True', True, False);
innerRef python: test(request['innerRef']=='True', True, False);
labelId request/labelId;
descrId request/descrId;
ajaxHookId python: contextObj.UID()+fieldName;
startNumber python: int(request.get('%s_startNumber' % ajaxHookId, 0));
appyType python: contextObj.getAppyType(fieldName, not isBack);
tool contextObj/getTool;
refObjects python:contextObj.getAppyRefs(fieldName, not isBack, startNumber);
objs refObjects/objects;
totalNumber refObjects/totalNumber;
batchSize refObjects/batchSize;
folder python: test(contextObj.isPrincipiaFolderish, contextObj, contextObj.getParentNode());
2009-06-29 07:06:01 -05:00
flavour python:tool.getFlavour(contextObj);
linkedPortalType python:flavour.getPortalType(appyType['klass']);
2009-10-25 15:42:08 -05:00
addPermission python: '%s: Add %s' % (tool.getAppName(), linkedPortalType);
2009-06-29 07:06:01 -05:00
multiplicity python:test(isBack, appyType['backd']['multiplicity'], appyType['multiplicity']);
maxReached python:(multiplicity[1] != None) and (len(objs) >= multiplicity[1]);
showPlusIcon python:not isBack and appyType['add'] and not maxReached and member.has_permission(addPermission, folder);
2009-10-25 15:42:08 -05:00
atMostOneRef python: (multiplicity[1] == 1) and (len(objs)<=1);
label python: tool.translate(labelId);
2009-11-03 08:02:18 -06:00
description python: tool.translate(descrId);
2009-11-17 03:05:19 -06:00
baseUrl python: contextObj.getUrl('showRef', **{'fieldName': fieldName, 'isBack': isBack, 'innerRef': innerRef, 'labelId': labelId, 'descrId': descrId, '%s_startNumber' % ajaxHookId: '**v**'})">
2009-06-29 07:06:01 -05:00
<tal:comment replace="nothing">This macro displays the Reference widget on a "consult" 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 class="no-style-table" cellpadding="0" cellspacing="0"><tr valign="top">
2009-10-18 07:52:27 -05:00
<td><span class="appyLabel" tal:condition="not: innerRef" tal:content="label"></span></td>
2009-06-29 07:06:01 -05:00
<tal:comment replace="nothing">If there is no object...</tal:comment>
<tal:noObject condition="not:objs">
2009-10-18 07:52:27 -05:00
<td tal:content="python: tool.translate('no_ref')"></td>
<td><metal:plusIcon use-macro="here/skyn/ref/macros/plusIcon"/></td>
2009-06-29 07:06:01 -05:00
</tal:noObject>
<tal:comment replace="nothing">If there is an object...</tal:comment>
<tal:objectIsPresent condition="python: len(objs) == 1">
2009-11-17 03:05:19 -06:00
<tal:obj repeat="obj objs">
2009-10-18 07:52:27 -05:00
<td><metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle" /></td>
2009-06-29 07:06:01 -05:00
<td tal:condition="not: isBack">
2009-10-18 07:52:27 -05:00
<metal:showObjectActions use-macro="here/skyn/ref/macros/objectActions" />
2009-06-29 07:06:01 -05:00
</td>
</tal:obj>
</tal:objectIsPresent>
</tr></table>
</tal:atMostOneReference>
<tal:comment replace="nothing">Display a fieldset in all other cases.</tal:comment>
<tal:anyNumberOfReferences condition="not: atMostOneRef">
<fieldset tal:attributes="class python:test(innerRef, 'innerAppyFieldset', '')">
<legend tal:condition="python: not innerRef or showPlusIcon">
2009-10-18 07:52:27 -05:00
<span tal:condition="not: innerRef" tal:content="label"/>
2009-11-17 03:05:19 -06:00
(<span tal:replace="totalNumber"/>)
2009-10-18 07:52:27 -05:00
<metal:plusIcon use-macro="here/skyn/ref/macros/plusIcon"/>
2009-06-29 07:06:01 -05:00
</legend>
<tal:comment replace="nothing">Object description</tal:comment>
2009-11-03 08:02:18 -06:00
<p tal:condition="python: not innerRef and description.strip()"
2009-10-18 07:52:27 -05:00
tal:content="description" class="discreet" ></p>
2009-06-29 07:06:01 -05:00
2009-10-25 15:42:08 -05:00
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
<metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/>
2009-06-29 07:06:01 -05:00
<tal:comment replace="nothing">No object is present</tal:comment>
2009-10-18 07:52:27 -05:00
<p tal:condition="not:objs" tal:content="python: tool.translate('no_ref')"></p>
2009-06-29 07:06:01 -05:00
<table width="100%" cellspacing="0" cellpadding="0" tal:condition="objs"
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
<tr valign="bottom"><td>
<tal:comment replace="nothing">Show backward reference(s)</tal:comment>
<table class="no-style-table" cellspacing="0" cellpadding="0"
tal:condition="python: isBack and objs">
<tr tal:repeat="obj objs">
2009-10-18 07:52:27 -05:00
<td><metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle" />
2009-06-29 07:06:01 -05:00
</td>
</tr>
</table>
<tal:comment replace="nothing">Show forward reference(s)</tal:comment>
2009-12-15 14:30:43 -06:00
<table tal:attributes="class python:test(innerRef, '', 'listing nosort');
2009-06-29 07:06:01 -05:00
width python:test(innerRef, '100%', test(appyType['wide'], '100%', ''))"
align="right" tal:condition="python: not isBack and objs" cellpadding="0" cellspacing="0">
<tr tal:condition="appyType/showHeaders">
2009-10-18 07:52:27 -05:00
<th tal:condition="python: 'title' not in appyType['shownInfo']"
tal:content="python: tool.translate('ref_name')"></th>
2009-06-29 07:06:01 -05:00
<th tal:repeat="shownField appyType/shownInfo">
<tal:showHeader condition="python: objs[0].getField(shownField)">
2009-10-18 07:52:27 -05:00
<tal:titleHeader condition="python: shownField == 'title'"
content="python: tool.translate('ref_name')"/>
2009-06-29 07:06:01 -05:00
<tal:otherHeader condition="python: shownField != 'title'"
define="labelId python: objs[0].getField(shownField).widget.label_msgid"
2009-10-18 07:52:27 -05:00
content="python: tool.translate(labelId)"/>
2009-06-29 07:06:01 -05:00
</tal:showHeader>
</th>
2009-10-18 07:52:27 -05:00
<th tal:content="python: tool.translate('ref_actions')"></th>
2009-06-29 07:06:01 -05:00
</tr>
2009-12-15 14:30:43 -06:00
<tal:row repeat="obj objs">
<tr valign="top" tal:define="odd repeat/obj/odd"
tal:attributes="class python:test(odd, 'even', 'odd')">
2009-06-29 07:06:01 -05:00
<tal:comment replace="nothing">Object title, shown here if not specified somewhere
else in appyType.shownInfo.</tal:comment>
<td tal:condition="python: 'title' not in appyType['shownInfo']"><metal:showObjectTitle
2009-10-18 07:52:27 -05:00
use-macro="here/skyn/ref/macros/objectTitle"/>
2009-06-29 07:06:01 -05:00
</td>
<tal:comment replace="nothing">Additional fields that must be shown</tal:comment>
<td tal:repeat="shownField appyType/shownInfo">
<tal:showTitle condition="python: shownField == 'title'">
2009-10-18 07:52:27 -05:00
<metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle"/>
2009-06-29 07:06:01 -05:00
</tal:showTitle>
<tal:showOtherField define="appyType python: obj.getAppyType(shownField);
field python:obj.getField(shownField);
contextObj python:obj;"
condition="python: appyType and (shownField != 'title')">
<tal:showNormalField condition="python: appyType['type'] not in ('Ref', 'Computed', 'Action')">
<metal:viewField use-macro="python: obj.widget(shownField, 'view', use_label=0)"/>
</tal:showNormalField>
<tal:showRef condition="python: appyType['type'] == 'Ref'">
<tal:ref tal:define="isBack python:appyType['isBack'];
2009-10-25 15:42:08 -05:00
fieldName python: test(isBack, field.relationship, field.getName());
innerRef python:True">
2009-10-18 07:52:27 -05:00
<metal:showField use-macro="here/skyn/ref/macros/showReference" />
2009-06-29 07:06:01 -05:00
</tal:ref>
</tal:showRef>
<tal:showComputed condition="python: appyType['type'] == 'Computed'">
<tal:computed content="python: obj.getComputedValue(appyType)"/>
</tal:showComputed>
<tal:showAction condition="python: appyType['type'] == 'Action'">
2009-10-18 07:52:27 -05:00
<metal:action use-macro="here/skyn/macros/macros/showActionField" />
2009-06-29 07:06:01 -05:00
</tal:showAction>
</tal:showOtherField>
</td>
<tal:comment replace="nothing">Actions</tal:comment>
<td align="right">
2009-10-18 07:52:27 -05:00
<metal:showObjectActions use-macro="here/skyn/ref/macros/objectActions" />
2009-06-29 07:06:01 -05:00
</td>
</tr>
2009-12-15 14:30:43 -06:00
</tal:row>
2009-06-29 07:06:01 -05:00
</table>
</td></tr>
</table>
2009-10-25 15:42:08 -05:00
<tal:comment replace="nothing">Appy (bottom) navigation</tal:comment>
<metal:nav use-macro="here/skyn/macros/macros/appyNavigate"/>
2009-06-29 07:06:01 -05:00
</fieldset>
<tal:comment replace="nothing">A carriage return needed in some cases.</tal:comment>
<br tal:define="widgetDescr widgetDescr|nothing"
tal:condition="python: not widgetDescr or (widgetDescr['widgetType'] != 'group')"/>
</tal:anyNumberOfReferences>
</div>
2009-10-18 07:52:27 -05:00
<div metal:define-macro="editReference"
2009-06-29 07:06:01 -05:00
tal:define="refPortalType python:here.getAppyRefPortalType(field.getName());
appyType python:here.getAppyType(field.getName());
allBrains python:here.uid_catalog(portal_type=refPortalType);
brains python:here.callAppySelect(appyType['select'], allBrains);
2009-10-25 15:42:08 -05:00
refUids python: [o.UID() for o in here.getAppyRefs(field.getName())['objects']];
2009-06-29 07:06:01 -05:00
isMultiple python:test(appyType['multiplicity'][1]!=1, 'multiple', '');
appyFieldName python: 'appy_ref_%s' % field.getName();
inError python:test(errors.has_key(field.getName()), True, False);
2009-10-18 07:52:27 -05:00
defaultValue python: contextObj.getDefault(field.getName());
2009-06-29 07:06:01 -05:00
defaultValueUID defaultValue/UID|nothing;
2009-10-18 07:52:27 -05:00
isBeingCreated python: contextObj.portal_factory.isTemporary(contextObj) or ('/portal_factory/' in contextObj.absolute_url())"
2009-06-29 07:06:01 -05:00
tal:attributes="class python:'appyRefEdit field' + test(inError, ' error', '')">
<tal:comment replace="nothing">This macro displays the Reference widget on an "edit" page</tal:comment>
2009-10-18 07:52:27 -05:00
<label tal:attributes="for python:appyFieldName" tal:content="label"></label>
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]>0"></span><br/>
2009-06-29 07:06:01 -05:00
<div tal:condition="inError" tal:content="python: errors[field.getName()]"></div>
<select tal:define="valueIsInReq python:test(request.get(appyFieldName, None) != None, True, False)"
tal:attributes="name python:'appy_ref_%s' % field.getName();
multiple isMultiple">
<option tal:condition="not: isMultiple" value="" i18n:translate="choose_a_value"/>
<option tal:repeat="brain brains"
2009-10-18 07:52:27 -05:00
tal:content="python: tool.getReferenceLabel(brain, appyType)"
2009-06-29 07:06:01 -05:00
tal:attributes="value brain/UID;
selected python:test((valueIsInReq and (brain.UID in request.get(appyFieldName, []))) or (not valueIsInReq and ((brain.UID in refUids) or (isBeingCreated and (brain.UID==defaultValueUID)))), True, False)"/>
</select>
</div>