appy.pod: bugfix while including a PDF file into a document; ease the inclusion of Plone images from a Plone/Zope DB through 'do text from document' statements; appy.gen: added obj.mayAct method that allows to display conditionnally the column 'Actions' when an object is shown in a list (query or ref); improved navigation from sub-objects to parent objects; improved layout.

This commit is contained in:
Gaetan Delannay 2012-02-23 15:58:06 +01:00
parent 9c5f92337b
commit 13f3400577
9 changed files with 90 additions and 62 deletions

View file

@ -923,6 +923,15 @@ class BaseMixin:
if hasattr(appyObj, 'mayNavigate'): return appyObj.mayNavigate()
return True
def mayAct(self):
'''May the currently logged user see column "actions" for this
object? This can be used for hiding the "edit" icon, for example:
when a user may edit only a restricted set of fields on an object,
we may avoid showing him the global "edit" icon.'''
appyObj = self.appy()
if hasattr(appyObj, 'mayAct'): return appyObj.mayAct()
return True
def mayDelete(self):
'''May the currently logged user delete this object? This condition
comes as an addition/refinement to the corresponding workflow
@ -1291,6 +1300,13 @@ class BaseMixin:
'''Returns a reference to the config module.'''
return self.__class__.config
def getParent(self):
'''If this object is stored within another one, this method returns it.
Else (if the object is stored directly within the tool or the root
data folder) it returns None.'''
parent = self.getParentNode()
if parent.meta_type != 'Folder': return parent
def index_html(self):
'''Redirects to /ui.'''
return self.REQUEST.RESPONSE.redirect(self.getUrl())

View file

@ -1,5 +1,5 @@
body { font: 75% Lucida,Helvetica,Arial,sans-serif; background-color: #EAEAEA; }
pre { font: 100% Lucida,Helvetica,Arial,sans-serif; margin: 0}
body { font: 75% Helvetica,Arial,sans-serif; background-color: #EAEAEA; }
pre { font: 100% Helvetica,Arial,sans-serif; margin: 0}
h1 { font-size: 11pt; margin:0;}
h2 { font-size: 10pt; margin:0; font-style: italic; font-weight: normal;}
h3 { font-size: 9pt; margin:0; font-weight: bold;}
@ -19,13 +19,13 @@ input[type=button] { border: 1px solid #cccccc;
input[type=submit] { border: 1px solid #cccccc; background-color: #f8f8f8;
cursor: pointer; }
input[type=password] { border: 1px solid #cccccc; background-color: #f8f8f8;
font-family: Lucida,Helvetica,Arial,sans-serif;}
font-family: Helvetica,Arial,sans-serif;}
input[type=text] { border: 1px solid #cccccc; background-color: #f8f8f8;
font-family: Lucida,Helvetica,Arial,sans-serif;
font-family: Helvetica,Arial,sans-serif;
margin-bottom: 1px}
select { border: 1px solid #cccccc; background-color: #f8f8f8;}
textarea { width: 99%; font: 100% Lucida,Helvetica,Arial,sans-serif;
textarea { width: 99%; font: 100% Helvetica,Arial,sans-serif;
border: 1px solid #a79e9e; background-color: #f8f8f8;}
label { font-weight: 600; font-style: italic; line-height: 1.4em;}
legend { padding-bottom: 2px; padding-right: 3px; color: black;}
@ -40,19 +40,19 @@ img {border: 0}
border-style: solid; border-width: 1px; border-color: grey; }
.top { height: 75px; margin-left: 3em; vertical-align: top;}
.lang { margin-right: 3px; }
.userStrip { background-color: #89A6B1; height: 40px;
border-top: 3px solid #405A64; border-bottom: 2px solid #5F7983; }
.userStrip { background-color: #d7dee4; height: 40px;
border-top: 1px solid #5F7983; border-bottom: 1px solid #5F7983; }
.login { margin-top: 2px; margin-bottom: 2px; color: white;}
.buttons { margin-left: 4px;}
.message { color: #fd9c03; position: absolute; top: -55px; left: 100px;
width: 700px; border: 1px black dashed; padding: 2px 6px;
background-color: #f4f5f6}
.discreet { font-size: 90%; }
.portlet { width: 150px; padding: 12px 9px 9px 9px;
border-right: 2px solid #5F7983;}
.portlet { width: 150px; border-right: 1px solid #5F7983;}
.portletContent { margin: 9px; }
.portletTitle { font-weight: bold; font-size: 110%; margin-bottom: 4px;}
.portletCurrent { font-weight: bold; }
.portletSep { border-top: 1px solid grey; margin-top: 9px; padding-top: 9px;}
.portletSep { border-top: 1px solid #5F7983; margin-top: 2px;}
.portletPage { font-style: italic; }
.portletGroup { font-variant: small-caps; font-weight: bold; font-style: normal;
margin: 0.4em 0 0.2em 0; }
@ -68,7 +68,7 @@ img {border: 0}
.list { border: 1px solid grey; margin-bottom: 3px;}
.list td, .list th { border: 1px solid grey;
padding-left: 5px; padding-right: 5px; padding-top: 3px;}
.list th { background-color: #c8d7e1; font-style: italic; font-weight: normal;}
.list th { background-color: #d7dee4; font-style: italic; font-weight: normal;}
.grid th { font-style: italic; font-weight: normal;
border-bottom: 2px solid grey; padding: 2px 2px;}
.grid td { padding-right: 5px; }

View file

@ -63,15 +63,15 @@
backText navInfo/backText">
<tr valign="middle">
<tal:comment replace="nothing">Go to the source URL (search or referred object)</tal:comment>
<td tal:condition="sourceUrl"><a tal:attributes="href sourceUrl"><img style="cursor:pointer"
<td tal:condition="sourceUrl"><a tal:attributes="href sourceUrl"><img
tal:attributes="src string: $appUrl/ui/gotoSource.png;
title python: backText + ' : ' + tool.translate('goto_source')"/></a></td>
<tal:comment replace="nothing">Go to the first page</tal:comment>
<td tal:condition="firstUrl"><a tal:attributes="href firstUrl"><img style="cursor:pointer"
<td tal:condition="firstUrl"><a tal:attributes="href firstUrl"><img
tal:attributes="src string: $appUrl/ui/arrowLeftDouble.png;
title python: tool.translate('goto_first')"/></a></td>
<tal:comment replace="nothing">Go to the previous page</tal:comment>
<td tal:condition="previousUrl"><a tal:attributes="href previousUrl"><img style="cursor:pointer"
<td tal:condition="previousUrl"><a tal:attributes="href previousUrl"><img
tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
title python: tool.translate('goto_previous')"/></a></td>
<tal:comment replace="nothing">Explain which element is currently shown</tal:comment>
@ -80,11 +80,11 @@
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</td>
<tal:comment replace="nothing">Go to the next page</tal:comment>
<td tal:condition="python: nextUrl"><a tal:attributes="href nextUrl"><img style="cursor:pointer"
<td tal:condition="python: nextUrl"><a tal:attributes="href nextUrl"><img
tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
title python: tool.translate('goto_next')"/></a></td>
<tal:comment replace="nothing">Go to the last page</tal:comment>
<td tal:condition="lastUrl"><a tal:attributes="href lastUrl"><img style="cursor:pointer"
<td tal:condition="lastUrl"><a tal:attributes="href lastUrl"><img
tal:attributes="src string: $appUrl/ui/arrowRightDouble.png;
title python: tool.translate('goto_last')"/></a></td>
</tr>

View file

@ -9,49 +9,56 @@
contextObj tool/getPublishedObject;
rootClasses tool/getRootClasses">
<tal:publishedObject condition="python: contextObj and contextObj.mayNavigate()">
<div class="portletTitle" tal:content="contextObj/Title"></div>
<div class="portletContent" tal:condition="python: contextObj and contextObj.mayNavigate()">
<div class="portletTitle" tal:define="parent contextObj/getParent">
<span tal:replace="contextObj/Title"></span>
<div style="float:right" tal:condition="python: parent">
<a tal:attributes="href parent/absolute_url">
<img tal:attributes="src string: $appUrl/ui/gotoSource.png"/>
</a>
</div>
</div>
<span><metal:phases use-macro="here/ui/portlet/macros/phases"/></span>
</tal:publishedObject>
</div>
<tal:comment replace="nothing">One section for every searchable root class.</tal:comment>
<tal:section repeat="rootClass python: [rc for rc in rootClasses if tool.userMaySearch(rc)]">
<tal:comment replace="nothing">Section title, with action icons</tal:comment>
<table width="100%"
tal:attributes="class python:test((repeat['rootClass'].number()==1) and not contextObj, '', 'portletSep')">
<tr>
<td>
<a tal:attributes="href python: '%s?className=%s' % (queryUrl, rootClass);
class python:test(not currentSearch and (currentClass==rootClass), 'portletCurrent', '')"
tal:content="structure python: _(rootClass + '_plural')"></a>
</td>
<td align="right"
tal:define="addPermission python: '%s: Add %s' % (appName, rootClass);
userMayAdd python: user.has_permission(addPermission, appFolder);
createMeans python: tool.getCreateMeans(rootClass)">
<tal:comment replace="nothing">Create a new object from a web form</tal:comment>
<a tal:condition="python: ('form' in createMeans) and userMayAdd"
tal:attributes="href python: '%s/do?action=Create&className=%s' % (toolUrl, rootClass);
title python: _('query_create')">
<img tal:attributes="src string: $appUrl/ui/plus.png"/>
</a>
<tal:comment replace="nothing">Create (a) new object(s) by importing data</tal:comment>
<a tal:condition="python: ('import' in createMeans) and userMayAdd"
tal:attributes="href python: '%s/ui/import?className=%s' % (toolUrl, rootClass);
title python: _('query_import')">
<img tal:attributes="src string: $appUrl/ui/import.png"/>
</a>
<tal:comment replace="nothing">Search objects of this type</tal:comment>
<a tal:define="showSearch python: tool.getAttr('enableAdvancedSearchFor%s' % rootClass)"
tal:condition="showSearch"
tal:attributes="href python: '%s/ui/search?className=%s' % (toolUrl, rootClass);
title python: _('search_objects')">
<img tal:attributes="src string: $appUrl/ui/search.gif"/>
</a>
</td>
</tr>
</table>
<tal:comment replace="nothing">Searches for this content type.</tal:comment>
<tal:comment replace="nothing">One section for every searchable root class.</tal:comment>
<tal:section repeat="rootClass python: [rc for rc in rootClasses if tool.userMaySearch(rc)]">
<tal:comment replace="nothing">A separator if required</tal:comment>
<div class="portletSep" tal:define="nb repeat/rootClass/number"
tal:condition="python: (nb == 1 and contextObj) or (nb != 1)"></div>
<div class="portletContent">
<tal:comment replace="nothing">Section title, with action icons</tal:comment>
<a tal:attributes="href python: '%s?className=%s' % (queryUrl, rootClass);
class python:test(not currentSearch and (currentClass==rootClass), 'portletCurrent', '')"
tal:content="structure python: _(rootClass + '_plural')">
</a>
<div style="float: right"
tal:define="addPermission python: '%s: Add %s' % (appName, rootClass);
userMayAdd python: user.has_permission(addPermission, appFolder);
createMeans python: tool.getCreateMeans(rootClass)">
<tal:comment replace="nothing">Create a new object from a web form</tal:comment>
<a tal:condition="python: ('form' in createMeans) and userMayAdd"
tal:attributes="href python: '%s/do?action=Create&className=%s' % (toolUrl, rootClass);
title python: _('query_create')">
<img tal:attributes="src string: $appUrl/ui/plus.png"/>
</a>
<tal:comment replace="nothing">Create (a) new object(s) by importing data</tal:comment>
<a tal:condition="python: ('import' in createMeans) and userMayAdd"
tal:attributes="href python: '%s/ui/import?className=%s' % (toolUrl, rootClass);
title python: _('query_import')">
<img tal:attributes="src string: $appUrl/ui/import.png"/>
</a>
<tal:comment replace="nothing">Search objects of this type</tal:comment>
<a tal:define="showSearch python: tool.getAttr('enableAdvancedSearchFor%s' % rootClass)"
tal:condition="showSearch"
tal:attributes="href python: '%s/ui/search?className=%s' % (toolUrl, rootClass);
title python: _('search_objects')">
<img tal:attributes="src string: $appUrl/ui/search.gif"/>
</a>
</div>
<tal:comment replace="nothing">Searches for this content type.</tal:comment>
<tal:searchOrGroup repeat="searchOrGroup python: tool.getSearches(rootClass)">
<tal:group condition="searchOrGroup/isGroup">
<tal:expanded define="group searchOrGroup;
@ -84,7 +91,7 @@
class python: test(search['name'] == currentSearch, 'portletCurrent', '');"
tal:content="structure search/label"></a>
</dt>
</tal:searchOrGroup>
</tal:searchOrGroup>
</tal:section>
</metal:portlet>

View file

@ -118,7 +118,7 @@
<tal:comment replace="nothing">Column "Actions"</tal:comment>
<td align="right">
<table class="noStyle">
<table class="noStyle" tal:condition="obj/mayAct">
<tr>
<tal:comment replace="nothing">Edit the element</tal:comment>
<td>

View file

@ -145,7 +145,7 @@
</tr>
<tr>
<td>
<table width="99%">
<table width="100%" cellpadding="0" cellspacing="0">
<tr valign="top">
<tal:comment replace="nothing">Portlet</tal:comment>
<td tal:condition="python: tool.showPortlet(context)" class="portlet">

View file

@ -210,7 +210,9 @@
</td>
<tal:comment replace="nothing">Actions</tal:comment>
<td align="right">
<metal:showObjectActions use-macro="app/ui/widgets/ref/macros/objectActions" />
<tal:show condition="obj/mayAct">
<metal:showObjectActions use-macro="app/ui/widgets/ref/macros/objectActions" />
</tal:show>
</td>
</tr>
</tal:row>

View file

@ -146,7 +146,7 @@ class PdfImporter(DocImporter):
if os.path.exists(nextImage):
# Use internally an Image importer for doing this job.
imgImporter =ImageImporter(None, nextImage, 'jpg',self.renderer)
imgImporter.setAnchor('paragraph')
imgImporter.setImageInfo('paragraph', True, None, None, None)
self.res += imgImporter.run()
os.remove(nextImage)
else:

View file

@ -297,6 +297,9 @@ class Renderer:
# Guess document format
if isinstance(content, FileWrapper):
format = content.mimeType
elif hasattr(content, 'filename') and content.filename:
format = os.path.splitext(content.filename)[1][1:]
content = content.data
if not format:
# It should be deduced from p_at
if not at: