[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="actionType" value="deleteEvent"/>
<input type="hidden" name="day"/> <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 ? --> <!-- Delete successive events ? -->
<div class="discreet" style="margin-bottom: 10px" <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.''' want to put in it. It is the way gen uses pod.'''
# Layout for rendering a POD field for exporting query results. # Layout for rendering a POD field for exporting query results.
rLayouts = {'view': Table('fl', width=None)} 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 ' \ POD_ERROR = 'An error occurred while generating the document. Please ' \
'contact the system administrator.' 'contact the system administrator.'
NO_TEMPLATE = 'Please specify a pod template in field "template".' 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.' TEMPLATE_NOT_FOUND = 'Template not found at %s.'
FREEZE_ERROR = 'Error while trying to freeze a "%s" file in pod field ' \ FREEZE_ERROR = 'Error while trying to freeze a "%s" file in pod field ' \
'"%s" (%s).' '"%s" (%s).'
FREEZE_FATAL_ERROR = 'Server error. Please contact the administrator.' 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(''' pxView = pxCell = Px('''
<table cellpadding="0" cellspacing="0"> <table cellpadding="0" cellspacing="0" var="uid=obj.uid">
<tr> <tr>
<td for="template in field.getVisibleTemplates(obj)"> <td for="info in field.getVisibleTemplates(obj)">
<table cellpadding="0" cellspacing="0" class="podTable"> <table cellpadding="0" cellspacing="0" class="podTable">
<tr> <tr>
<td for="fmt in field.getOutputFormats(obj)"> <td for="fmt in info.formats"
<img src=":url(fmt)" title=":fmt.upper()" class="clickable" var2="freezeAllowed=fmt in info.freezeFormats;
onclick=":'generatePodDocument(%s,%s,%s,%s,%s)' % \ frozen=field.isFrozen(obj, info.template, fmt)">
(q(obj.uid), q(name), q(template), q(fmt), \ <!-- A clickable icon if no freeze action is allowed -->
q(ztool.getQueryInfo()))"/> <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>
<td class="podName">:field.getTemplateName(obj, template)</td> <td class="podName">:field.getTemplateName(obj, info.template)</td>
</tr> </tr>
</table> </table>
</td> </td>
@ -71,7 +118,8 @@ class Pod(Field):
maxChars=None, colspan=1, master=None, masterValue=None, maxChars=None, colspan=1, master=None, masterValue=None,
focus=False, historized=False, mapping=None, label=None, focus=False, historized=False, mapping=None, label=None,
template=None, templateName=None, showTemplate=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). # Param "template" stores the path to the pod template(s).
if not template: raise Exception(Pod.NO_TEMPLATE) if not template: raise Exception(Pod.NO_TEMPLATE)
if isinstance(template, basestring): if isinstance(template, basestring):
@ -89,13 +137,48 @@ class Pod(Field):
# "template" contains several templates and "templateName" is None, Appy # "template" contains several templates and "templateName" is None, Appy
# will produce names from template filenames. # will produce names from template filenames.
self.templateName = templateName self.templateName = templateName
# "showTemplate", if specified, must be a method that will be called # "showTemplate" determines if the current user may generate documents
# with the current template as single arg and that must return True if # based on this pod field. More precisely, "showTemplate", if specified,
# the template can be seen by the current user. "showTemplate" comes in # must be a method that will be called with the current template as
# addition to self.show. self.show dictates the visibility of the whole # single arg (one among self.template) and that must return the list or
# field (ie, all templates from self.template) while "showTemplate" # tuple of formats that the current user may use as output formats for
# dictates the visiblity of a specific template within self.template. # 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 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 # The context is a dict containing a specific pod context, or a method
# that returns such a dict. # that returns such a dict.
self.context = context self.context = context
@ -118,12 +201,11 @@ class Pod(Field):
# field is determined by freezing. # field is determined by freezing.
self.validable = False self.validable = False
def getOutputFormats(self, obj): def getAllFormats(self, template):
'''Returns self.formats, excepted if there is a frozen document: in '''Gets all the outputy formats that are available for a given
this case, only the format of the frozen doc is returned.''' p_template.'''
if not obj.user.has_role('Manager'): return self.formats ext = os.path.splitext(template)[1]
# A manager can have all formats return self.allFormats[ext]
return self.allFormats
def getTemplateName(self, obj, fileName): def getTemplateName(self, obj, fileName):
'''Gets the name of a template given its p_fileName.''' '''Gets the name of a template given its p_fileName.'''
@ -149,14 +231,25 @@ class Pod(Field):
def getVisibleTemplates(self, obj): def getVisibleTemplates(self, obj):
'''Returns, among self.template, the template(s) that can be shown.''' '''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 = [] res = []
for template in self.template: for template in self.template:
if self.showTemplate(obj, template): formats = isManager and self.getAllFormats(template) or \
res.append(template) self.showTemplate(obj, template)
if formats:
res.append(Object(template=template, formats=formats,
freezeFormats=self.getFreezeFormats(obj, template)))
return res 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 '''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 returning a frozen one. A pod field differs from other field types
because there can be several ways to produce the field value (ie: 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] template = template or rq.get('template') or self.template[0]
format = format or rq.get('podFormat') or 'odt' format = format or rq.get('podFormat') or 'odt'
# Security check. # Security check.
if not self.showTemplate(obj, template): if not noSecurity and not self.showTemplate(obj, template):
raise Exception(self.UNAVAILABLE_TEMPLATE) raise Exception(self.UNAUTHORIZED)
# Return the frozen document if frozen. # Return the frozen document if frozen.
frozen = self.isFrozen(obj, template, format) frozen = self.isFrozen(obj, template, format)
if frozen: if frozen:
print 'RETURN FROZEN'
fileName = self.getDownloadName(obj, template, format, False) fileName = self.getDownloadName(obj, template, format, False)
return FileInfo(frozen, inDb=False, uploadName=fileName) return FileInfo(frozen, inDb=False, uploadName=fileName)
# We must call pod to compute a pod document from "template". # 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. # Get a FileInfo instance to manipulate the file on the filesystem.
return FileInfo(result, inDb=False, uploadName=fileName) 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 '''Gets the name on disk on the frozen document corresponding to this
pod field, p_template and p_format.''' pod field, p_template and p_format.'''
template = template or self.template[0] template = template or self.template[0]
templateName = os.path.splitext(template)[0].replace(os.sep, '_') 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'): def isFrozen(self, obj, template=None, format='pdf'):
'''Is there a frozen document for thid pod field, on p_obj, for '''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) res = os.path.join(dbFolder, folder, fileName)
if os.path.exists(res): return res 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 '''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 # Compute the absolute path where to store the frozen document in the
# database. # database.
dbFolder, folder = obj.o.getFsFolder(create=True) dbFolder, folder = obj.o.getFsFolder(create=True)
@ -282,12 +383,12 @@ class Pod(Field):
if os.path.exists(result): if os.path.exists(result):
obj.log('Freeze: overwriting %s...' % result) obj.log('Freeze: overwriting %s...' % result)
# Generate the document. # Generate the document.
doc = self.getValue(obj, template=template, format=format, doc = self.getValue(obj, template=template, format=format,result=result)
result=result)
if isinstance(doc, basestring): if isinstance(doc, basestring):
# An error occurred, the document was not generated. # An error occurred, the document was not generated.
obj.log(self.FREEZE_ERROR % (format, self.name, doc), type='error') 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...') obj.log('Trying to freeze the ODT version...')
# Try to freeze the ODT version of the document, which does not # Try to freeze the ODT version of the document, which does not
# require to call LibreOffice: the risk of error is smaller. # require to call LibreOffice: the risk of error is smaller.
@ -303,12 +404,35 @@ class Pod(Field):
raise Exception(self.FREEZE_FATAL_ERROR) raise Exception(self.FREEZE_FATAL_ERROR)
return doc 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 '''Unfreezes, on p_obj, the document for this pod field, for p_template
in p_format.''' 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. # Compute the absolute path to the frozen doc.
dbFolder, folder = obj.o.getFsFolder() dbFolder, folder = obj.o.getFsFolder()
fileName = self.getFreezeName(template, format) fileName = self.getFreezeName(template, format)
frozenName = os.path.join(dbFolder, folder, fileName) frozenName = os.path.join(dbFolder, folder, fileName)
if os.path.exists(frozenName): os.remove(frozenName) 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. # PX that displays referred objects as menus.
pxViewMenus = Px(''' pxViewMenus = Px('''
<table><tr style="font-size: 93%"> <table><tr valign="bottom">
<td for="menu in field.getLinkedObjectsByMenu(obj, zobjects)"> <td for="menu in field.getLinkedObjectsByMenu(obj, zobjects)">
<!-- A single object in the menu: show a clickable icon to get it --> <!-- 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) --> <!-- Display the number of objects in the menu (if more than one) -->
<x if="len(menu.zobjects) &gt; 1">:len(menu.zobjects)</x> <x if="len(menu.zobjects) &gt; 1">:len(menu.zobjects)</x>
<!-- The dropdown menu containing annexes --> <!-- The dropdown menu containing annexes -->
<div class="dropdown" id=":dropdownId"> <div id=":dropdownId" class="dropdown">
<div for="ztied in menu.zobjects" <div for="ztied in menu.zobjects"
var2="ztiedUrl=field.getMenuUrl(zobj, ztied)"> var2="ztiedUrl=field.getMenuUrl(zobj, ztied)">
<a href=":ztiedUrl">:ztied.title</a> <a href=":ztiedUrl">:ztied.title</a>

View file

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

View file

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

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock" msgid "page_unlock"
msgstr "" msgstr ""
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "" msgstr ""
#. Default: "Are you sure you want to unlink this element?" #. Default: "The action has been performed."
msgid "unlink_confirm" msgid "action_done"
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"
msgstr "" msgstr ""
#. Default: "Go to top" #. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr ""
msgid "doc" msgid "doc"
msgstr "" msgstr ""
#. Default: "RTF"
msgid "rtf"
msgstr ""
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "" msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls" msgid "xls"
msgstr "" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "" msgstr ""

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock" msgid "page_unlock"
msgstr "" msgstr ""
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "" msgstr ""
#. Default: "Are you sure you want to unlink this element?" #. Default: "The action has been performed."
msgid "unlink_confirm" msgid "action_done"
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"
msgstr "" msgstr ""
#. Default: "Go to top" #. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr ""
msgid "doc" msgid "doc"
msgstr "" msgstr ""
#. Default: "RTF"
msgid "rtf"
msgstr ""
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "" msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls" msgid "xls"
msgstr "" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "" msgstr ""

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock" msgid "page_unlock"
msgstr "" msgstr ""
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "Wollen Sie dieses Element wirklich entfernen?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr "" msgstr ""
#. Default: "Are you sure you want to unlock this page?" #. Default: "The action has been performed."
msgid "unlock_confirm" msgid "action_done"
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"
msgstr "" msgstr ""
#. Default: "Go to top" #. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc" msgid "doc"
msgstr "DOC (Microsoft Word)" msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "" msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls" msgid "xls"
msgstr "" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "" msgstr ""

View file

@ -204,29 +204,13 @@ msgstr "Unlink"
msgid "page_unlock" msgid "page_unlock"
msgstr "Unlock" msgstr "Unlock"
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "Are you sure you want to delete this element?" msgstr ""
#. Default: "Are you sure you want to unlink this element?" #. Default: "The action has been performed."
msgid "unlink_confirm" msgid "action_done"
msgstr "Are you sure you want to unlink this element?" msgstr ""
#. 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: "Go to top" #. Default: "Go to top"
msgid "goto_first" msgid "goto_first"
@ -288,10 +272,6 @@ msgstr "PDF"
msgid "doc" msgid "doc"
msgstr "DOC" msgstr "DOC"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF"
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "ODS" msgstr "ODS"
@ -300,6 +280,22 @@ msgstr "ODS"
msgid "xls" msgid "xls"
msgstr "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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "Welcome to this Appy-powered site." msgstr "Welcome to this Appy-powered site."

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock" msgid "page_unlock"
msgstr "" msgstr ""
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "¿Está seguro de querer suprimir ese elemento?" msgstr "¿Está seguro?"
#. Default: "Are you sure you want to unlink this element?" #. Default: "The action has been performed."
msgid "unlink_confirm" msgid "action_done"
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"
msgstr "" msgstr ""
#. Default: "Go to top" #. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc" msgid "doc"
msgstr "DOC (Microsoft Word)" msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "" msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls" msgid "xls"
msgstr "" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "" msgstr ""

View file

@ -204,29 +204,13 @@ msgstr "Dissocier"
msgid "page_unlock" msgid "page_unlock"
msgstr "Déverrouiller" msgstr "Déverrouiller"
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "Êtes-vous sûr de vouloir supprimer cet élément?" msgstr "Êtes-vous sûr?"
#. Default: "Are you sure you want to unlink this element?" #. Default: "The action has been performed."
msgid "unlink_confirm" msgid "action_done"
msgstr "Êtes-vous sûr de vouloir dissocier cet élément?" msgstr "L'action a été réalisée."
#. 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: "Go to top" #. Default: "Go to top"
msgid "goto_first" msgid "goto_first"
@ -288,10 +272,6 @@ msgstr "PDF"
msgid "doc" msgid "doc"
msgstr "DOC (Microsoft Word)" msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "ODS (LibreOffice Calc)" msgstr "ODS (LibreOffice Calc)"
@ -300,6 +280,22 @@ msgstr "ODS (LibreOffice Calc)"
msgid "xls" msgid "xls"
msgstr "XLS (Microsoft Excel)" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "Bienvenue sur ce site fabriqué avec <a href=\"http://appyframework.org\" target=\"_blank\">Appy</a>" 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" msgid "page_unlock"
msgstr "" msgstr ""
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "È sicuro di voler eliminare questo elemento?" msgstr "È sicuro?"
#. Default: "Are you sure you want to unlink this element?" #. Default: "The action has been performed."
msgid "unlink_confirm" msgid "action_done"
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"
msgstr "" msgstr ""
#. Default: "Go to top" #. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc" msgid "doc"
msgstr "DOC (Microsoft Word)" msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "" msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls" msgid "xls"
msgstr "" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "" msgstr ""

View file

@ -203,28 +203,12 @@ msgstr ""
msgid "page_unlock" msgid "page_unlock"
msgstr "" msgstr ""
#. Default: "Are you sure you want to delete this element?" #. Default: "Are you sure?"
msgid "delete_confirm" msgid "action_confirm"
msgstr "Wil u dit element werkelijk verwijderen?"
#. Default: "Are you sure you want to unlink this element?"
msgid "unlink_confirm"
msgstr "" msgstr ""
#. Default: "Are you sure you want to unlock this page?" #. Default: "The action has been performed."
msgid "unlock_confirm" msgid "action_done"
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"
msgstr "" msgstr ""
#. Default: "Go to top" #. Default: "Go to top"
@ -287,10 +271,6 @@ msgstr "PDF"
msgid "doc" msgid "doc"
msgstr "DOC (Microsoft Word)" msgstr "DOC (Microsoft Word)"
#. Default: "RTF"
msgid "rtf"
msgstr "RTF (Rich Text)"
#. Default: "ODS" #. Default: "ODS"
msgid "ods" msgid "ods"
msgstr "" msgstr ""
@ -299,6 +279,22 @@ msgstr ""
msgid "xls" msgid "xls"
msgstr "" 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." #. Default: "Welcome to this Appy-powered site."
msgid "front_page_text" msgid "front_page_text"
msgstr "" msgstr ""

View file

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

View file

@ -446,14 +446,14 @@ function triggerTransition(formId, transitionId, msg) {
function onDeleteObject(objectUid) { function onDeleteObject(objectUid) {
f = document.getElementById('deleteForm'); f = document.getElementById('deleteForm');
f.objectUid.value = objectUid; f.objectUid.value = objectUid;
askConfirm('form', 'deleteForm', delete_confirm); askConfirm('form', 'deleteForm', action_confirm);
} }
function onDeleteEvent(objectUid, eventTime) { function onDeleteEvent(objectUid, eventTime) {
f = document.getElementById('deleteEventForm'); f = document.getElementById('deleteEventForm');
f.objectUid.value = objectUid; f.objectUid.value = objectUid;
f.eventTime.value = eventTime; f.eventTime.value = eventTime;
askConfirm('form', 'deleteEventForm', delete_confirm); askConfirm('form', 'deleteEventForm', action_confirm);
} }
function onUnlinkObject(sourceUid, fieldName, targetUid) { function onUnlinkObject(sourceUid, fieldName, targetUid) {
@ -461,14 +461,14 @@ function onUnlinkObject(sourceUid, fieldName, targetUid) {
f.sourceUid.value = sourceUid; f.sourceUid.value = sourceUid;
f.fieldName.value = fieldName; f.fieldName.value = fieldName;
f.targetUid.value = targetUid; f.targetUid.value = targetUid;
askConfirm('form', 'unlinkForm', unlink_confirm); askConfirm('form', 'unlinkForm', action_confirm);
} }
function onUnlockPage(objectUid, pageName) { function onUnlockPage(objectUid, pageName) {
f = document.getElementById('unlockForm'); f = document.getElementById('unlockForm');
f.objectUid.value = objectUid; f.objectUid.value = objectUid;
f.pageName.value = pageName; f.pageName.value = pageName;
askConfirm('form', 'unlockForm', unlock_confirm); askConfirm('form', 'unlockForm', action_confirm);
} }
function createCookie(name, value, days) { function createCookie(name, value, days) {
@ -521,17 +521,38 @@ function toggleCookie(cookieId) {
} }
// Function that allows to generate a document from a pod template. // Function that allows to generate a document from a pod template.
function generatePodDocument(uid, fieldName, template, podFormat, queryData, function generatePod(uid,fieldName,template,podFormat,queryData,customParams) {
customParams) { var f = document.getElementById('podForm');
var theForm = document.getElementById("podTemplateForm"); f.objectUid.value = uid;
theForm.objectUid.value = uid; f.fieldName.value = fieldName;
theForm.fieldName.value = fieldName; f.template.value = template;
theForm.template.value = template; f.podFormat.value = podFormat;
theForm.podFormat.value = podFormat; f.queryData.value = queryData;
theForm.queryData.value = queryData; if (customParams) { f.customParams.value = customParams; }
if (customParams) { theForm.customParams.value = customParams; } else { f.customParams.value = ''; }
else { theForm.customParams.value = ''; } f.action.value = 'generate';
theForm.submit(); 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() { 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="objectUid"/>
<input type="hidden" name="pageName"/> <input type="hidden" name="pageName"/>
</form> </form>
<!-- Global form for generating a document from a pod template --> <!-- Global form for generating/freezing a document from a pod template -->
<form id="podTemplateForm" name="podTemplateForm" method="post" <form id="podForm" name="podForm" method="post"
action=":ztool.absolute_url() + '/generateDocument'"> action=":ztool.absolute_url() + '/doPod'">
<input type="hidden" name="objectUid"/> <input type="hidden" name="objectUid"/>
<input type="hidden" name="fieldName"/> <input type="hidden" name="fieldName"/>
<input type="hidden" name="template"/> <input type="hidden" name="template"/>
<input type="hidden" name="podFormat"/> <input type="hidden" name="podFormat"/>
<input type="hidden" name="queryData"/> <input type="hidden" name="queryData"/>
<input type="hidden" name="customParams"/> <input type="hidden" name="customParams"/>
<input type="hidden" name="action" value="generate"/>
</form>''') </form>''')
pxPageBottom = Px(''' pxPageBottom = Px('''

View file

@ -123,6 +123,21 @@ class AbstractWrapper(object):
</form> </form>
</div> </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 --> <!-- Popup for reinitializing the password -->
<div id="askPasswordReinitPopup" class="popup" <div id="askPasswordReinitPopup" class="popup"
if="isAnon and ztool.showForgotPassword()"> if="isAnon and ztool.showForgotPassword()">
@ -791,19 +806,21 @@ class AbstractWrapper(object):
zopeObj.reindex() zopeObj.reindex()
return appyObj 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 '''This method freezes the content of pod field named p_fieldName, for
the given p_template (several templates can be given in the given p_template (several templates can be given in
podField.template), in the given p_format ("pdf" by default).''' podField.template), in the given p_format ("pdf" by default).'''
field = self.o.getAppyType(fieldName) field = self.o.getAppyType(fieldName)
if field.type!= 'Pod': raise Exception('Cannot freeze non-Pod field.') 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.''' '''This method unfreezes a pod field.'''
field = self.o.getAppyType(fieldName) field = self.o.getAppyType(fieldName)
if field.type!= 'Pod': raise Exception('Cannot unfreeze non-Pod field.') 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): def delete(self):
'''Deletes myself.''' '''Deletes myself.'''