[gen] Added 'freeze actions' to pod fields.

This commit is contained in:
Gaetan Delannay 2014-03-24 22:55:00 +01:00
parent 0834356487
commit d0749cc365
32 changed files with 426 additions and 281 deletions

View file

@ -181,7 +181,7 @@ class Calendar(Field):
<input type="hidden" name="actionType" value="deleteEvent"/>
<input type="hidden" name="day"/>
<div align="center" style="margin-bottom: 5px">_('delete_confirm')</div>
<div align="center" style="margin-bottom: 5px">_('action_confirm')</div>
<!-- Delete successive events ? -->
<div class="discreet" style="margin-bottom: 10px"

View file

@ -33,29 +33,76 @@ class Pod(Field):
want to put in it. It is the way gen uses pod.'''
# Layout for rendering a POD field for exporting query results.
rLayouts = {'view': Table('fl', width=None)}
allFormats = ('pdf', 'doc', 'odt')
allFormats = {'.odt': ('pdf', 'doc', 'odt'), '.ods': ('xls', 'ods')}
POD_ERROR = 'An error occurred while generating the document. Please ' \
'contact the system administrator.'
NO_TEMPLATE = 'Please specify a pod template in field "template".'
UNAVAILABLE_TEMPLATE = 'You are not allow to perform this action.'
UNAUTHORIZED = 'You are not allow to perform this action.'
TEMPLATE_NOT_FOUND = 'Template not found at %s.'
FREEZE_ERROR = 'Error while trying to freeze a "%s" file in pod field ' \
'"%s" (%s).'
FREEZE_FATAL_ERROR = 'Server error. Please contact the administrator.'
# Icon allowing to generate a given template in a given format.
pxIcon = Px('''
<img var="iconSuffix=frozen and 'Frozen' or ''"
src=":url(fmt + iconSuffix)" class="clickable"
title=":field.getIconTitle(obj, fmt, frozen)"
onclick=":'generatePod(%s,%s,%s,%s,%s)' % (q(uid), q(name), \
q(info.template), q(fmt), q(ztool.getQueryInfo()))"/>''')
pxView = pxCell = Px('''
<table cellpadding="0" cellspacing="0">
<table cellpadding="0" cellspacing="0" var="uid=obj.uid">
<tr>
<td for="template in field.getVisibleTemplates(obj)">
<td for="info in field.getVisibleTemplates(obj)">
<table cellpadding="0" cellspacing="0" class="podTable">
<tr>
<td for="fmt in field.getOutputFormats(obj)">
<img src=":url(fmt)" title=":fmt.upper()" class="clickable"
onclick=":'generatePodDocument(%s,%s,%s,%s,%s)' % \
(q(obj.uid), q(name), q(template), q(fmt), \
q(ztool.getQueryInfo()))"/>
<td for="fmt in info.formats"
var2="freezeAllowed=fmt in info.freezeFormats;
frozen=field.isFrozen(obj, info.template, fmt)">
<!-- A clickable icon if no freeze action is allowed -->
<x if="not freezeAllowed">:field.pxIcon</x>
<!-- A clickable icon and a dropdown menu else. -->
<div if="freezeAllowed" class="dropdownMenu"
var2="dropdownId='%s_%s' % (uid, \
field.getFreezeName(info.template, fmt, sep='_'))"
onmouseover=":'toggleDropdown(%s)' % q(dropdownId)"
onmouseout=":'toggleDropdown(%s,%s)' % (q(dropdownId), \
q('none'))">
<x>:field.pxIcon</x>
<!-- The dropdown menu containing freeze actions -->
<table id=":dropdownId" class="dropdown">
<!-- Unfreeze -->
<tr if="frozen" valign="top">
<td>
<a onclick=":'freezePod(%s,%s,%s,%s,%s)' % (q(uid), q(name), \
q(info.template), q(fmt), q('unfreeze'))"
class="podName">:_('unfreezeField')</a>
</td>
<td align="center"><img src=":url('unfreeze')"/></td>
</tr>
<!-- (Re-)freeze -->
<tr valign="top">
<td>
<a onclick=":'freezePod(%s,%s,%s,%s,%s)' % (q(uid), q(name), \
q(info.template), q(fmt), q('freeze'))"
class="podName">:_('freezeField')</a>
</td>
<td align="center"><img src=":url('freeze')"/></td>
</tr>
<!-- (Re-)upload -->
<tr valign="top">
<td>
<a onclick=":'uploadPod(%s,%s,%s,%s)' % (q(uid), q(name), \
q(info.template), q(fmt))"
class="podName">:_('uploadField')</a>
</td>
<td align="center"><img src=":url('upload')"/></td>
</tr>
</table>
</div>
</td>
<td class="podName">:field.getTemplateName(obj, template)</td>
<td class="podName">:field.getTemplateName(obj, info.template)</td>
</tr>
</table>
</td>
@ -71,7 +118,8 @@ class Pod(Field):
maxChars=None, colspan=1, master=None, masterValue=None,
focus=False, historized=False, mapping=None, label=None,
template=None, templateName=None, showTemplate=None,
context=None, stylesMapping={}, formats=None):
freezeTemplate=None, context=None, stylesMapping={},
formats=None):
# Param "template" stores the path to the pod template(s).
if not template: raise Exception(Pod.NO_TEMPLATE)
if isinstance(template, basestring):
@ -89,13 +137,48 @@ class Pod(Field):
# "template" contains several templates and "templateName" is None, Appy
# will produce names from template filenames.
self.templateName = templateName
# "showTemplate", if specified, must be a method that will be called
# with the current template as single arg and that must return True if
# the template can be seen by the current user. "showTemplate" comes in
# addition to self.show. self.show dictates the visibility of the whole
# field (ie, all templates from self.template) while "showTemplate"
# dictates the visiblity of a specific template within self.template.
# "showTemplate" determines if the current user may generate documents
# based on this pod field. More precisely, "showTemplate", if specified,
# must be a method that will be called with the current template as
# single arg (one among self.template) and that must return the list or
# tuple of formats that the current user may use as output formats for
# generating a document. If the current user is not allowed at all to
# generate documents based on the current template, "showTemplate" must
# return an empty tuple/list. If "showTemplate" is not specified, the
# user will be able to generate documents based on the current template,
# in any format from self.formats (see below).
# "showTemplate" comes in addition to self.show. self.show dictates the
# visibility of the whole field (ie, all templates from self.template)
# while "showTemplate" dictates the visiblity of a specific template
# within self.template.
self.showTemplate = showTemplate
# "freezeTemplate" determines if the current user may freeze documents
# normally generated dynamically from this pod field. More precisely,
# "freezeTemplate", if specified, must be a method that will be called
# with the current template as single arg and must return the (possibly
# empty) list or tuple of formats the current user may freeze. The
# "freezing-related actions" that are granted by "freezeTemplate" are
# the following. When no document is frozen yet for a given
# template/format, the user may:
# - freeze the document: pod will be called to produce a document from
# the current database content and will store it in the database.
# Subsequent user requests for this pod field will return the frozen
# doc instead of generating on-the-fly documents;
# - upload a document: the user will be able to upload a document that
# will be stored in the database. Subsequent user requests for this
# pod field will return this doc instead of generating on-the-fly
# documents.
# When a document is already frozen or uploaded for a given
# template/format, the user may:
# - unfreeze the document: the frozen or uploaded document will be
# deleted from the database and subsequent user requests for the pod
# field will again generate on-the-fly documents;
# - re-freeze the document: the frozen or uploaded document will be
# deleted, a new document will be generated from the current database
# content and will be frozen as a replacement to the deleted one;
# - upload a document: the frozen or uploaded document will be replaced
# by a new document uploaded by the current user.
self.freezeTemplate = freezeTemplate
# The context is a dict containing a specific pod context, or a method
# that returns such a dict.
self.context = context
@ -118,12 +201,11 @@ class Pod(Field):
# field is determined by freezing.
self.validable = False
def getOutputFormats(self, obj):
'''Returns self.formats, excepted if there is a frozen document: in
this case, only the format of the frozen doc is returned.'''
if not obj.user.has_role('Manager'): return self.formats
# A manager can have all formats
return self.allFormats
def getAllFormats(self, template):
'''Gets all the outputy formats that are available for a given
p_template.'''
ext = os.path.splitext(template)[1]
return self.allFormats[ext]
def getTemplateName(self, obj, fileName):
'''Gets the name of a template given its p_fileName.'''
@ -149,14 +231,25 @@ class Pod(Field):
def getVisibleTemplates(self, obj):
'''Returns, among self.template, the template(s) that can be shown.'''
if not self.showTemplate: return self.template # Show them all.
isManager = obj.user.has_role('Manager')
if not self.showTemplate:
# Show them all in any format.
res = []
for template in self.template:
res.append(Object(template=template,
formats=self.getAllFormats(template),
freezeFormats=self.getFreezeFormats(obj, template)))
res = []
for template in self.template:
if self.showTemplate(obj, template):
res.append(template)
formats = isManager and self.getAllFormats(template) or \
self.showTemplate(obj, template)
if formats:
res.append(Object(template=template, formats=formats,
freezeFormats=self.getFreezeFormats(obj, template)))
return res
def getValue(self, obj, template=None, format=None, result=None):
def getValue(self, obj, template=None, format=None, result=None,
noSecurity=False):
'''For a pod field, getting its value means computing a pod document or
returning a frozen one. A pod field differs from other field types
because there can be several ways to produce the field value (ie:
@ -172,12 +265,11 @@ class Pod(Field):
template = template or rq.get('template') or self.template[0]
format = format or rq.get('podFormat') or 'odt'
# Security check.
if not self.showTemplate(obj, template):
raise Exception(self.UNAVAILABLE_TEMPLATE)
if not noSecurity and not self.showTemplate(obj, template):
raise Exception(self.UNAUTHORIZED)
# Return the frozen document if frozen.
frozen = self.isFrozen(obj, template, format)
if frozen:
print 'RETURN FROZEN'
fileName = self.getDownloadName(obj, template, format, False)
return FileInfo(frozen, inDb=False, uploadName=fileName)
# We must call pod to compute a pod document from "template".
@ -254,12 +346,12 @@ class Pod(Field):
# Get a FileInfo instance to manipulate the file on the filesystem.
return FileInfo(result, inDb=False, uploadName=fileName)
def getFreezeName(self, template=None, format='pdf'):
def getFreezeName(self, template=None, format='pdf', sep='.'):
'''Gets the name on disk on the frozen document corresponding to this
pod field, p_template and p_format.'''
template = template or self.template[0]
templateName = os.path.splitext(template)[0].replace(os.sep, '_')
return '%s_%s.%s' % (self.name, templateName, format)
return '%s_%s%s%s' % (self.name, templateName, sep, format)
def isFrozen(self, obj, template=None, format='pdf'):
'''Is there a frozen document for thid pod field, on p_obj, for
@ -271,9 +363,18 @@ class Pod(Field):
res = os.path.join(dbFolder, folder, fileName)
if os.path.exists(res): return res
def freeze(self, obj, template=None, format='pdf'):
def freeze(self, obj, template=None, format='pdf', noSecurity=True,
freezeOdtOnError=True):
'''Freezes, on p_obj, a document for this pod field, for p_template in
p_format.'''
p_format. If p_noSecurity is True, the security check, based on
self.freezeTemplate, is bypassed. if freezeOdtOnError is True and
format is not "odt", if the freezing fails we try to freeze the odt
version, which is more robust because it does not require calling
LibreOffice.'''
# Security check.
if not noSecurity and \
(format not in self.getFreezeFormats(obj, template)):
raise Exception(self.UNAUTHORIZED)
# Compute the absolute path where to store the frozen document in the
# database.
dbFolder, folder = obj.o.getFsFolder(create=True)
@ -282,12 +383,12 @@ class Pod(Field):
if os.path.exists(result):
obj.log('Freeze: overwriting %s...' % result)
# Generate the document.
doc = self.getValue(obj, template=template, format=format,
result=result)
doc = self.getValue(obj, template=template, format=format,result=result)
if isinstance(doc, basestring):
# An error occurred, the document was not generated.
obj.log(self.FREEZE_ERROR % (format, self.name, doc), type='error')
if format == 'odt': raise Exception(self.FREEZE_FATAL_ERROR)
if not freezeOdtOnError or (format == 'odt'):
raise Exception(self.FREEZE_FATAL_ERROR)
obj.log('Trying to freeze the ODT version...')
# Try to freeze the ODT version of the document, which does not
# require to call LibreOffice: the risk of error is smaller.
@ -303,12 +404,35 @@ class Pod(Field):
raise Exception(self.FREEZE_FATAL_ERROR)
return doc
def unfreeze(self, obj, template=None, format='pdf'):
def unfreeze(self, obj, template=None, format='pdf', noSecurity=True):
'''Unfreezes, on p_obj, the document for this pod field, for p_template
in p_format.'''
# Security check.
if not noSecurity and \
(format not in self.getFreezeFormats(obj, template)):
raise Exception(self.UNAUTHORIZED)
# Compute the absolute path to the frozen doc.
dbFolder, folder = obj.o.getFsFolder()
fileName = self.getFreezeName(template, format)
frozenName = os.path.join(dbFolder, folder, fileName)
if os.path.exists(frozenName): os.remove(frozenName)
def getFreezeFormats(self, obj, template=None):
'''What are the formats into which the current user may freeze
p_template?'''
# Manager can always perform freeze actions.
template = template or self.template[0]
isManager = obj.user.has_role('Manager')
if isManager: return self.getAllFormats(template)
# Others users can perform freeze actions depending on
# self.freezeTemplate.
if not self.freezeTemplate: return ()
return self.freezeTemplate(obj, template)
def getIconTitle(self, obj, format, frozen):
'''Get the title of the format icon.'''
res = obj.translate(format)
if frozen:
res += ' (%s)' % obj.translate('frozen')
return res
# ------------------------------------------------------------------------------

View file

@ -214,7 +214,7 @@ class Ref(Field):
# PX that displays referred objects as menus.
pxViewMenus = Px('''
<table><tr style="font-size: 93%">
<table><tr valign="bottom">
<td for="menu in field.getLinkedObjectsByMenu(obj, zobjects)">
<!-- A single object in the menu: show a clickable icon to get it -->
@ -234,7 +234,7 @@ class Ref(Field):
<!-- Display the number of objects in the menu (if more than one) -->
<x if="len(menu.zobjects) &gt; 1">:len(menu.zobjects)</x>
<!-- The dropdown menu containing annexes -->
<div class="dropdown" id=":dropdownId">
<div id=":dropdownId" class="dropdown">
<div for="ztied in menu.zobjects"
var2="ztiedUrl=field.getMenuUrl(zobj, ztied)">
<a href=":ztiedUrl">:ztied.title</a>

View file

@ -19,8 +19,7 @@ except ImportError:
_noroles = []
# Errors -----------------------------------------------------------------------
jsMessages = ('no_elem_selected', 'delete_confirm', 'unlink_confirm',
'unlock_confirm', 'warn_leave_form')
jsMessages = ('no_elem_selected', 'action_confirm', 'warn_leave_form')
# ------------------------------------------------------------------------------
class ToolMixin(BaseMixin):
@ -108,21 +107,37 @@ class ToolMixin(BaseMixin):
if not bg: return url
return 'background-image: url(%s)' % url
def generateDocument(self):
'''Generates the document from field-related info. UID of object that
is the template target is given in the request.'''
def doPod(self):
'''Performs an action linked to a pod field: generate, freeze,
unfreeze... a document from a pod field.'''
rq = self.REQUEST
# Get the object on which a document must be generated.
# Get the object that is the target of this action.
obj = self.getObject(rq.get('objectUid'), appy=True)
fieldName = rq.get('fieldName')
# Get the document by accessing the value of the pod field.
res = getattr(obj, fieldName)
if isinstance(res, basestring):
# An error has occurred, and p_res contains the error message
obj.say(res)
# What is the action to perform?
action = rq.get('action', 'generate')
if action == 'generate':
# Generate a (or get a frozen) document by accessing the value of
# the pod field.
res = getattr(obj, fieldName)
if isinstance(res, basestring):
# An error has occurred, and p_res contains the error message
obj.say(res)
return self.goto(rq.get('HTTP_REFERER'))
# res contains a FileInfo instance.
res.writeResponse(rq.RESPONSE)
elif action == 'freeze':
# (Re-)freeze a document in the database.
res = obj.freeze(fieldName, rq.get('template'), rq.get('podFormat'),
noSecurity=False, freezeOdtOnError=False)
obj.say(obj.translate('action_done'))
return self.goto(rq.get('HTTP_REFERER'))
elif action == 'unfreeze':
# Unfreeze a document in the database.
obj.unfreeze(fieldName, rq.get('template'), rq.get('podFormat'),
noSecurity=False)
obj.say(obj.translate('action_done'))
return self.goto(rq.get('HTTP_REFERER'))
# res contains a FileInfo instance.
res.writeResponse(rq.RESPONSE)
def getAppName(self):
'''Returns the name of the application.'''

View file

@ -156,7 +156,7 @@ class BaseMixin:
urlBack = self.getTool().getSiteUrl()
else:
urlBack = self.getUrl(rq['HTTP_REFERER'])
self.say(self.translate('delete_done'))
self.say(self.translate('action_done'))
self.goto(urlBack)
def onDeleteEvent(self):
@ -188,7 +188,7 @@ class BaseMixin:
field = sourceObject.getAppyType(rq['fieldName'])
field.unlinkObject(sourceObject, targetObject)
urlBack = self.getUrl(rq['HTTP_REFERER'])
self.say(self.translate('unlink_done'))
self.say(self.translate('action_done'))
self.goto(urlBack)
def onCreate(self):
@ -327,7 +327,7 @@ class BaseMixin:
obj = tool.getObject(rq['objectUid'])
obj.removeLock(rq['pageName'], force=True)
urlBack = self.getUrl(rq['HTTP_REFERER'])
self.say(self.translate('unlock_done'))
self.say(self.translate('action_done'))
self.goto(urlBack)
def onCreateWithoutForm(self):

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock"
msgstr ""
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr ""
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr ""
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr ""
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr ""
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr ""
#. Default: "The page has been unlocked."
msgid "unlock_done"
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr ""
msgid "doc"
msgstr ""
#. Default: "RTF"
msgid "rtf"
msgstr ""
#. Default: "ODS"
msgid "ods"
msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls"
msgstr ""
#. Default: "frozen"
msgid "frozen"
msgstr ""
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr ""
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr ""
#. Default: "Upload a new file"
msgid "uploadField"
msgstr ""
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr ""

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock"
msgstr ""
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr ""
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr ""
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr ""
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr ""
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr ""
#. Default: "The page has been unlocked."
msgid "unlock_done"
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr ""
msgid "doc"
msgstr ""
#. Default: "RTF"
msgid "rtf"
msgstr ""
#. Default: "ODS"
msgid "ods"
msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls"
msgstr ""
#. Default: "frozen"
msgid "frozen"
msgstr ""
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr ""
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr ""
#. Default: "Upload a new file"
msgid "uploadField"
msgstr ""
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr ""

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock"
msgstr ""
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
msgstr "Wollen Sie dieses Element wirklich entfernen?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr ""
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr ""
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr "Das Element wurde entfernt."
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr ""
#. Default: "The page has been unlocked."
msgid "unlock_done"
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc"
msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS"
msgid "ods"
msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls"
msgstr ""
#. Default: "frozen"
msgid "frozen"
msgstr ""
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr ""
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr ""
#. Default: "Upload a new file"
msgid "uploadField"
msgstr ""
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr ""

View file

@ -204,29 +204,13 @@ msgstr "Unlink"
msgid "page_unlock"
msgstr "Unlock"
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
msgstr "Are you sure you want to delete this element?"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr ""
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr "Are you sure you want to unlink this element?"
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr "Are you sure you want to unlock this page?"
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr "The element has been deleted."
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr "The element has been unlinked."
#. Default: "The page has been unlocked."
msgid "unlock_done"
msgstr "The page has been unlocked."
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
msgid "goto_first"
@ -288,10 +272,6 @@ msgstr "PDF"
msgid "doc"
msgstr "DOC"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF"
#. Default: "ODS"
msgid "ods"
msgstr "ODS"
@ -300,6 +280,22 @@ msgstr "ODS"
msgid "xls"
msgstr "XLS"
#. Default: "frozen"
msgid "frozen"
msgstr "frozen"
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr "(Re-)freeze"
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr "Unfreeze"
#. Default: "Upload a new file"
msgid "uploadField"
msgstr "Upload a new file"
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr "Welcome to this Appy-powered site."

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock"
msgstr ""
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
msgstr "¿Está seguro de querer suprimir ese elemento?"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr "¿Está seguro?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr ""
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr ""
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr "El elemento ha sido suprimido."
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr ""
#. Default: "The page has been unlocked."
msgid "unlock_done"
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc"
msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS"
msgid "ods"
msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls"
msgstr ""
#. Default: "frozen"
msgid "frozen"
msgstr ""
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr ""
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr ""
#. Default: "Upload a new file"
msgid "uploadField"
msgstr ""
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr ""

View file

@ -204,29 +204,13 @@ msgstr "Dissocier"
msgid "page_unlock"
msgstr "Déverrouiller"
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
msgstr "Êtes-vous sûr de vouloir supprimer cet élément?"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr "Êtes-vous sûr?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr "Êtes-vous sûr de vouloir dissocier cet élément?"
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr "Êtes-vous sûr de vouloir déverrouiller cette page?"
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr "L'élément a été supprimé."
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr "L'élément a été dissocié."
#. Default: "The page has been unlocked."
msgid "unlock_done"
msgstr "La page a été déverrouillée."
#. Default: "The action has been performed."
msgid "action_done"
msgstr "L'action a été réalisée."
#. Default: "Go to top"
msgid "goto_first"
@ -288,10 +272,6 @@ msgstr "PDF"
msgid "doc"
msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS"
msgid "ods"
msgstr "ODS (LibreOffice Calc)"
@ -300,6 +280,22 @@ msgstr "ODS (LibreOffice Calc)"
msgid "xls"
msgstr "XLS (Microsoft Excel)"
#. Default: "frozen"
msgid "frozen"
msgstr "gelé"
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr "(Re-)geler"
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr "Dégeler"
#. Default: "Upload a new file"
msgid "uploadField"
msgstr "Écraser par..."
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr "Bienvenue sur ce site fabriqué avec <a href=\"http://appyframework.org\" target=\"_blank\">Appy</a>"

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock"
msgstr ""
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
msgstr "È sicuro di voler eliminare questo elemento?"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr "È sicuro?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr ""
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr ""
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr "L'elemento è stato cancellato."
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr ""
#. Default: "The page has been unlocked."
msgid "unlock_done"
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc"
msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS"
msgid "ods"
msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls"
msgstr ""
#. Default: "frozen"
msgid "frozen"
msgstr ""
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr ""
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr ""
#. Default: "Upload a new file"
msgid "uploadField"
msgstr ""
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr ""

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock"
msgstr ""
#. Default: "Are you sure you want to delete this element?"
msgid "delete_confirm"
msgstr "Wil u dit element werkelijk verwijderen?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
#. Default: "Are you sure?"
msgid "action_confirm"
msgstr ""
#. Default: "Are you sure you want to unlock this page?"
msgid "unlock_confirm"
msgstr ""
#. Default: "The element has been deleted."
msgid "delete_done"
msgstr "Het element werd verwijderd."
#. Default: "The element has been unlinked."
msgid "unlink_done"
msgstr ""
#. Default: "The page has been unlocked."
msgid "unlock_done"
#. Default: "The action has been performed."
msgid "action_done"
msgstr ""
#. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc"
msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS"
msgid "ods"
msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls"
msgstr ""
#. Default: "frozen"
msgid "frozen"
msgstr ""
#. Default: "(Re-)freeze"
msgid "freezeField"
msgstr ""
#. Default: "Unfreeze"
msgid "unfreezeField"
msgstr ""
#. Default: "Upload a new file"
msgid "uploadField"
msgstr ""
#. Default: "Welcome to this Appy-powered site."
msgid "front_page_text"
msgstr ""

View file

@ -102,9 +102,8 @@ td.search { padding-top: 8px }
width: 350px; z-index : 100; background: white; padding: 8px;
border: 1px solid grey }
.dropdown { display:none; position: absolute; border: 1px solid #cccccc;
background-color: white; padding-top: 4px }
.dropdownMenu { cursor: pointer; padding-right: 4px }
.dropdown a { padding: 0 0.5em }
background-color: white; padding: 3px 4px 0 }
.dropdownMenu { cursor: pointer; padding-right: 4px; font-size: 93% }
.dropdown a:hover { text-decoration: underline }
.list { margin-bottom: 3px }
.list td, .list th { border: 1px solid grey;
@ -156,5 +155,5 @@ td.search { padding-top: 8px }
.homeTable th { padding-top: 5px; font-size: 105% }
.first { margin-top: 0px }
.error { margin: 5px }
.podName { font-size: 90%; padding-left: 3px }
.podName { font-size: 90% }
.podTable { margin-left: 15px }

View file

@ -446,14 +446,14 @@ function triggerTransition(formId, transitionId, msg) {
function onDeleteObject(objectUid) {
f = document.getElementById('deleteForm');
f.objectUid.value = objectUid;
askConfirm('form', 'deleteForm', delete_confirm);
askConfirm('form', 'deleteForm', action_confirm);
}
function onDeleteEvent(objectUid, eventTime) {
f = document.getElementById('deleteEventForm');
f.objectUid.value = objectUid;
f.eventTime.value = eventTime;
askConfirm('form', 'deleteEventForm', delete_confirm);
askConfirm('form', 'deleteEventForm', action_confirm);
}
function onUnlinkObject(sourceUid, fieldName, targetUid) {
@ -461,14 +461,14 @@ function onUnlinkObject(sourceUid, fieldName, targetUid) {
f.sourceUid.value = sourceUid;
f.fieldName.value = fieldName;
f.targetUid.value = targetUid;
askConfirm('form', 'unlinkForm', unlink_confirm);
askConfirm('form', 'unlinkForm', action_confirm);
}
function onUnlockPage(objectUid, pageName) {
f = document.getElementById('unlockForm');
f.objectUid.value = objectUid;
f.pageName.value = pageName;
askConfirm('form', 'unlockForm', unlock_confirm);
askConfirm('form', 'unlockForm', action_confirm);
}
function createCookie(name, value, days) {
@ -521,17 +521,38 @@ function toggleCookie(cookieId) {
}
// Function that allows to generate a document from a pod template.
function generatePodDocument(uid, fieldName, template, podFormat, queryData,
customParams) {
var theForm = document.getElementById("podTemplateForm");
theForm.objectUid.value = uid;
theForm.fieldName.value = fieldName;
theForm.template.value = template;
theForm.podFormat.value = podFormat;
theForm.queryData.value = queryData;
if (customParams) { theForm.customParams.value = customParams; }
else { theForm.customParams.value = ''; }
theForm.submit();
function generatePod(uid,fieldName,template,podFormat,queryData,customParams) {
var f = document.getElementById('podForm');
f.objectUid.value = uid;
f.fieldName.value = fieldName;
f.template.value = template;
f.podFormat.value = podFormat;
f.queryData.value = queryData;
if (customParams) { f.customParams.value = customParams; }
else { f.customParams.value = ''; }
f.action.value = 'generate';
f.submit();
}
// Function that allows to (un-)freeze a document from a pod template.
function freezePod(uid, fieldName, template, podFormat, action) {
var f = document.getElementById('podForm');
f.objectUid.value = uid;
f.fieldName.value = fieldName;
f.template.value = template;
f.podFormat.value = podFormat;
f.action.value = action;
askConfirm('form', 'podForm', action_confirm);
}
// Function that allows to upload a file for freezing it in a od field.
function uploadPod(uid, fieldName, template, podFormat) {
var f = document.getElementById('uploadForm');
f.objectUid.value = uid;
f.fieldName.value = fieldName;
f.template.value = template;
f.podFormat.value = podFormat;
openPopup('uploadPopup');
}
function protectAppyForm() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 475 B

BIN
gen/ui/docFrozen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

BIN
gen/ui/freeze.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

BIN
gen/ui/frozen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 731 B

After

Width:  |  Height:  |  Size: 663 B

BIN
gen/ui/odsFrozen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 774 B

After

Width:  |  Height:  |  Size: 470 B

BIN
gen/ui/odtFrozen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 432 B

BIN
gen/ui/pdfFrozen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

BIN
gen/ui/unfreeze.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

BIN
gen/ui/upload.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

After

Width:  |  Height:  |  Size: 623 B

BIN
gen/ui/xlsFrozen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

View file

@ -128,15 +128,16 @@ class ToolWrapper(AbstractWrapper):
<input type="hidden" name="objectUid"/>
<input type="hidden" name="pageName"/>
</form>
<!-- Global form for generating a document from a pod template -->
<form id="podTemplateForm" name="podTemplateForm" method="post"
action=":ztool.absolute_url() + '/generateDocument'">
<!-- Global form for generating/freezing a document from a pod template -->
<form id="podForm" name="podForm" method="post"
action=":ztool.absolute_url() + '/doPod'">
<input type="hidden" name="objectUid"/>
<input type="hidden" name="fieldName"/>
<input type="hidden" name="template"/>
<input type="hidden" name="podFormat"/>
<input type="hidden" name="queryData"/>
<input type="hidden" name="customParams"/>
<input type="hidden" name="action" value="generate"/>
</form>''')
pxPageBottom = Px('''

View file

@ -123,6 +123,21 @@ class AbstractWrapper(object):
</form>
</div>
<!-- Popup for uploading a file in a pod field -->
<div id="uploadPopup" class="popup" align="center">
<form id="uploadForm" name="uploadForm" enctype="multipart/form-data"
method="post" action=":ztool.absolute_url() + '/uploadPod'">
<input type="hidden" name="objectUid"/>
<input type="hidden" name="fieldName"/>
<input type="hidden" name="template"/>
<input type="hidden" name="podFormat"/>
<input type="file" name="uploadedFile"/><br/><br/>
<input type="submit" value=":_('object_save')"/>
<input type="button" onclick="closePopup('uploadPopup')"
value=":_('object_cancel')"/>
</form>
</div>
<!-- Popup for reinitializing the password -->
<div id="askPasswordReinitPopup" class="popup"
if="isAnon and ztool.showForgotPassword()">
@ -791,19 +806,21 @@ class AbstractWrapper(object):
zopeObj.reindex()
return appyObj
def freeze(self, fieldName, template=None, format='pdf'):
def freeze(self, fieldName, template=None, format='pdf', noSecurity=True,
freezeOdtOnError=True):
'''This method freezes the content of pod field named p_fieldName, for
the given p_template (several templates can be given in
podField.template), in the given p_format ("pdf" by default).'''
field = self.o.getAppyType(fieldName)
if field.type!= 'Pod': raise Exception('Cannot freeze non-Pod field.')
return field.freeze(self, template, format)
return field.freeze(self, template, format, noSecurity=noSecurity,
freezeOdtOnError=freezeOdtOnError)
def unfreeze(self, fieldName, template=None, format='pdf'):
def unfreeze(self, fieldName, template=None, format='pdf', noSecurity=True):
'''This method unfreezes a pod field.'''
field = self.o.getAppyType(fieldName)
if field.type!= 'Pod': raise Exception('Cannot unfreeze non-Pod field.')
field.unfreeze(self, template, format)
field.unfreeze(self, template, format, noSecurity=noSecurity)
def delete(self):
'''Deletes myself.'''