Fixed bug #394258 and added a new skin directly within Appy, such that every generated product does not need to include copies of Appy images and web pages.
|  | @ -1,228 +0,0 @@ | |||
| <tal:comment replace="nothing"> We begin with some sub-macros used within | ||||
|   macro "showReference" defined below.</tal:comment> | ||||
| 
 | ||||
| <metal:objectTitle define-macro="objectTitle" i18n:domain="<!applicationName!>"> | ||||
|   <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.</tal:comment> | ||||
|   <a tal:define="viewUrl obj/absolute_url; | ||||
|                  fullUrl python: test(isBack, viewUrl + '/?pageName=%s&phase=%s' % (appyType['page'], appyType['phase']), viewUrl)" | ||||
|      tal:attributes="href fullUrl" tal:content="obj/Title"></a> | ||||
| </metal:objectTitle> | ||||
| 
 | ||||
| <metal:objectActions define-macro="objectActions" i18n:domain="<!applicationName!>"> | ||||
|   <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">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="label_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="label_remove" i18n:domain="plone" i18n:attributes="title" /> | ||||
|     </a></td> | ||||
|     <tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment> | ||||
|     <td class="noPadding" tal:condition="python: len(objs)>1"> | ||||
|       <form tal:condition="python: member.has_permission('Modify portal content', obj)" | ||||
|             tal:attributes="action python: contextObj.absolute_url() + '/<!applicationName!>_do'" | ||||
|             tal:define="objectIndex python:contextObj.getAppyRefIndex(field.getName(), obj)"> | ||||
|         <input type="hidden" name="actionType" value="changeRefOrder"/> | ||||
|         <input type="hidden" name="fieldName" tal:attributes="value field/getName"/> | ||||
|         <input type="hidden" name="objectUid" tal:attributes="value obj/UID"/> | ||||
|         <tal:comment replace="nothing">Arrow up</tal:comment> | ||||
|         <span tal:condition="python: objectIndex > 0"> | ||||
|         <input type="image" name="moveUp" tal:attributes="src python: contextObj.absolute_url() + '/arrowUp.png'" | ||||
|                 title="move_up" i18n:attributes="title" class="imageInput"/> | ||||
|         </span> | ||||
|         <tal:comment replace="nothing">Arrow down</tal:comment> | ||||
|         <span tal:condition="python: objectIndex < (len(objs)-1)"> | ||||
|         <input type="image" name="moveDown" tal:attributes="src python: contextObj.absolute_url() + '/arrowDown.png'" | ||||
|                 title="move_down" i18n:attributes="title" class="imageInput"/> | ||||
|         </span> | ||||
|       </form> | ||||
|     </td> | ||||
|     </tr> | ||||
|   </table> | ||||
| </metal:objectActions> | ||||
| 
 | ||||
| <metal:plusIcon define-macro="plusIcon" i18n:domain="<!applicationName!>"> | ||||
|     <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 src="plus.png" i18n:attributes="title" style="cursor:pointer" | ||||
|        tal:condition="showPlusIcon" title="add_ref" | ||||
|        tal:attributes="onClick python: 'href: window.location=\'%s/createAppyObject?initiator=%s&field=%s&type_name=%s\'' % (folder.absolute_url(), contextObj.UID(), field.getName(), linkedPortalType)"/> | ||||
| </metal:plusIcon> | ||||
| 
 | ||||
| <div metal:define-macro="showReference" i18n:domain="<!applicationName!>" | ||||
|      tal:define="tool python: contextObj.<!toolInstanceName!>; | ||||
|                  flavour python:tool.getFlavour(contextObj); | ||||
|                  folder python: test(contextObj.isPrincipiaFolderish, contextObj, contextObj.getParentNode()); | ||||
|                  linkedPortalType python:flavour.getPortalType(appyType['klass']); | ||||
|                  addPermission python: '<!applicationName!>: Add %s' % linkedPortalType; | ||||
|                  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); | ||||
|                  atMostOneRef python: (multiplicity[1] == 1) and (len(objs)<=1)"> | ||||
| 
 | ||||
|   <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"> | ||||
|       <td><span class="appyLabel" tal:condition="not: innerRef" | ||||
|                 i18n:translate="" tal:content="labelMsgId"></span></td> | ||||
| 
 | ||||
|       <tal:comment replace="nothing">If there is no object...</tal:comment> | ||||
|       <tal:noObject condition="not:objs"> | ||||
|         <td i18n:translate="">no_ref</td> | ||||
|         <td><metal:plusIcon use-macro="here/<!applicationName!>AppyReference/macros/plusIcon"/></td> | ||||
|       </tal:noObject> | ||||
| 
 | ||||
|       <tal:comment replace="nothing">If there is an object...</tal:comment> | ||||
|       <tal:objectIsPresent condition="python: len(objs) == 1"> | ||||
|         <tal:obj define="obj python:objs[0]"> | ||||
|           <td><metal:showObjectTitle use-macro="here/<!applicationName!>AppyReference/macros/objectTitle" /></td> | ||||
|           <td tal:condition="not: isBack"> | ||||
|             <metal:showObjectActions use-macro="here/<!applicationName!>AppyReference/macros/objectActions" /> | ||||
|           </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"> | ||||
|         <span tal:condition="not: innerRef" i18n:translate="" tal:content="labelMsgId"/> | ||||
|         <metal:plusIcon use-macro="here/<!applicationName!>AppyReference/macros/plusIcon"/> | ||||
|       </legend> | ||||
| 
 | ||||
|       <tal:comment replace="nothing">Object description</tal:comment> | ||||
|       <p tal:define="descr python:contextObj.utranslate(descrMsgId, domain='<!applicationName!>')" | ||||
|          tal:condition="python: not innerRef and descr.strip()" tal:content="descr" class="discreet" ></p> | ||||
| 
 | ||||
|       <tal:comment replace="nothing">No object is present</tal:comment> | ||||
|       <p tal:condition="not:objs" i18n:translate="">no_ref</p> | ||||
| 
 | ||||
|       <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"> | ||||
|             <td><metal:showObjectTitle use-macro="here/<!applicationName!>AppyReference/macros/objectTitle" /> | ||||
|             </td> | ||||
|           </tr> | ||||
|         </table> | ||||
| 
 | ||||
|         <tal:comment replace="nothing">Show forward reference(s)</tal:comment> | ||||
|         <table tal:attributes="class python:test(innerRef, '', 'vertical listing'); | ||||
|                                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"> | ||||
|             <th tal:condition="python: 'title' not in appyType['shownInfo']" i18n:translate="ref_name"></th> | ||||
|             <th tal:repeat="shownField appyType/shownInfo"> | ||||
|               <tal:showHeader condition="python: objs[0].getField(shownField)"> | ||||
|                 <tal:titleHeader condition="python: shownField == 'title'" i18n:translate="ref_name"/> | ||||
|                 <tal:otherHeader condition="python: shownField != 'title'" | ||||
|                                  define="labelId python: objs[0].getField(shownField).widget.label_msgid" | ||||
|                                  content="labelId" i18n:translate=""/> | ||||
|               </tal:showHeader> | ||||
|             </th> | ||||
|             <th i18n:translate="ref_actions"></th> | ||||
|           </tr> | ||||
|           <tr tal:repeat="obj objs" valign="top"> | ||||
|             <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 | ||||
|                 use-macro="here/<!applicationName!>AppyReference/macros/objectTitle"/>  | ||||
|             </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'"> | ||||
|                 <metal:showObjectTitle use-macro="here/<!applicationName!>AppyReference/macros/objectTitle"/> | ||||
|               </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']; | ||||
|                                         fieldRel python:field.relationship; | ||||
|                                         objs python:contextObj.getAppyRefs(field.getName()); | ||||
|                                         labelMsgId field/widget/label_msgid; | ||||
|                                         descrMsgId field/widget/description_msgid; | ||||
|                                         innerRef python:True"> | ||||
|                     <metal:showField use-macro="here/<!applicationName!>AppyReference/macros/showReference" /> | ||||
|                   </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'"> | ||||
|                   <metal:action use-macro="here/<!macros!>/macros/showActionField" /> | ||||
|                 </tal:showAction> | ||||
|               </tal:showOtherField>  | ||||
|             </td> | ||||
|             <tal:comment replace="nothing">Actions</tal:comment> | ||||
|             <td align="right"> | ||||
|               <metal:showObjectActions use-macro="here/<!applicationName!>AppyReference/macros/objectActions" /> | ||||
|             </td> | ||||
|           </tr> | ||||
|         </table> | ||||
| 
 | ||||
|         </td></tr> | ||||
|       </table> | ||||
|     </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> | ||||
| 
 | ||||
| <div metal:define-macro="editReference" i18n:domain="<!applicationName!>" | ||||
|      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); | ||||
|                  refUids python: [o.UID() for o in here.getAppyRefs(field.getName())]; | ||||
|                  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); | ||||
|                  defaultValue python: here.getDefault(field.getName()); | ||||
|                  defaultValueUID defaultValue/UID|nothing; | ||||
|                  isBeingCreated python: context.portal_factory.isTemporary(context) or ('/portal_factory/' in context.absolute_url())" | ||||
|      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> | ||||
| 
 | ||||
|   <label tal:attributes="for python:appyFieldName" | ||||
|          i18n:translate="" tal:content="field/widget/label_msgid"></label> | ||||
|   <span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]>0"></span><br/> | ||||
|   <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" | ||||
|         tal:content="python: here.<!toolInstanceName!>.getReferenceLabel(brain, appyType)" | ||||
|         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> | ||||
|  | @ -20,8 +20,8 @@ class <!genClassName!>(<!parents!>): | |||
|     allowed_content_types = [] | ||||
|     filter_content_types = 0 | ||||
|     global_allow = 1 | ||||
|     immediate_view = '<!applicationName!>_appy_view' | ||||
|     default_view = '<!applicationName!>_appy_view' | ||||
|     immediate_view = 'skyn/view' | ||||
|     default_view = 'skyn/view' | ||||
|     suppl_views = () | ||||
|     typeDescription = '<!genClassName!>' | ||||
|     typeDescMsgId = '<!genClassName!>_edit_descr' | ||||
|  |  | |||
|  | @ -22,8 +22,8 @@ class <!flavourName!>(OrderedBaseFolder, FlavourMixin): | |||
|     filter_content_types = 0 | ||||
|     global_allow = 1 | ||||
|     #content_icon = '<!flavourName!>.gif' | ||||
|     immediate_view = '<!applicationName!>_appy_view' | ||||
|     default_view = '<!applicationName!>_appy_view' | ||||
|     immediate_view = 'skyn/view' | ||||
|     default_view = 'skyn/view' | ||||
|     suppl_views = () | ||||
|     typeDescription = "<!flavourName!>" | ||||
|     typeDescMsgId = '<!flavourName!>_edit_descr' | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| <!codeHeader!> | ||||
| from zExceptions import BadRequest | ||||
| from Products.CMFCore.DirectoryView import manage_addDirectoryView | ||||
| from Products.ExternalMethod.ExternalMethod import ExternalMethod | ||||
| from Products.Archetypes.Extensions.utils import installTypes | ||||
| from Products.Archetypes.Extensions.utils import install_subskin | ||||
|  |  | |||
|  | @ -1,769 +0,0 @@ | |||
| <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"/> | ||||
|   <div class="discreet" tal:content="structure description"/> | ||||
|   <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"/> | ||||
|   <div class="discreet" tal:content="structure description"/> | ||||
| </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> | ||||
|       <th><img tal:attributes= "src string: $portal_url/arrowDown.gif; | ||||
|                                 onClick python:'javascript:onSort(\'title\')';" | ||||
|                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"> | ||||
|         <img tal:attributes= "src string: $portal_url/arrowDown.gif; | ||||
|                               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'"> | ||||
|           <td tal:condition="fieldDescr/atField" | ||||
|               tal:attributes="id python:'field_%s' % fieldDescr['atField'].getName()"> | ||||
|             <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> | ||||
|           <td tal:condition="not: fieldDescr/atField" style="color:red">Field | ||||
|             <span tal:replace="fieldDescr/name"/> not found. | ||||
|           </td> | ||||
|         </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> | ||||
|  | @ -21,8 +21,8 @@ class <!applicationName!>PodTemplate(BaseContent, PodTemplateMixin): | |||
|     filter_content_types = 0 | ||||
|     global_allow = 1 | ||||
|     #content_icon = '<!applicationName!>PodTemplate.gif' | ||||
|     immediate_view = '<!applicationName!>_appy_view' | ||||
|     default_view = '<!applicationName!>_appy_view' | ||||
|     immediate_view = 'skyn/view' | ||||
|     default_view = 'skyn/view' | ||||
|     suppl_views = () | ||||
|     typeDescription = "<!applicationName!>PodTemplate" | ||||
|     typeDescMsgId = '<!applicationName!>_edit_descr' | ||||
|  |  | |||
|  | @ -1,45 +1,16 @@ | |||
| <html xmlns:tal="http://xml.zope.org/namespaces/tal" | ||||
|       xmlns:metal="http://xml.zope.org/namespaces/metal" | ||||
|       i18n:domain="<!applicationName!>"> | ||||
| <body> | ||||
| 
 | ||||
| <div metal:define-macro="portlet" | ||||
|      tal:define="tool python: context.<!toolInstanceName!>" | ||||
|      tal:condition="tool/showPortlet"> | ||||
| 
 | ||||
|   <metal:block metal:use-macro="here/global_defines/macros/defines" /> | ||||
| 
 | ||||
|   <dl class="portlet" | ||||
|       tal:define="rootClasses python:[<!rootClasses!>]; | ||||
|                   appFolder tool/getAppFolder"> | ||||
| 
 | ||||
|     <tal:comment replace="nothing">Portlet title, with link to tool.</tal:comment> | ||||
|     <dt class="portletHeader"> | ||||
|       <span i18n:translate="" tal:content="python: '<!applicationName!>'"> | ||||
|       </span>  | ||||
|       <img i18n:attributes="title" style="cursor:pointer" title="<!applicationName!>Tool" | ||||
|            tal:condition="python: member.has_role('Manager')" | ||||
|            tal:attributes="onClick python: 'href: window.location=\'%s/\'' % tool.absolute_url(); | ||||
|                            src python: here.<!toolInstanceName!>.absolute_url() + '/appyConfig.gif'"/> | ||||
|     </dt> | ||||
| 
 | ||||
|     <tal:comment replace="nothing">Links to flavours</tal:comment> | ||||
|     <dt class="portletAppyItem" tal:repeat="flavourInfo tool/getFlavoursInfo"> | ||||
|         <a tal:define="flavourNumber flavourInfo/number; | ||||
|                        rootTypes python: test(flavourNumber==1, rootClasses, ['%s_%s' % (rc, flavourNumber) for rc in rootClasses]); | ||||
|                        rootClassesQuery python:','.join(rootTypes)" | ||||
|          tal:content="flavourInfo/title" | ||||
|          i18n:translate="" title="query_consult_all" i18n:attributes="title" | ||||
|          tal:attributes="href python:'%s/<!queryName!>?query=%s&flavourNumber=%d' % (appFolder.absolute_url(), rootClassesQuery, flavourNumber)"></a> | ||||
|     </dt> | ||||
| 
 | ||||
|     <dt class="portletAppyItem" tal:condition="python: context.meta_type in rootClasses"> | ||||
|         <metal:phases use-macro="here/<!macros!>/macros/phases"/> | ||||
|     </dt> | ||||
| 
 | ||||
|   </dl> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
| </body> | ||||
|   <body> | ||||
|     <div metal:define-macro="portlet" | ||||
|          tal:define="tool python: context.<!toolInstanceName!>" | ||||
|          tal:condition="tool/showPortlet"> | ||||
|       <metal:block metal:use-macro="here/global_defines/macros/defines" /> | ||||
|       <dl tal:define="rootClasses tool/getRootClasses; | ||||
|                       appName string:<!applicationName!>; | ||||
|                       appFolder tool/getAppFolder" class="portlet"> | ||||
|         <metal:content use-macro="here/skyn/macros/macros/portletContent"/> | ||||
|       </dl> | ||||
|     </div> | ||||
|   </body> | ||||
| </html> | ||||
|  |  | |||
|  | @ -1,63 +0,0 @@ | |||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" | ||||
|       metal:use-macro="here/main_template/macros/master" | ||||
|       i18n:domain="<!applicationName!>"> | ||||
| 
 | ||||
| <!-- This page presents results of queries --> | ||||
| <body> | ||||
|     <div metal:fill-slot="top_slot"> | ||||
|       <metal:block metal:use-macro="here/global_defines/macros/defines" /> | ||||
|       <div tal:define="dummy python:request.set('disable_border', 1)" /> | ||||
|     </div> | ||||
| 
 | ||||
|     <div metal:fill-slot="main" | ||||
|          tal:define="tool python: context.<!toolInstanceName!>; | ||||
|                      queryName python:context.REQUEST.get('query'); | ||||
|                      flavourNumber python:context.REQUEST.get('flavourNumber'); | ||||
|                      rootClasses python:[<!rootClasses!>]; | ||||
|                      rootTypes python: test(flavourNumber=='1', rootClasses, ['%s_%s' % (rc, flavourNumber) for rc in rootClasses]); | ||||
|                      rootClassesQuery python:','.join(rootClasses); | ||||
|                      mainTabSelected python: queryName.find(',') != -1; | ||||
|                      appFolder tool/getAppFolder"> | ||||
| 
 | ||||
|       <span tal:condition="python: queryName and (queryName != 'none')"> | ||||
|         <span tal:define="queryResult python: context.<!toolInstanceName!>.executeQuery(queryName, int(flavourNumber)); | ||||
|                           batch queryResult"> | ||||
| 
 | ||||
|         <!-- Tabs --> | ||||
|         <ul class="contentViews appyTabs"> | ||||
| 
 | ||||
|           <!-- Tab "All objects" --> | ||||
|           <li tal:define="selected python:mainTabSelected" | ||||
|               tal:attributes="class python:test(selected, 'selected', 'plain')" | ||||
|               tal:condition="python: len(rootClasses)>1"> | ||||
| 
 | ||||
|             <a tal:attributes="href python: '%s/<!queryName!>?query=%s&flavourNumber=%s' % (appFolder.absolute_url(), rootClassesQuery, flavourNumber)" | ||||
|                i18n:translate="">query_consult_all</a> | ||||
|           </li> | ||||
|           <!-- One tab for each root content type --> | ||||
|           <tal:tab repeat="rootContentType rootTypes"> | ||||
|             <li tal:define="selected python:queryName == rootContentType" | ||||
|                 tal:attributes="class python:test(selected, 'selected', 'plain')"> | ||||
|               <a i18n:translate="" tal:content="rootContentType" | ||||
|                  tal:attributes="href python: '%s/<!queryName!>?query=%s&flavourNumber=%s' % (appFolder.absolute_url(), rootContentType, flavourNumber)"/> | ||||
|               <img i18n:attributes="title" style="cursor:pointer" title="query_create" class="appyPlusImg" | ||||
|                    tal:define="addPermission python: '<!applicationName!>: Add %s' % rootContentType" | ||||
|                    tal:attributes="onClick python: 'href: window.location=\'%s/createObject?type_name=%s\'' % (appFolder.absolute_url(), rootContentType); | ||||
|                     src python: here.<!toolInstanceName!>.absolute_url() + '/plus.png'" | ||||
|                    tal:condition="python: member.has_permission(addPermission, appFolder)"/> | ||||
|             </li> | ||||
|           </tal:tab> | ||||
|         </ul> | ||||
|         <br/> | ||||
| 
 | ||||
|         <!-- Query result --> | ||||
|         <span tal:condition="queryResult"> | ||||
|           <span metal:use-macro="here/<!macros!>/macros/queryResult"></span> | ||||
|         </span> | ||||
|         <span tal:condition="not: queryResult" | ||||
|               i18n:translate="query_no_result">No result.</span> | ||||
|         </span> | ||||
|       </span> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | @ -52,14 +52,14 @@ | |||
| /* stepxx classes are used for displaying status of a phase or state. */ | ||||
| .stepDone { | ||||
|   background-color: #cde2a7; | ||||
|   background-image: url(&dtml-portal_url;/done.png); | ||||
|   background-image: url(&dtml-portal_url;/skyn/done.png); | ||||
|   background-repeat: no-repeat; | ||||
|   background-position: center left; | ||||
| } | ||||
| 
 | ||||
| .stepCurrent { | ||||
|   background-color: #ffce7b; | ||||
|   background-image: url(&dtml-portal_url;/current.png); | ||||
|   background-image: url(&dtml-portal_url;/skyn/current.png); | ||||
|   background-repeat: no-repeat; | ||||
|   background-position: center left; | ||||
| } | ||||
|  |  | |||
|  | @ -24,8 +24,8 @@ class <!toolName!>(UniqueObject, OrderedBaseFolder, ToolMixin): | |||
|     filter_content_types = 0 | ||||
|     global_allow = 0 | ||||
|     #content_icon = '<!toolName!>.gif' | ||||
|     immediate_view = '<!applicationName!>_appy_view' | ||||
|     default_view = '<!applicationName!>_appy_view' | ||||
|     immediate_view = 'skyn/view' | ||||
|     default_view = 'skyn/view' | ||||
|     suppl_views = () | ||||
|     typeDescription = "<!toolName!>" | ||||
|     typeDescMsgId = '<!toolName!>_edit_descr' | ||||
|  | @ -35,7 +35,7 @@ class <!toolName!>(UniqueObject, OrderedBaseFolder, ToolMixin): | |||
|     schema = fullSchema | ||||
|     schema["id"].widget.visible = False | ||||
|     schema["title"].widget.visible = False | ||||
|     # When browsing into the tool, the 'configure' portlet should be dislayed. | ||||
|     # When browsing into the tool, the 'configure' portlet should be displayed. | ||||
|     left_slots = ['here/portlet_prefs/macros/portlet'] | ||||
|     right_slots = [] | ||||
|     for elem in dir(ToolMixin): | ||||
|  |  | |||
| Before Width: | Height: | Size: 899 B | 
|  | @ -1,160 +0,0 @@ | |||
| <tal:block metal:define-macro="master" | ||||
|            define="errors options/state/getErrors | nothing; | ||||
|                    Iterator python:modules['Products.Archetypes'].IndexIterator; | ||||
|                    schematas here/Schemata; | ||||
|                    fieldsets python:[key for key in schematas.keys() if (key != 'metadata') and (schematas[key].editableFields(here, visible_only=True))]; | ||||
|                    default_fieldset python:(not schematas or schematas.has_key('default')) and 'default' or fieldsets[0]; | ||||
|                    fieldset request/fieldset|options/fieldset|default_fieldset; | ||||
|                    fields python:schematas[fieldset].editableFields(here); | ||||
|                    dummy python:here.at_isEditable(fields); | ||||
|                    portal_type python:here.getPortalTypeName().lower().replace(' ', '_'); | ||||
|                    type_name here/getPortalTypeName|here/archetype_name; | ||||
|                    lockable python:hasattr(here, 'wl_isLocked'); | ||||
|                    isLocked python:lockable and here.wl_isLocked(); | ||||
|                    tabindex tabindex|python:Iterator(pos=7000); | ||||
|                    isEdit python:True; | ||||
|                    contextObj python:context; | ||||
|                    css python:here.getUniqueWidgetAttr(fields, 'helper_css'); | ||||
|                    js python:here.getUniqueWidgetAttr(fields, 'helper_js'); | ||||
|                    phaseInfo python: context.getAppyPhases(fieldset=fieldset, forPlone=True); | ||||
|                    phase request/phase|phaseInfo/name; | ||||
|                    pageName python: context.getAppyPage(isEdit, phaseInfo);"> | ||||
| 
 | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" | ||||
|       xmlns:tal="http://xml.zope.org/namespaces/tal" | ||||
|       xmlns:metal="http://xml.zope.org/namespaces/metal" | ||||
|       xmlns:i18n="http://xml.zope.org/namespaces/i18n" | ||||
|       metal:use-macro="here/main_template/macros/master"> | ||||
| 
 | ||||
|   <!-- Disable the Standard Plone green tab --> | ||||
|   <div metal:fill-slot="top_slot"> | ||||
|     <metal:block metal:use-macro="here/global_defines/macros/defines" /> | ||||
|     <div tal:define="dummy python:request.set('disable_border', 1)" /> | ||||
|   </div> | ||||
| 
 | ||||
|   <!-- Archetypes stuff for managing Javascript and CSS. If I remove this stuff, | ||||
|        Javascript popup for dates does not work anyore --> | ||||
|   <metal:javascript_head fill-slot="javascript_head_slot"> | ||||
|     <tal:block define="macro here/archetypes_custom_js/macros/javascript_head | nothing" | ||||
|                condition="macro"> | ||||
|       <metal:block use-macro="macro" /> | ||||
|     </tal:block> | ||||
|     <tal:js condition="js" repeat="item js"> | ||||
|       <script type="text/javascript" charset="iso-8859-1" | ||||
|               tal:condition="python:exists('portal/%s' % item)" | ||||
|               tal:attributes="src string:$portal_url/$item"> | ||||
|       </script> | ||||
|     </tal:js> | ||||
|     <tal:block define="macro edit_macros/javascript_head | nothing" condition="macro"> | ||||
|       <metal:block use-macro="macro" /> | ||||
|     </tal:block> | ||||
|   </metal:javascript_head> | ||||
| 
 | ||||
|   <metal:css fill-slot="css_slot"> | ||||
|     <tal:css condition="css" repeat="item css"> | ||||
|       <style type="text/css" media="all" | ||||
|              tal:condition="python:exists('portal/%s' % item)" | ||||
|              tal:content="structure string:<!-- @import url($portal_url/$item); -->"> | ||||
|       </style> | ||||
|     </tal:css> | ||||
|     <tal:block define="macro edit_macros/css | nothing" condition="macro"> | ||||
|       <metal:block use-macro="macro" /> | ||||
|     </tal:block> | ||||
|   </metal:css> | ||||
| 
 | ||||
|   <body> | ||||
|     <metal:fill fill-slot="main"> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/showPagePrologue"/> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/showPageHeader"/> | ||||
| 
 | ||||
|       <form name="edit_form" method="post" enctype="multipart/form-data" | ||||
|             class="enableUnloadProtection atBaseEditForm" | ||||
|             tal:attributes="action python:here.absolute_url()+'/'+template.id; | ||||
|                             id string:${portal_type}-base-edit"> | ||||
| 
 | ||||
|         <div metal:use-macro="here/<!macros!>/macros/listFields" /> | ||||
| 
 | ||||
|         <div class="formControls"> | ||||
|           <input type="hidden" name="fieldset" tal:attributes="value fieldset"/> | ||||
|           <input type="hidden" name="form.submitted" value="1"/> | ||||
|           <input type="hidden" name="add_reference.field:record" value=""/> | ||||
|           <input type="hidden" name="add_reference.type:record" value=""/> | ||||
|           <input type="hidden" name="add_reference.destination:record" value=""/> | ||||
| 
 | ||||
|           <tal:env define="env request/controller_state/kwargs"> | ||||
|             <tal:loop repeat="varname python:('reference_source_url', 'reference_source_field', 'reference_source_fieldset')"> | ||||
|              <tal:reference define="items python:env.get(varname, request.get(varname))" | ||||
|                            condition="items"> | ||||
|               <input tal:repeat="item items" type="hidden" | ||||
|                      tal:attributes="value item; | ||||
|                                      name string:form_env.${varname}:list:record"/> | ||||
|              </tal:reference> | ||||
|             </tal:loop> | ||||
|           </tal:env> | ||||
| 
 | ||||
|           <tal:comment replace="nothing">Turn 'persistent_' variables from controller_state persistent | ||||
|           </tal:comment> | ||||
|           <tal:env repeat="env request/controller_state/kwargs/items"> | ||||
|             <input type="hidden" | ||||
|                    tal:define="key python:env[0]; | ||||
|                                value python:env[1]" | ||||
|                    tal:condition="python:key.startswith('persistent_')" | ||||
|                    tal:attributes="name string:form_env.${key}:record; | ||||
|                                    value value"/> | ||||
|           </tal:env> | ||||
| 
 | ||||
|           <tal:comment replace="nothing">Turn 'persistent_' variables from forms (GET/POST) persistent | ||||
|           </tal:comment> | ||||
|           <tal:env repeat="env request/form"> | ||||
|             <input type="hidden" | ||||
|                      tal:define="key env; | ||||
|                                  value request/?env" | ||||
|                      tal:condition="python:key.startswith('persistent_')" | ||||
|                      tal:attributes="name string:form_env.${key}:record; | ||||
|                                      value value"/> | ||||
|           </tal:env> | ||||
| 
 | ||||
|           <tal:comment replace="nothing">Store referrer to remember where to go back | ||||
|           </tal:comment> | ||||
|           <input type="hidden" name="last_referer" | ||||
|                  tal:define="last_referer python:here.session_restore_value('HTTP_REFERER', request.form.get('last_referer', request.get('HTTP_REFERER')))" | ||||
|                  tal:attributes="value python:(last_referer and '%s/%s' % (here.absolute_url(), template.id) not in last_referer) and last_referer or (here.getParentNode() and here.getParentNode().absolute_url())"/> | ||||
| 
 | ||||
|             <tal:comment replace="nothing">Buttons (Previous, Next, Save, etc)</tal:comment> | ||||
|             <metal:block define-slot="buttons" | ||||
|                          tal:define="pages phaseInfo/pages; | ||||
|                                      pageIndex python:pages.index(fieldset); | ||||
|                                      numberOfPages python:len(pages)"> | ||||
| 
 | ||||
|               <tal:previousButton condition="python: pageIndex > 0"> | ||||
|                 <input class="context" type="submit" name="form_previous" | ||||
|                        i18n:attributes="value label_previous;" i18n:domain="plone" | ||||
|                        tal:attributes="tabindex tabindex/next; | ||||
|                                        disabled python:test(isLocked, 'disabled', None);"/> | ||||
|                 <input type="hidden" name="previousPage" tal:attributes="value python: pages[pageIndex-1]"/> | ||||
|               </tal:previousButton> | ||||
|               <tal:nextButton condition="python: pageIndex < numberOfPages - 1"> | ||||
|                 <input class="context" type="submit" name="form_next" value="Next" | ||||
|                        i18n:attributes="value label_next;" i18n:domain="plone" | ||||
|                        tal:attributes="tabindex tabindex/next; | ||||
|                                        disabled python:test(isLocked, 'disabled', None);"/> | ||||
|                 <input type="hidden" name="nextPage" tal:attributes="value python: pages[pageIndex+1]"/> | ||||
|               </tal:nextButton> | ||||
|               <input class="context" type="submit" name="form_submit" | ||||
|                      i18n:attributes="value label_save;" i18n:domain="plone" | ||||
|                      tal:attributes="tabindex tabindex/next; | ||||
|                                      disabled python:test(isLocked, 'disabled', None);"/> | ||||
|               <input class="standalone" type="submit" name="form.button.cancel" | ||||
|                      i18n:attributes="value label_cancel;" i18n:domain="plone" | ||||
|                      tal:attributes="tabindex tabindex/next"/> | ||||
|             </metal:block> | ||||
|           </div> | ||||
| 
 | ||||
|       </form> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/showPageFooter"/> | ||||
|     </metal:fill> | ||||
|   </body> | ||||
| 
 | ||||
| </html> | ||||
| 
 | ||||
| </tal:block> | ||||
|  | @ -1,13 +0,0 @@ | |||
| [default] | ||||
| title = Edit | ||||
| 
 | ||||
| [validators] | ||||
| validators = validate_base | ||||
| validators..form_add = | ||||
| validators..cancel = | ||||
| 
 | ||||
| [actions] | ||||
| action.success = traverse_to:string:content_edit | ||||
| action.success..form_add = traverse_to:string:add_reference | ||||
| action.success..cancel = traverse_to:string:go_back | ||||
| action.failure = traverse_to_action:string:edit | ||||
|  | @ -1,35 +0,0 @@ | |||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" | ||||
|       i18n:domain="<!applicationName!>" | ||||
|       lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" | ||||
|       xmlns:metal="http://xml.zope.org/namespaces/metal" | ||||
|       xmlns:i18n="http://xml.zope.org/namespaces/i18n" | ||||
|       metal:use-macro="here/main_template/macros/master"> | ||||
| 
 | ||||
|   <head><title></title></head> | ||||
| 
 | ||||
|   <tal:comment replace="nothing">Disable standard Plone green tabs</tal:comment> | ||||
|   <div metal:fill-slot="top_slot"> | ||||
|     <metal:block metal:use-macro="here/global_defines/macros/defines" /> | ||||
|     <div tal:define="dummy python:request.set('disable_border', 1)" /> | ||||
|   </div> | ||||
| 
 | ||||
|   <tal:comment replace="nothing">Fill main slot of Plone main_template</tal:comment> | ||||
|   <body> | ||||
|     <metal:fill fill-slot="main" | ||||
|       tal:define="contextObj python:context; | ||||
|                   portal_type python:here.getPortalTypeName().lower().replace(' ', '_'); | ||||
|                   errors python:request.get('errors', {}); | ||||
|                   isEdit python:False; | ||||
|                   tool contextObj/getTool; | ||||
|                   flavour python: tool.getFlavour(contextObj); | ||||
|                   phaseInfo python: contextObj.getAppyPhases(currentOnly=True, forPlone=False); | ||||
|                   phase request/phase|phaseInfo/name; | ||||
|                   pageName python: contextObj.getAppyPage(isEdit, phaseInfo); | ||||
|                   showWorkflow python: flavour.getAttr('showWorkflowFor' + contextObj.meta_type)"> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/showPagePrologue"/> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/showPageHeader"/> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/listFields" /> | ||||
|       <div metal:use-macro="here/<!macros!>/macros/showPageFooter"/> | ||||
|     </metal:fill> | ||||
|   </body> | ||||
| </html> | ||||
| Before Width: | Height: | Size: 174 B | 
| Before Width: | Height: | Size: 174 B | 
|  | @ -13,24 +13,24 @@ import Extensions.appyWrappers | |||
| # every Archetype instance has a method "getProductConfig" that returns this | ||||
| # module. | ||||
| from persistent.list import PersistentList | ||||
| from Products.Archetypes.utils import DisplayList | ||||
| from OFS.Image import File | ||||
| from DateTime import DateTime | ||||
| from Products.CMFCore.utils import getToolByName | ||||
| from Products.CMFPlone.PloneBatch import Batch | ||||
| from OFS.Image import File | ||||
| from Products.Archetypes.utils import DisplayList | ||||
| import logging | ||||
| logger = logging.getLogger('<!applicationName!>') | ||||
| 
 | ||||
| # Some global variables -------------------------------------------------------- | ||||
| PROJECTNAME = '<!applicationName!>' | ||||
| defaultAddRoles = [<!defaultAddRoles!>] | ||||
| DEFAULT_ADD_CONTENT_PERMISSION = "Add portal content" | ||||
| ADD_CONTENT_PERMISSIONS = { | ||||
| <!addPermissions!>} | ||||
| setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, tuple(defaultAddRoles)) | ||||
| product_globals = globals() | ||||
| PROJECTNAME = '<!applicationName!>' | ||||
| applicationRoles = [<!roles!>] | ||||
| rootClasses = [<!rootClasses!>] | ||||
| referers = { | ||||
| <!referers!> | ||||
| } | ||||
|  |  | |||
|  | @ -1,27 +0,0 @@ | |||
| ## Controller Python Script "createAppyObject" | ||||
| ##bind container=container | ||||
| ##bind context=context | ||||
| ##bind namespace= | ||||
| ##bind script=script | ||||
| ##bind state=state | ||||
| ##bind subpath=traverse_subpath | ||||
| ##parameters=initiator, field, type_name | ||||
| ##title=createAppyObject | ||||
| ## | ||||
| if not initiator or not field: | ||||
|     raise Exception, 'You must specify the uid of the object that initiates ' \ | ||||
|                      'this creation in the "initiator" parameter and the ' \ | ||||
|                      'related field in the "field" param.' | ||||
| 
 | ||||
| if not type_name: | ||||
|     raise Exception, 'You must specify the target type name in the "type_name" ' \ | ||||
|                      'parameter.' | ||||
| 
 | ||||
| initiatorRes = context.uid_catalog.searchResults(UID=initiator) | ||||
| if not initiatorRes: | ||||
|     raise Exception, 'Given initiator UID does not correspond to a valid object.' | ||||
| 
 | ||||
| context.REQUEST.SESSION['initiator'] = initiator | ||||
| context.REQUEST.SESSION['initiatorField'] = field | ||||
| context.REQUEST.SESSION['initiatorTarget'] = type_name | ||||
| return state.set(status='success') | ||||
|  | @ -1,2 +0,0 @@ | |||
| [actions] | ||||
| action.success=redirect_to:python:'createObject?type_name=%s' % request.SESSION.get('initiatorTarget') | ||||
| Before Width: | Height: | Size: 244 B | 
|  | @ -1,51 +0,0 @@ | |||
| ## Python Script "<!applicationName!>_do.py" | ||||
| ##bind container=container | ||||
| ##bind context=context | ||||
| ##bind namespace= | ||||
| ##bind script=script | ||||
| ##bind subpath=traverse_subpath | ||||
| ##parameters=actionType | ||||
| ##title=Executes an action | ||||
| rq = context.REQUEST | ||||
| urlBack = rq['HTTP_REFERER'] | ||||
| 
 | ||||
| if actionType == 'appyAction': | ||||
|     obj = context.uid_catalog(UID=rq['objectUid'])[0].getObject() | ||||
|     res, msg = obj.executeAppyAction(rq['fieldName']) | ||||
|     if not msg: | ||||
|         # Use the default i18n messages | ||||
|         suffix = 'ko' | ||||
|         if res: | ||||
|             suffix = 'ok' | ||||
|         label = '%s_action_%s' % (obj.getLabelPrefix(rq['fieldName']), suffix) | ||||
|         msg = context.utranslate(label, domain='<!applicationName!>') | ||||
|     context.plone_utils.addPortalMessage(msg) | ||||
| 
 | ||||
| elif actionType == 'changeRefOrder': | ||||
|     # Move the item up (-1), down (+1) or at a given position ? | ||||
|     move = -1 # Move up | ||||
|     isDelta = True | ||||
|     if rq.get('moveDown.x', None) != None: | ||||
|         move = 1 # Move down | ||||
|     elif rq.get('moveSeveral.x', None) != None: | ||||
|         try: | ||||
|             move = int(rq.get('moveValue')) | ||||
|             # In this case, it is not a delta value; it is the new position where | ||||
|             # the item must be moved. | ||||
|             isDelta = False | ||||
|         except ValueError: | ||||
|             context.plone_utils.addPortalMessage( | ||||
|                 context.utranslate('ref_invalid_index', domain='<!applicationName!>')) | ||||
|     context.changeAppyRefOrder(rq['fieldName'], rq['objectUid'], move, isDelta) | ||||
| 
 | ||||
| elif actionType == 'triggerTransition': | ||||
|     from Products.CMFPlone import PloneMessageFactory as _ | ||||
|     context.portal_workflow.doActionFor(context, rq['workflow_action'], | ||||
|                                         comment=rq.get('comment', '')) | ||||
|     if urlBack.find('?') != -1: | ||||
|         # Remove params; this way, the user may be redirected to correct phase | ||||
|         # when relevant. | ||||
|         urlBack = urlBack[:urlBack.find('?')] | ||||
|     context.plone_utils.addPortalMessage(_(u'Your content\'s status has been modified.')) | ||||
| 
 | ||||
| return rq.RESPONSE.redirect(urlBack) | ||||
| Before Width: | Height: | Size: 818 B | 
| Before Width: | Height: | Size: 248 B | 
| Before Width: | Height: | Size: 201 B | 
| Before Width: | Height: | Size: 192 B | 
| Before Width: | Height: | Size: 754 B | 
| Before Width: | Height: | Size: 228 B | 
| Before Width: | Height: | Size: 225 B | 
| Before Width: | Height: | Size: 225 B | 
 Gaetan Delannay
						Gaetan Delannay