appy.pod: xhtml2odt: ability to include images from img tags (anonymously). Non-anonymous solution for a Appy/Zope server only; function 'document': allow to specify size of images in cm or px, or via a 'style' tag; appy.gen: allow to upload images in ckeditor fields; improved error management.

This commit is contained in:
Gaetan Delannay 2012-01-04 18:03:46 +01:00
parent 98fafad14a
commit 2bd3fe1eeb
10 changed files with 206 additions and 54 deletions

View file

@ -2138,7 +2138,8 @@ class Pod(Type):
stylesMapping = self.stylesMapping
rendererParams = {'template': StringIO.StringIO(template.content),
'context': podContext, 'result': tempFileName,
'stylesMapping': stylesMapping}
'stylesMapping': stylesMapping,
'imageResolver': tool.o.getApp()}
if tool.unoEnabledPython:
rendererParams['pythonWithUnoPath'] = tool.unoEnabledPython
if tool.openOfficePort:

View file

@ -21,7 +21,8 @@ homePage = '''
</tal:main>
'''
errorPage = '''
<tal:main define="tool python: context.config">
<tal:main define="tool python: context.config"
on-error="string: ServerError">
<html metal:use-macro="context/ui/template/macros/main">
<div metal:fill-slot="content" tal:define="o python:options">
<p tal:condition="o/error_message"

View file

@ -1387,31 +1387,71 @@ class BaseMixin:
for name in templateName.split('/'): res = getattr(res, name)
return res
def download(self):
'''Downloads the content of the file that is in the File field named
p_name.'''
def download(self, name=None):
'''Downloads the content of the file that is in the File field whose
name is in the request. This name can also represent an attribute
storing an image within a rich text field. If p_name is not given, it is retrieved
from the request.'''
name = self.REQUEST.get('name')
if not name: return
appyType = self.getAppyType(name)
if (not appyType.type =='File') or not appyType.isShowable(self,'view'):
return
if '_img_' not in name:
appyType = self.getAppyType(name)
else:
appyType = self.getAppyType(name.split('_img_')[0])
if not appyType.isShowable(self, 'view'):
from zExceptions import NotFound
raise NotFound()
theFile = getattr(self.aq_base, name, None)
if theFile:
response = self.REQUEST.RESPONSE
response.setHeader('Content-Disposition', 'inline;filename="%s"' % \
theFile.filename)
# Define content type
if theFile.content_type:
response.setHeader('Content-Type', theFile.content_type)
response.setHeader('Cachecontrol', 'no-cache')
response.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:05 GMT')
return theFile.index_html(self.REQUEST, self.REQUEST.RESPONSE)
def allows(self, permission):
def upload(self):
'''Receives an image uploaded by the user via ckeditor and stores it in
a special field on this object.'''
# Get the name of the rich text field for which an image must be stored.
params = self.REQUEST['QUERY_STRING'].split('&')
fieldName = params[0].split('=')[1]
ckNum = params[1].split('=')[1]
# We will store the image in a field named [fieldName]_img_[nb].
i = 1
attrName = '%s_img_%d' % (fieldName, i)
while True:
if not hasattr(self.aq_base, attrName):
break
else:
i += 1
attrName = '%s_img_%d' % (fieldName, i)
# Store the image. Create a fake File instance for doing the job.
fakeFile = gen.File(isImage=True)
fakeFile.name = attrName
fakeFile.store(self, self.REQUEST['upload'])
# Return the URL of the image.
url = '%s/download?name=%s' % (self.absolute_url(), attrName)
resp = "<script type='text/javascript'>window.parent.CKEDITOR.tools" \
".callFunction(%s, '%s');</script>" % (ckNum, url)
self.REQUEST.RESPONSE.write(resp)
def allows(self, permission, raiseError=False):
'''Has the logged user p_permission on p_self ?'''
return self.getUser().has_permission(permission, self)
hasPermission = self.getUser().has_permission(permission, self)
if not hasPermission and raiseError:
from AccessControl import Unauthorized
raise Unauthorized
return hasPermission
def getEditorInit(self, name):
'''Gets the Javascrit init code for displaying a rich editor for
'''Gets the Javascript init code for displaying a rich editor for
field named p_name.'''
return "CKEDITOR.replace('%s', {toolbar: 'Appy'})" % name
return "CKEDITOR.replace('%s', {toolbar: 'Appy', filebrowserUploadUrl:"\
"'%s/upload'})" % (name, self.absolute_url())
def getCalendarInit(self, name, years):
'''Gets the Javascript init code for displaying a calendar popup for

View file

@ -2,6 +2,7 @@
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="contextObj context/getParentNode;
dummy python: contextObj.allows('Modify portal content', raiseError=True);
errors request/errors | python:{};
layoutType python:'edit';
layout python: contextObj.getPageLayout(layoutType);
@ -9,7 +10,8 @@
phase phaseInfo/name;
page request/page|python:'main';
cssJs python: contextObj.getCssAndJs(contextObj.getAppyTypes(layoutType, page), layoutType);
confirmMsg request/confirmMsg | nothing;">
confirmMsg request/confirmMsg | nothing;"
tal:on-error="structure python: tool.manageError(error)">
<tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
<link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"

View file

@ -2,13 +2,15 @@
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="contextObj python: context.getParentNode();
dummy python: contextObj.allows('View', raiseError=True);
portal_type python: context.portal_type.lower().replace(' ', '_');
errors python: req.get('errors', {});
layoutType python:'view';
layout python: contextObj.getPageLayout(layoutType);
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
page req/page|python:'main';
phase phaseInfo/name;">
phase phaseInfo/name;"
tal:on-error="structure python: tool.manageError(error)">
<metal:prologue use-macro="context/ui/page/macros/prologue"/>
<metal:show use-macro="context/ui/page/macros/show"/>
<metal:footer use-macro="context/ui/page/macros/footer"/>