2009-06-29 07:06:01 -05:00
|
|
|
<div metal:define-macro="listPodTemplates" i18n:domain="<!applicationName!>" class="appyPod"
|
|
|
|
tal:define="flavour python: context.<!toolInstanceName!>.getFlavour(context);
|
|
|
|
podTemplates python: flavour.getAvailablePodTemplates(context, phase);"
|
|
|
|
tal:condition="podTemplates">
|
|
|
|
<script language="javascript">
|
|
|
|
<!--
|
|
|
|
// Function that allows to generate a meeting document containing selected items.
|
|
|
|
function generatePodDocument(contextUid, templateUid) {
|
|
|
|
var theForm = document.forms["podTemplateForm"];
|
|
|
|
theForm.objectUid.value = contextUid;
|
|
|
|
theForm.templateUid.value = templateUid;
|
|
|
|
theForm.submit();
|
|
|
|
}
|
|
|
|
-->
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Form submitted when an object needs to be generated as a document.</tal:comment>
|
|
|
|
<form name="podTemplateForm" method="post"
|
|
|
|
tal:attributes="action python: context.absolute_url() + '/generateDocument'">
|
|
|
|
<input type="hidden" name="objectUid"/>
|
|
|
|
<input type="hidden" name="templateUid"/>
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<tal:podTemplates define="maxShownTemplates python: flavour.getMaxShownTemplates(context)">
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Display templates as links if a few number of templates must be shown</tal:comment>
|
|
|
|
<span class="discreet" tal:condition="python: len(podTemplates)<=maxShownTemplates"
|
|
|
|
tal:repeat="podTemplate podTemplates">
|
|
|
|
<a style="cursor: pointer"
|
|
|
|
tal:define="podFormat podTemplate/getPodFormat"
|
|
|
|
tal:attributes="onclick python: 'javascript:generatePodDocument(\'%s\',\'%s\')' % (context.UID(), podTemplate.UID())" >
|
|
|
|
<img tal:attributes="src string: $portal_url/$podFormat.png"/>
|
|
|
|
<span tal:replace="podTemplate/Title"/>
|
|
|
|
</a>
|
|
|
|
</span>
|
|
|
|
<tal:comment replace="nothing">Display templates as a list if a lot of templates must be shown</tal:comment>
|
|
|
|
<select tal:condition="python: len(podTemplates)>maxShownTemplates">
|
|
|
|
<option value="" i18n:translate="">choose_a_doc</option>
|
|
|
|
<option tal:repeat="podTemplate podTemplates" tal:content="podTemplate/Title"
|
|
|
|
tal:attributes="onclick python: 'javascript:generatePodDocument(\'%s\',\'%s\')' % (context.UID(), podTemplate.UID())" />
|
|
|
|
</select>
|
|
|
|
</tal:podTemplates>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<metal:editString define-macro="editString" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="vocab python:field.Vocabulary(contextObj);">
|
|
|
|
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/>
|
2009-07-28 03:14:40 -05:00
|
|
|
<div class="discreet" tal:content="structure description"/>
|
2009-06-29 07:06:01 -05:00
|
|
|
<select tal:attributes="name fieldName;
|
|
|
|
id fieldName;
|
|
|
|
tabindex tabindex/next;
|
|
|
|
multiple isMultiple;
|
|
|
|
onchange python: 'javascript:updateSlaves(getMasterValue(this), \'%s\')' % appyType['id'];
|
|
|
|
class python: contextObj.getCssClasses(appyType, asSlave=False)">
|
|
|
|
<option tal:repeat="item vocab" i18n:translate=""
|
|
|
|
tal:attributes="value item;
|
|
|
|
selected python:contextObj.fieldValueSelected(fieldName, value, item)"
|
|
|
|
tal:content="python:here.translate(vocab.getMsgId(item), default=vocab.getValue(item))"/>
|
|
|
|
</select>
|
|
|
|
</metal:editString>
|
|
|
|
|
|
|
|
<metal:editBoolean define-macro="editBoolean" i18n:domain="<!applicationName!>">
|
|
|
|
<input type="checkbox"
|
|
|
|
tal:attributes="tabindex tabindex/next;
|
|
|
|
name python: fieldName + '_visible';
|
|
|
|
id fieldName;
|
|
|
|
checked python:contextObj.checkboxChecked(fieldName, value);
|
|
|
|
onClick python:'toggleCheckbox(\'%s\', \'%s_hidden\');;updateSlaves(getMasterValue(this), \'%s\')' % (fieldName, fieldName, appyType['id']);
|
|
|
|
class python: 'noborder ' + contextObj.getCssClasses(appyType, asSlave=False)"/>
|
|
|
|
<input tal:attributes="name fieldName;
|
|
|
|
id string:${fieldName}_hidden;
|
|
|
|
value python: test(contextObj.checkboxChecked(fieldName, value), 'True', 'False')"
|
|
|
|
type="hidden" />
|
|
|
|
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/>
|
2009-07-28 03:14:40 -05:00
|
|
|
<div class="discreet" tal:content="structure description"/>
|
2009-06-29 07:06:01 -05:00
|
|
|
</metal:editBoolean>
|
|
|
|
|
|
|
|
<div metal:define-macro="editField" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="fieldName field/getName;
|
|
|
|
isMultiple python:test(appyType['multiplicity'][1]!=1, 'multiple', '');
|
|
|
|
inError python:test(errors.has_key(fieldName), True, False);
|
|
|
|
value python:field.getAccessor(contextObj)();
|
|
|
|
defaultValue python: contextObj.getDefault(fieldName);
|
|
|
|
label python: contextObj.utranslate(field.widget.label_msgid, domain='<!applicationName!>');
|
|
|
|
description python: contextObj.utranslate(field.widget.description_msgid, domain='<!applicationName!>')"
|
|
|
|
tal:attributes="class python:'field ' + test(inError, ' error', '')">
|
|
|
|
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]>0"></span>
|
|
|
|
<div tal:condition="inError" tal:content="python: errors[fieldName]"></div>
|
|
|
|
<tal:stringField condition="python: appyType['type'] == 'String'">
|
|
|
|
<metal:edit use-macro="here/<!macros!>/macros/editString"/>
|
|
|
|
</tal:stringField>
|
|
|
|
<tal:booleanField condition="python: appyType['type'] == 'Boolean'">
|
|
|
|
<metal:edit use-macro="here/<!macros!>/macros/editBoolean"/>
|
|
|
|
</tal:booleanField>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showComputedField" i18n:domain="<!applicationName!>">
|
|
|
|
<span class="appyLabel" tal:condition="showLabel"
|
|
|
|
tal:content="field/widget/label_msgid" i18n:translate=""></span>
|
|
|
|
<tal:showValue define="theValue python: contextObj.getComputedValue(appyType)">
|
|
|
|
<span tal:condition="appyType/plainText" tal:replace="theValue"/>
|
|
|
|
<span tal:condition="not: appyType/plainText" tal:replace="structure theValue"/>
|
|
|
|
</tal:showValue>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showInfoField" i18n:domain="<!applicationName!>">
|
|
|
|
<span class="appyLabel" tal:content="field/widget/label_msgid" i18n:translate=""></span>
|
|
|
|
<span tal:content="field/widget/description_msgid" i18n:translate=""></span>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showActionField" i18n:domain="<!applicationName!>">
|
|
|
|
<form name="executeAppyAction" action="<!applicationName!>_do" method="POST">
|
|
|
|
<input type="hidden" name="actionType" value="appyAction"/>
|
|
|
|
<input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/>
|
|
|
|
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
|
|
|
|
<input type="submit" name="do" i18n:attributes="value"
|
|
|
|
tal:attributes="value field/widget/label_msgid"/>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showArchetypesField" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="field fieldDescr/atField|widgetDescr/atField;
|
|
|
|
appyType fieldDescr/appyType|widgetDescr/appyType;
|
|
|
|
showLabel showLabel|python:True;"
|
|
|
|
tal:attributes="class python: contextObj.getCssClasses(appyType, asSlave=True)">
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">For some fields we simply use the standard Archetypes
|
|
|
|
macro for showing it. Special Appy field types like Ref and Computed have their
|
|
|
|
corresponding Archetypes fields set as invisible, so they won't be shown by the following
|
|
|
|
tal:showField.</tal:comment>
|
|
|
|
|
|
|
|
<tal:showField define="mode python:test(isEdit, 'edit', 'view');"
|
|
|
|
tal:condition="python: test(isEdit, member.has_permission(field.write_permission, contextObj), member.has_permission(field.read_permission, contextObj))">
|
|
|
|
<tal:editField condition="isEdit">
|
|
|
|
<metal:editMacro use-macro="python:contextObj.widget(field.getName(), mode='edit', use_label=showLabel)" />
|
|
|
|
</tal:editField>
|
|
|
|
<tal:viewField tal:condition="not: isEdit">
|
|
|
|
<tal:defField>
|
|
|
|
<tal:fileField condition="python: (appyType['type'] == 'File')">
|
|
|
|
<span tal:condition="showLabel" tal:content="field/widget/label_msgid" i18n:translate=""></span>
|
|
|
|
<metal:viewField use-macro="python: contextObj.widget(field.getName(), 'view', use_label=0)"/>
|
|
|
|
</tal:fileField>
|
|
|
|
<tal:simpleField condition="python: (appyType['type'] in ('Integer', 'Float', 'Date', 'Boolean')) or (appyType['type'] == 'String' and (appyType['format'] == 0))">
|
|
|
|
<span tal:condition="showLabel" tal:content="field/widget/label_msgid" i18n:translate=""
|
|
|
|
tal:attributes="class python: 'appyLabel ' + contextObj.getCssClasses(appyType, asSlave=False);
|
|
|
|
id python: field.getAccessor(contextObj)()"></span>
|
|
|
|
<metal:viewField use-macro="python: contextObj.widget(field.getName(), 'view', use_label=0)"/>
|
|
|
|
</tal:simpleField>
|
|
|
|
<tal:formattedString condition="python: (appyType['type'] == 'String' and (appyType['format'] != 0))">
|
|
|
|
<fieldset tal:define="value python:field.getAccessor(contextObj)()">
|
|
|
|
<legend tal:condition="showLabel" i18n:translate="" tal:content="field/widget/label_msgid"></legend>
|
|
|
|
<span tal:condition="python: appyType['format'] == 1"
|
|
|
|
tal:replace="structure python: value.replace('\n', '<br>')"/>
|
|
|
|
<span tal:condition="python: appyType['format'] == 2" tal:replace="structure value"/>
|
|
|
|
</fieldset>
|
|
|
|
</tal:formattedString>
|
|
|
|
</tal:defField>
|
|
|
|
</tal:viewField>
|
|
|
|
</tal:showField>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">For other fields like Refs we use specific view/edit macros.</tal:comment>
|
|
|
|
<tal:viewRef condition="python: (not isEdit) and (appyType['type'] == 'Ref')">
|
|
|
|
<tal:ref define="isBack python:False;
|
|
|
|
fieldRel python:field.relationship;
|
|
|
|
objs python:contextObj.getAppyRefs(field.getName());
|
|
|
|
labelMsgId field/widget/label_msgid;
|
|
|
|
descrMsgId field/widget/description_msgid;
|
|
|
|
innerRef innerRef|python:False">
|
|
|
|
<metal:viewRef use-macro="here/<!applicationName!>AppyReference/macros/showReference" />
|
|
|
|
</tal:ref>
|
|
|
|
</tal:viewRef>
|
|
|
|
<tal:editRef condition="python: isEdit and (appyType['type'] == 'Ref')">
|
|
|
|
<tal:ref define="appyType fieldDescr/appyType|widgetDescr/appyType"
|
|
|
|
condition="python: appyType['link']==True">
|
|
|
|
<metal:editRef use-macro="here/<!applicationName!>AppyReference/macros/editReference" />
|
|
|
|
</tal:ref>
|
|
|
|
</tal:editRef>
|
|
|
|
<tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')">
|
|
|
|
<metal:cf use-macro="here/<!macros!>/macros/showComputedField" />
|
|
|
|
</tal:computedField>
|
|
|
|
<tal:actionField condition="python: (not isEdit) and (appyType['type'] == 'Action')">
|
|
|
|
<metal:af use-macro="here/<!macros!>/macros/showActionField" />
|
|
|
|
</tal:actionField>
|
|
|
|
<tal:masterString condition="python: isEdit and (appyType['type'] in ('String', 'Boolean')) and (appyType['slaves'])">
|
|
|
|
<metal:mf use-macro="here/<!macros!>/macros/editField" />
|
|
|
|
</tal:masterString>
|
|
|
|
<tal:infoField condition="python: (not isEdit) and (appyType['type'] == 'Info')">
|
|
|
|
<metal:af use-macro="here/<!macros!>/macros/showInfoField" />
|
|
|
|
</tal:infoField>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showBackwardField" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="isBack python:True;
|
|
|
|
appyType widgetDescr/appyType;
|
|
|
|
fieldRel widgetDescr/fieldRel;
|
|
|
|
objs python:contextObj.getBRefs(fieldRel);
|
|
|
|
labelMsgId python:'%s_%s_back' % (contextObj.meta_type, appyType['backd']['attribute']);
|
|
|
|
descrMsgId python:'';
|
|
|
|
innerRef innerRef|python:False">
|
|
|
|
<div metal:use-macro="here/<!applicationName!>AppyReference/macros/showReference" />
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<span metal:define-macro="showGroup" i18n:domain="<!applicationName!>">
|
|
|
|
<fieldset class="appyGroup">
|
|
|
|
<legend><i i18n:translate=""
|
|
|
|
tal:content="python: '%s_group_%s' % (contextObj.meta_type, widgetDescr['name'])"></i></legend>
|
|
|
|
<table tal:define="global fieldNb python:-1" width="100%">
|
|
|
|
<tr valign="top" tal:repeat="rowNb python:range(widgetDescr['rows'])">
|
|
|
|
<td tal:repeat="colNb python:range(widgetDescr['cols'])" tal:attributes="width python: str(100.0/widgetDescr['cols']) + '%'">
|
|
|
|
<tal:showField define="global fieldNb python:fieldNb+1;
|
|
|
|
hasFieldDescr python: test(fieldNb < len(widgetDescr['fields']), True, False);"
|
|
|
|
tal:condition="hasFieldDescr">
|
|
|
|
<tal:field define="fieldDescr python:widgetDescr['fields'][fieldNb]">
|
|
|
|
<tal:archetypesField condition="python: fieldDescr['widgetType'] == 'field'">
|
|
|
|
<metal:atField use-macro="here/<!macros!>/macros/showArchetypesField"/>
|
|
|
|
</tal:archetypesField>
|
|
|
|
<tal:backwardRef tal:condition="python: (not isEdit) and (fieldDescr['widgetType'] == 'backField')">
|
|
|
|
<metal:backRef use-macro="here/<!macros!>/macros/showBackwardField" />
|
|
|
|
</tal:backwardRef>
|
|
|
|
</tal:field>
|
|
|
|
</tal:showField>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</fieldset>
|
|
|
|
<br/>
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<div metal:define-macro="listFields" i18n:domain="<!applicationName!>"
|
|
|
|
tal:repeat="widgetDescr python: contextObj.getAppyFields(isEdit, pageName)">
|
|
|
|
|
|
|
|
<tal:displayArchetypesField condition="python: widgetDescr['widgetType'] == 'field'">
|
|
|
|
<tal:atField condition="python: widgetDescr['page'] == pageName">
|
|
|
|
<metal:field use-macro="here/<!macros!>/macros/showArchetypesField" />
|
|
|
|
</tal:atField>
|
|
|
|
</tal:displayArchetypesField>
|
|
|
|
|
|
|
|
<tal:displayBackwardRef condition="python: (not isEdit) and (widgetDescr['widgetType'] == 'backField')">
|
|
|
|
<tal:backRef condition="python: widgetDescr['appyType']['backd']['page'] == pageName">
|
|
|
|
<metal:field metal:use-macro="here/<!macros!>/macros/showBackwardField" />
|
|
|
|
</tal:backRef>
|
|
|
|
</tal:displayBackwardRef>
|
|
|
|
|
|
|
|
<tal:displayGroup condition="python: widgetDescr['widgetType'] == 'group'">
|
|
|
|
<tal:displayG condition="python: widgetDescr['page'] == pageName">
|
|
|
|
<metal:group metal:use-macro="here/<!macros!>/macros/showGroup" />
|
|
|
|
</tal:displayG>
|
|
|
|
</tal:displayGroup>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<span metal:define-macro="byline" i18n:domain="<!applicationName!>"
|
|
|
|
tal:condition="python: site_properties.allowAnonymousViewAbout or not isAnon"
|
|
|
|
tal:define="creator here/Creator;" class="documentByLine">
|
|
|
|
<tal:name tal:condition="creator"
|
|
|
|
tal:define="author python:context.portal_membership.getMemberInfo(creator)">
|
|
|
|
<span class="documentAuthor" i18n:domain="plone" i18n:translate="label_by_author">
|
|
|
|
by <a tal:attributes="href string:${portal_url}/author/${creator}"
|
|
|
|
tal:content="python:author and author['fullname'] or creator"
|
|
|
|
tal:omit-tag="not:author" i18n:name="author"/>
|
|
|
|
—
|
|
|
|
</span>
|
|
|
|
</tal:name>
|
|
|
|
<span class="documentModified">
|
|
|
|
<span i18n:translate="box_last_modified" i18n:domain="plone"/>
|
|
|
|
<span tal:replace="python:toLocalizedTime(here.ModificationDate(),long_format=1)"/>
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span metal:define-macro="workflowHistory" i18n:domain="<!applicationName!>" class="reviewHistory"
|
|
|
|
tal:define="history context/getWorkflowHistory" tal:condition="history">
|
|
|
|
<dl id="history" class="collapsible inline collapsedOnLoad">
|
|
|
|
<dt class="collapsibleHeader" i18n:translate="label_history" i18n:domain="plone">History</dt>
|
|
|
|
<dd class="collapsibleContent">
|
|
|
|
<table width="100%" class="listing nosort" i18n:attributes="summary summary_review_history"
|
|
|
|
tal:define="review_history python:context.portal_workflow.getInfoFor(context, 'review_history', []);
|
|
|
|
review_history python:[review for review in review_history if review.get('action','')]"
|
|
|
|
tal:condition="review_history">
|
|
|
|
<tr i18n:domain="plone">
|
|
|
|
<th i18n:translate="listingheader_action"/>
|
|
|
|
<th i18n:translate="listingheader_performed_by"/>
|
|
|
|
<th i18n:translate="listingheader_date_and_time"/>
|
|
|
|
<th i18n:translate="listingheader_comment"/>
|
|
|
|
</tr>
|
|
|
|
<metal:block tal:define="review_history python: portal.reverseList(review_history);"
|
|
|
|
tal:repeat="items review_history">
|
|
|
|
<tr tal:define="odd repeat/items/odd;
|
|
|
|
rhComments items/comments|nothing;
|
|
|
|
state items/review_state|nothing"
|
|
|
|
tal:attributes="class python:test(odd, 'even', 'odd')" tal:condition="items/action">
|
|
|
|
<td i18n:translate="" tal:content="python: context.getWorkflowLabel(items['action'])"
|
|
|
|
tal:attributes="class string:state-${state}"/>
|
|
|
|
<td tal:define="actorid python:items.get('actor');
|
|
|
|
actor python:context.portal_membership.getMemberInfo(actorid);
|
|
|
|
fullname actor/fullname|nothing;
|
|
|
|
username actor/username|nothing"
|
|
|
|
tal:content="python:fullname or username or actorid"/>
|
|
|
|
<td tal:content="python:toLocalizedTime(items['time'],long_format=True)"/>
|
|
|
|
<td> <tal:comment condition="rhComments" tal:content="rhComments"/>
|
|
|
|
<tal:noComment condition="not: rhComments" i18n:translate="no_comments" i18n:domain="plone"/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</metal:block>
|
|
|
|
</table>
|
|
|
|
</dd>
|
|
|
|
</dl>
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<div metal:define-macro="showPagePrologue" i18n:domain="<!applicationName!>">
|
|
|
|
<tal:comment replace="nothing">Global Javascript functions, used in edit and
|
|
|
|
consult views, are defined gere.</tal:comment>
|
|
|
|
|
|
|
|
<script language="javascript">
|
|
|
|
<!--
|
|
|
|
// This function turns a checkbox into a radio button... sort of
|
|
|
|
function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
|
|
|
|
vis = document.getElementById(visibleCheckbox);
|
|
|
|
hidden = document.getElementById(hiddenBoolean);
|
|
|
|
if (vis.checked) hidden.value = 'True';
|
|
|
|
else hidden.value = 'False';
|
|
|
|
}
|
|
|
|
// Returns an array of selected options in a select widget
|
|
|
|
function getMasterValue(widget) {
|
|
|
|
res = new Array();
|
|
|
|
if (widget.type == 'checkbox') {
|
|
|
|
var mv = widget.checked + '';
|
|
|
|
mv = mv.charAt(0).toUpperCase() + mv.substr(1);
|
|
|
|
res.push(mv);
|
|
|
|
}
|
|
|
|
else { // SELECT widget
|
|
|
|
for (var i=0; i < widget.options.length; i++) {
|
|
|
|
if (widget.options[i].selected) res.push(widget.options[i].value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
// Given the value(s) selected in a master field, this function updates the
|
|
|
|
// state of all corresponding slaves.
|
|
|
|
function updateSlaves(masterValues, appyTypeId) {
|
|
|
|
var slaves = cssQuery('div.slave_' + appyTypeId);
|
|
|
|
for (var i=0; i< slaves.length; i++){
|
|
|
|
slaves[i].style.display = "none";
|
|
|
|
}
|
|
|
|
for (var i=0; i < masterValues.length; i++) {
|
|
|
|
var activeSlaves = cssQuery('div.slaveValue_' + appyTypeId + '_' + masterValues[i]);
|
|
|
|
for (var j=0; j < activeSlaves.length; j++){
|
|
|
|
activeSlaves[j].style.display = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Triggers a workflow transition
|
|
|
|
function triggerTransition(transitionId) {
|
|
|
|
var theForm = document.getElementById('triggerTransitionForm');
|
|
|
|
theForm.workflow_action.value = transitionId;
|
|
|
|
theForm.submit();
|
|
|
|
}
|
|
|
|
-->
|
|
|
|
</script>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showPageHeader" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="appyPages python: context.getAppyPages(phase);
|
|
|
|
showCommonInfo python: not isEdit"
|
|
|
|
tal:condition="python: not context.portal_factory.isTemporary(context)">
|
|
|
|
|
|
|
|
<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">
|
|
|
|
<tr valign="bottom">
|
|
|
|
<tal:comment replace="nothing">Title, edit icon and state</tal:comment>
|
|
|
|
<td width="80%">
|
|
|
|
<b class="appyTitle" tal:content="title_string | here/title_or_id"></b>
|
|
|
|
<tal:comment replace="nothing">Show the phase name tied to this page</tal:comment>
|
|
|
|
<span class="discreet" tal:condition="python: phaseInfo['totalNbOfPhases']>1">−
|
|
|
|
<span i18n:translate="phase"></span>:
|
|
|
|
<span tal:define="label python:'%s_phase_%s' % (context.meta_type, phase)"
|
|
|
|
tal:content="label" i18n:translate=""></span>
|
|
|
|
</span>
|
|
|
|
<tal:comment replace="nothing">When no tabs are shown, we provide an edit icon.</tal:comment>
|
|
|
|
<img tal:define="editPageName python:test(pageName=='main', 'default', pageName)"
|
|
|
|
src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title"
|
|
|
|
style="cursor:pointer"
|
|
|
|
tal:attributes="onClick python: 'href: window.location=\'%s/<!applicationName!>_appy_edit?fieldset=%s&phase=%s\'' % (context.absolute_url(), editPageName, phase)"
|
|
|
|
tal:condition="python: (len(appyPages)==1) and member.has_permission('Modify portal content', context)"/>
|
|
|
|
</td>
|
|
|
|
<td><metal:actions use-macro="here/document_actions/macros/document_actions"/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr tal:define="descrLabel python: here.utranslate('%s_edit_descr' % here.portal_type, domain='<!applicationName!>')" tal:condition="descrLabel/strip" >
|
|
|
|
<tal:comment replace="nothing">Content type description</tal:comment>
|
|
|
|
<td colspan="2" class="discreet" tal:content="descrLabel"/>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<metal:byLine use-macro="here/<!macros!>/macros/byline"/>
|
|
|
|
<tal:showWorkflow condition="showWorkflow">
|
|
|
|
<metal:workflowHistory use-macro="here/<!macros!>/macros/workflowHistory"/>
|
|
|
|
</tal:showWorkflow>
|
|
|
|
</td>
|
|
|
|
<td valign="top"><metal:pod use-macro="here/<!macros!>/macros/listPodTemplates"/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Workflow-related information and actions</tal:comment>
|
|
|
|
<tr tal:condition="python: showWorkflow and context.getWorkflowLabel()">
|
|
|
|
<td colspan="2" class="appyWorkflow">
|
|
|
|
<table width="100%">
|
|
|
|
<tr>
|
|
|
|
<td><metal:states use-macro="here/<!macros!>/macros/states"/></td>
|
|
|
|
<td align="right"><metal:states use-macro="here/<!macros!>/macros/transitions"/></td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Tabs</tal:comment>
|
|
|
|
<ul class="contentViews appyTabs" tal:condition="python: len(appyPages)>1">
|
|
|
|
<li tal:repeat="thePage appyPages"
|
|
|
|
tal:attributes="class python:test(thePage == pageName, 'selected', 'plain')">
|
|
|
|
<tal:tab define="pageLabel python: '%s_page_%s' % (here.meta_type, thePage)">
|
|
|
|
<a i18n:translate="" tal:content="pageLabel"
|
|
|
|
tal:attributes="href python: here.absolute_url() + '/<!applicationName!>_appy_view?phase=%s&pageName=%s' % (phase, thePage)">
|
|
|
|
</a>
|
|
|
|
<img tal:define="editPageName python:test(thePage=='main', 'default', thePage)"
|
|
|
|
src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title"
|
|
|
|
style="cursor:pointer" class="appyPlusImg"
|
|
|
|
tal:attributes="onClick python: 'href: window.location=\'%s/<!applicationName!>_appy_edit?fieldset=%s&phase=%s\'' % (context.absolute_url(), editPageName, phase)"
|
|
|
|
tal:condition="python: member.has_permission('Modify portal content', context)"/>
|
|
|
|
</tal:tab>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="showPageFooter" i18n:domain="<!applicationName!>">
|
|
|
|
<script language="javascript">
|
|
|
|
<!--
|
|
|
|
// When the current page is loaded, we must set the correct state for all slave fields.
|
|
|
|
var masters = cssQuery('.appyMaster');
|
|
|
|
for (var i=0; i < masters.length; i++) {
|
|
|
|
var cssClasses = masters[i].className.split(' ');
|
|
|
|
for (var j=0; j < cssClasses.length; j++) {
|
|
|
|
if (cssClasses[j].indexOf('master_') == 0) {
|
|
|
|
var appyId = cssClasses[j].split('_')[1];
|
|
|
|
var masterValue = [];
|
|
|
|
if (masters[i].nodeName == 'SPAN'){
|
|
|
|
var idField = masters[i].id;
|
|
|
|
if (idField == '') {
|
|
|
|
masterValue.push(idField);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (idField[0] == '(') {
|
|
|
|
// There are multiple values, split it
|
|
|
|
var subValues = idField.substring(1, idField.length-1).split(',');
|
|
|
|
for (var k=0; k < subValues.length; k++){
|
|
|
|
var subValue = subValues[k].strip();
|
|
|
|
masterValue.push(subValue.substring(1, subValue.length-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { masterValue.push(masters[i].id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { masterValue = getMasterValue(masters[i]);
|
|
|
|
}
|
|
|
|
updateSlaves(masterValue, appyId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-->
|
|
|
|
</script>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div metal:define-macro="queryResult" i18n:domain="<!applicationName!>">
|
|
|
|
|
|
|
|
<script language="javascript">
|
|
|
|
<!--
|
|
|
|
function getSortValue(row, fieldName) {
|
|
|
|
// Find, from p_fieldName, the cell that is used for sorting.
|
|
|
|
var cellId = "field_" + fieldName;
|
|
|
|
var cells = row.cells;
|
|
|
|
for (var i=0; i < cells.length; i++) {
|
|
|
|
if (cells[i].id == cellId) {
|
|
|
|
// Ok we have the cell on which we must sort.
|
|
|
|
// Now get the cell content.
|
|
|
|
// If the cell contains links, content is the 1st link content
|
|
|
|
var innerLinks = cells[i].getElementsByTagName("a");
|
|
|
|
if (innerLinks.length > 0) {
|
|
|
|
return innerLinks[0].innerHTML;
|
|
|
|
} else {
|
|
|
|
return cells[i].innerHTML;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function sortRows(fieldName, ascending) {
|
|
|
|
var queryRows = cssQuery('#query_row');
|
|
|
|
// Create a wrapper for sorting
|
|
|
|
var RowWrapper = function(row, fieldName) {
|
|
|
|
this.value = getSortValue(row, fieldName);
|
|
|
|
this.cloned_node = row.cloneNode(true);
|
|
|
|
this.toString = function() {
|
|
|
|
if (this.value.toString) {
|
|
|
|
return this.value.toString();
|
|
|
|
} else {
|
|
|
|
return this.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Wrap nodes
|
|
|
|
var items = new Array();
|
|
|
|
for (var i=0; i<queryRows.length; i++) {
|
|
|
|
items.push(new RowWrapper(queryRows[i], fieldName));
|
|
|
|
}
|
|
|
|
// Sort nodes
|
|
|
|
items.sort();
|
|
|
|
if (!ascending) {
|
|
|
|
items.reverse();
|
|
|
|
}
|
|
|
|
// Reorder nodes
|
|
|
|
for (var i=0; i<items.length; i++) {
|
|
|
|
var dest = queryRows[i];
|
|
|
|
dest.parentNode.replaceChild(items[i].cloned_node, dest);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function onSort(fieldName){
|
|
|
|
// First, switch the sort arrow (up->down or down->up)
|
|
|
|
var arrow = document.getElementById("arrow_" + fieldName);
|
|
|
|
var sortAscending = (arrow.src.indexOf('arrowDown.gif') != -1);
|
|
|
|
if (sortAscending){
|
|
|
|
// Display "up" image
|
|
|
|
arrow.src = arrow.src.replace('arrowDown.gif', 'arrowUp.gif')
|
|
|
|
}
|
|
|
|
else { // Display "down" image
|
|
|
|
arrow.src = arrow.src.replace('arrowUp.gif', 'arrowDown.gif')
|
|
|
|
}
|
|
|
|
// Then, sort the rows on column "fieldName".
|
|
|
|
sortRows(fieldName, sortAscending);
|
|
|
|
}
|
|
|
|
|
|
|
|
function cellMatches(cell, searchValue) {
|
|
|
|
// This function returns true if the HTML p_cell contains p_searchValue
|
|
|
|
var innerLinks = cell.getElementsByTagName("a");
|
|
|
|
// If the cell contains links, we search within the link contents
|
|
|
|
for (var i=0; i < innerLinks.length; i++){
|
|
|
|
var linkContent = innerLinks[i].innerHTML.toLowerCase();
|
|
|
|
if (linkContent.indexOf(searchValue) != -1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we are here, we still have no match. Let's search directly within
|
|
|
|
// the cell.
|
|
|
|
var cellContent = cell.innerHTML.toLowerCase();
|
|
|
|
if (cellContent.indexOf(searchValue) != -1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function onTextEntered(fieldName) {
|
|
|
|
// Is called whenever text is entered into field named p_fieldName.
|
|
|
|
var cellId = "field_" + fieldName
|
|
|
|
var field = document.getElementById("filter_" + fieldName);
|
|
|
|
var fieldValue = field.value.toLowerCase();
|
|
|
|
if (fieldValue.length >= 3) {
|
|
|
|
// Browse all rows and check if it should be visible or not.
|
|
|
|
var queryRows = cssQuery('#query_row');
|
|
|
|
for (var i=0; i < queryRows.length; i++) {
|
|
|
|
// Find the value of the cell.
|
|
|
|
var queryCells = queryRows[i].cells;
|
|
|
|
for (var j=0; j < queryCells.length; j++) {
|
|
|
|
if (queryCells[j].id == cellId) {
|
|
|
|
if (cellMatches(queryCells[j], fieldValue)) {
|
|
|
|
queryRows[i].style.display = "";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
queryRows[i].style.display = "none";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Show all rows
|
|
|
|
var queryRows = cssQuery('#query_row');
|
|
|
|
for (var i=0; i < queryRows.length; i++) {
|
|
|
|
queryRows[i].style.display = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-->
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<table class="vertical listing" width="100%"
|
|
|
|
tal:define="fieldDescrs python: context.<!toolInstanceName!>.getResultColumns(queryResult[0].getObject(), queryName);">
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Every item in fieldDescr is a FieldDescr instance,
|
|
|
|
excepted for workflow state (which is not a field): in thi case it is simply string
|
|
|
|
"workflowState".</tal:comment>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Headers, with filters and sort arrows</tal:comment>
|
|
|
|
<tr>
|
|
|
|
<tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment>
|
2009-07-28 03:14:40 -05:00
|
|
|
<th><img tal:attributes= "src string: $portal_url/arrowDown.gif;
|
|
|
|
onClick python:'javascript:onSort(\'title\')';"
|
2009-06-29 07:06:01 -05:00
|
|
|
id="arrow_title" style="cursor:pointer"/>
|
|
|
|
<span i18n:translate="ref_name"/>
|
|
|
|
<input id="filter_title" type="text" size="10" onkeyup="javascript:onTextEntered('title')"/>
|
|
|
|
</th>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Columns corresponding to other fields</tal:comment>
|
|
|
|
<tal:columnHeader repeat="fieldDescr fieldDescrs">
|
|
|
|
<th tal:define="fieldName fieldDescr/atField/getName|string:workflow_state">
|
2009-07-28 03:14:40 -05:00
|
|
|
<img tal:attributes= "src string: $portal_url/arrowDown.gif;
|
2009-06-29 07:06:01 -05:00
|
|
|
onClick python:'javascript:onSort(\'%s\')' % fieldName;
|
|
|
|
id python: 'arrow_%s' % fieldName"
|
|
|
|
style="cursor:pointer"/>
|
|
|
|
<tal:comment replace="nothing">Display header for a "standard" field</tal:comment>
|
|
|
|
<tal:standardField condition="python: fieldName != 'workflow_state'">
|
|
|
|
<span i18n:translate="" tal:content="fieldDescr/atField/widget/label_msgid"/>
|
|
|
|
</tal:standardField>
|
|
|
|
<tal:comment replace="nothing">Display header for the workflow state</tal:comment>
|
|
|
|
<tal:workflowState condition="python: fieldName == 'workflow_state'">
|
|
|
|
<span i18n:translate="workflow_state"/>
|
|
|
|
</tal:workflowState>
|
|
|
|
<input type="text" size="10"
|
|
|
|
tal:attributes="id python: 'filter_%s' % fieldName;
|
|
|
|
onkeyup python:'javascript:onTextEntered(\'%s\')' % fieldName"/>
|
|
|
|
</th>
|
|
|
|
</tal:columnHeader>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Column "Object type", shown if we are on tab "consult all"</tal:comment>
|
|
|
|
<th tal:condition="mainTabSelected"><img
|
|
|
|
tal:attributes= "src string: $portal_url/arrowDown.gif;
|
|
|
|
onClick python:'javascript:onSort(\'root_type\')';"
|
|
|
|
id = "arrow_root_type" style="cursor:pointer"/>
|
|
|
|
<span i18n:translate="root_type"/>
|
|
|
|
<input type="text" size="10" id="filter_root_type"
|
|
|
|
tal:attributes="onkeyup python:'javascript:onTextEntered(\'root_type\')'"/>
|
|
|
|
</th>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Column "Actions"</tal:comment>
|
|
|
|
<th i18n:translate="ref_actions"></th>
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Results</tal:comment>
|
|
|
|
<tr tal:repeat="brain queryResult" id="query_row">
|
|
|
|
<tal:row define="obj brain/getObject">
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment>
|
|
|
|
<td id="field_title"><a tal:content="brain/Title"
|
|
|
|
tal:attributes="href python: obj.absolute_url()"></a></td>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Columns corresponding to other fields</tal:comment>
|
|
|
|
<tal:otherFields repeat="fieldDescr fieldDescrs">
|
|
|
|
<tal:standardField condition="python: fieldDescr != 'workflowState'">
|
2009-07-10 08:01:50 -05:00
|
|
|
<td tal:condition="fieldDescr/atField"
|
|
|
|
tal:attributes="id python:'field_%s' % fieldDescr['atField'].getName()">
|
2009-06-29 07:06:01 -05:00
|
|
|
<tal:field define="contextObj python:obj;
|
|
|
|
isEdit python:False;
|
|
|
|
showLabel python:False;
|
|
|
|
innerRef python:True"
|
|
|
|
condition="python: contextObj.showField(fieldDescr)">
|
|
|
|
<metal:field use-macro="here/<!macros!>/macros/showArchetypesField"/>
|
|
|
|
</tal:field>
|
|
|
|
</td>
|
2009-07-10 08:01:50 -05:00
|
|
|
<td tal:condition="not: fieldDescr/atField" style="color:red">Field
|
|
|
|
<span tal:replace="fieldDescr/name"/> not found.
|
|
|
|
</td>
|
2009-06-29 07:06:01 -05:00
|
|
|
</tal:standardField>
|
|
|
|
<tal:workflowState condition="python: fieldDescr == 'workflowState'">
|
|
|
|
<td id="field_workflow_state" i18n:translate="" tal:content="obj/getWorkflowLabel"></td>
|
|
|
|
</tal:workflowState>
|
|
|
|
</tal:otherFields>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Column "Object type", shown if we are on tab "consult all"</tal:comment>
|
|
|
|
<td tal:condition="mainTabSelected" tal:content="obj/portal_type"
|
|
|
|
i18n:translate="" id="field_root_type"></td>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Column "Actions"</tal:comment>
|
|
|
|
<td align="right">
|
|
|
|
<table class="no-style-table" cellpadding="0" cellspacing="0">
|
|
|
|
<tr>
|
|
|
|
<tal:comment replace="nothing">Edit the element</tal:comment>
|
|
|
|
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/edit'"
|
|
|
|
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
|
|
|
<img src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title" />
|
|
|
|
</a></td>
|
|
|
|
<tal:comment replace="nothing">Delete the element</tal:comment>
|
|
|
|
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/delete_confirmation'"
|
|
|
|
tal:condition="python: member.has_permission('Delete objects', obj)">
|
|
|
|
<img src="delete_icon.gif" title="Delete" i18n:domain="plone" i18n:attributes="title" />
|
|
|
|
</a></td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</td>
|
|
|
|
</tal:row>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<div metal:use-macro="context/batch_macros/macros/navigation" />
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<metal:phases define-macro="phases" i18n:domain="<!applicationName!>">
|
|
|
|
<tal:comment replace="nothing">This macro displays phases defined for a given content type,
|
|
|
|
only if more than one phase is defined.</tal:comment>
|
|
|
|
<table width="100%" tal:define="phases context/getAppyPhases|nothing"
|
|
|
|
tal:condition="python: phases and (len(phases)>1)" cellspacing="1" cellpadding="0">
|
|
|
|
<tal:phase repeat="phase phases">
|
|
|
|
<tr>
|
|
|
|
<td tal:define="label python:'%s_phase_%s' % (context.meta_type, phase['name']);
|
|
|
|
displayLink python: (phase['phaseStatus'] != 'Future') and ('/portal_factory' not in context.absolute_url())"
|
|
|
|
tal:attributes="class python: 'appyPhase step' + phase['phaseStatus']">
|
|
|
|
<a tal:attributes="href python: '%s?phase=%s&pageName=%s' % (context.absolute_url(), phase['name'], phase['pages'][0]);" tal:condition="displayLink"
|
|
|
|
i18n:translate="" tal:content="label"/>
|
|
|
|
<span tal:condition="not: displayLink" i18n:translate="" tal:content="label"/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr tal:condition="python: phase['name'] != phases[-1]['name']">
|
|
|
|
<td align="center"><img tal:attributes="src string: $portal_url/nextPhase.png"/></td>
|
|
|
|
</tr>
|
|
|
|
</tal:phase>
|
|
|
|
</table>
|
|
|
|
</metal:phases>
|
|
|
|
|
|
|
|
<metal:states define-macro="states" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="showAllStatesInPhase python: flavour.getAttr('showAllStatesInPhaseFor' + contextObj.meta_type);
|
|
|
|
states python: context.getAppyStates(phase, currentOnly=not showAllStatesInPhase)"
|
|
|
|
tal:condition="python: test(showAllStatesInPhase, len(states)>1, True)">
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<tal:state repeat="stateInfo states">
|
|
|
|
<td tal:attributes="class python: 'appyState step' + stateInfo['stateStatus']"
|
|
|
|
tal:content="python: context.getWorkflowLabel(stateInfo['name'])" i18n:translate="">
|
|
|
|
</td>
|
|
|
|
<td tal:condition="python: stateInfo['name'] != states[-1]['name']">
|
|
|
|
<img tal:attributes="src string: $portal_url/nextState.png"/>
|
|
|
|
</td>
|
|
|
|
</tal:state>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</metal:states>
|
|
|
|
|
|
|
|
<metal:transitions define-macro="transitions" i18n:domain="<!applicationName!>"
|
|
|
|
tal:define="transitions python: contextObj.portal_workflow.getTransitionsFor(contextObj);"
|
|
|
|
tal:condition="transitions">
|
|
|
|
<form id="triggerTransitionForm" method="post"
|
|
|
|
tal:attributes="action python: contextObj.absolute_url() + '/<!applicationName!>_do'">
|
|
|
|
<input type="hidden" name="actionType" value="triggerTransition"/>
|
|
|
|
<input type="hidden" name="workflow_action"/>
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<tal:comment replace="nothing">Input field allowing to enter a comment before triggering a transition</tal:comment>
|
|
|
|
<td tal:define="showCommentsField python:flavour.getAttr('showWorkflowCommentFieldFor'+context.meta_type)"
|
|
|
|
align="right" tal:condition="showCommentsField">
|
|
|
|
<span i18n:translate="workflow_comment" class="discreet"></span>
|
|
|
|
<input type="text" id="comment" name="comment" size="35"/>
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<tal:comment replace="nothing">Buttons for triggering transitions</tal:comment>
|
|
|
|
<td align="right" tal:repeat="transition transitions">
|
|
|
|
<input type="button" i18n:attributes="value" class="context"
|
|
|
|
tal:attributes="value python: transition['name'];
|
|
|
|
onClick python: 'javascript: triggerTransition(\'%s\')' % transition['id']"/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</form>
|
|
|
|
</metal:transitions>
|