Fixed bug #394258 and added a new skin directly within Appy, such that every generated product does not need to include copies of Appy images and web pages.
|
@ -1 +1,3 @@
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
def getPath(): return os.path.dirname(__file__)
|
||||||
|
|
0
gen/plone25/__init__.py
Executable file → Normal file
0
gen/plone25/descriptors.py
Executable file → Normal file
55
gen/plone25/generator.py
Executable file → Normal file
|
@ -15,10 +15,6 @@ from descriptors import ArchetypeFieldDescriptor, ArchetypesClassDescriptor, \
|
||||||
|
|
||||||
# Common methods that need to be defined on every Archetype class --------------
|
# Common methods that need to be defined on every Archetype class --------------
|
||||||
COMMON_METHODS = '''
|
COMMON_METHODS = '''
|
||||||
def at_post_create_script(self): self._appy_onEdit(True)
|
|
||||||
def at_post_edit_script(self): self._appy_onEdit(False)
|
|
||||||
def post_validate(self, REQUEST=None, errors=None):
|
|
||||||
if not errors: self._appy_validateAllFields(REQUEST, errors)
|
|
||||||
def getTool(self): return self.%s
|
def getTool(self): return self.%s
|
||||||
def getProductConfig(self): return Products.%s.config
|
def getProductConfig(self): return Products.%s.config
|
||||||
'''
|
'''
|
||||||
|
@ -50,7 +46,6 @@ class Generator(AbstractGenerator):
|
||||||
'portletName': self.portletName, 'queryName': self.queryName,
|
'portletName': self.portletName, 'queryName': self.queryName,
|
||||||
'toolInstanceName': self.toolInstanceName,
|
'toolInstanceName': self.toolInstanceName,
|
||||||
'podTemplateName': self.podTemplateName,
|
'podTemplateName': self.podTemplateName,
|
||||||
'macros': '%s_macros' % self.applicationName.lower(),
|
|
||||||
'commonMethods': commonMethods})
|
'commonMethods': commonMethods})
|
||||||
# Predefined class descriptors
|
# Predefined class descriptors
|
||||||
self.toolDescr = ToolClassDescriptor(Tool, self)
|
self.toolDescr = ToolClassDescriptor(Tool, self)
|
||||||
|
@ -117,14 +112,12 @@ class Generator(AbstractGenerator):
|
||||||
msg('bad_alphanumeric', '', msg.BAD_ALPHANUMERIC),
|
msg('bad_alphanumeric', '', msg.BAD_ALPHANUMERIC),
|
||||||
]
|
]
|
||||||
# Create basic files (config.py, Install.py, etc)
|
# Create basic files (config.py, Install.py, etc)
|
||||||
self.generateAppyReference()
|
|
||||||
self.generateTool()
|
self.generateTool()
|
||||||
self.generateConfig()
|
self.generateConfig()
|
||||||
self.generateInit()
|
self.generateInit()
|
||||||
self.generateInstall()
|
self.generateInstall()
|
||||||
self.generateWorkflows()
|
self.generateWorkflows()
|
||||||
self.generateWrappers()
|
self.generateWrappers()
|
||||||
self.generatePortlet()
|
|
||||||
if self.config.frontPage == True:
|
if self.config.frontPage == True:
|
||||||
self.labels.append(msg('front_page_text', '', msg.FRONT_PAGE_TEXT))
|
self.labels.append(msg('front_page_text', '', msg.FRONT_PAGE_TEXT))
|
||||||
self.copyFile('frontPage.pt', self.repls,
|
self.copyFile('frontPage.pt', self.repls,
|
||||||
|
@ -135,20 +128,11 @@ class Generator(AbstractGenerator):
|
||||||
destFolder='profiles/default')
|
destFolder='profiles/default')
|
||||||
self.copyFile('ProfileInit.py', self.repls, destFolder='profiles',
|
self.copyFile('ProfileInit.py', self.repls, destFolder='profiles',
|
||||||
destName='__init__.py')
|
destName='__init__.py')
|
||||||
|
self.copyFile('Portlet.pt', self.repls,
|
||||||
|
destName='%s.pt' % self.portletName, destFolder=self.skinsFolder)
|
||||||
self.copyFile('tool.gif', {})
|
self.copyFile('tool.gif', {})
|
||||||
self.copyFile('Macros.pt', self.repls, destFolder=self.skinsFolder,
|
|
||||||
destName='%s_macros.pt' % self.applicationName.lower())
|
|
||||||
self.copyFile('appy_view.pt', self.repls, destFolder=self.skinsFolder,
|
|
||||||
destName='%s_appy_view.pt' % self.applicationName)
|
|
||||||
self.copyFile('appy_edit.cpt', self.repls, destFolder=self.skinsFolder,
|
|
||||||
destName='%s_appy_edit.cpt' % self.applicationName)
|
|
||||||
self.copyFile('appy_edit.cpt.metadata', self.repls,
|
|
||||||
destFolder=self.skinsFolder,
|
|
||||||
destName='%s_appy_edit.cpt.metadata'%self.applicationName)
|
|
||||||
self.copyFile('Styles.css.dtml', self.repls, destFolder=self.skinsFolder,
|
self.copyFile('Styles.css.dtml', self.repls, destFolder=self.skinsFolder,
|
||||||
destName = '%s.css.dtml' % self.applicationName)
|
destName = '%s.css.dtml' % self.applicationName)
|
||||||
self.copyFile('do.py', self.repls, destFolder=self.skinsFolder,
|
|
||||||
destName='%s_do.py' % self.applicationName)
|
|
||||||
if self.config.minimalistPlone:
|
if self.config.minimalistPlone:
|
||||||
self.copyFile('colophon.pt', self.repls,destFolder=self.skinsFolder)
|
self.copyFile('colophon.pt', self.repls,destFolder=self.skinsFolder)
|
||||||
self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder)
|
self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder)
|
||||||
|
@ -241,18 +225,6 @@ class Generator(AbstractGenerator):
|
||||||
self.referers[refClassName] = []
|
self.referers[refClassName] = []
|
||||||
self.referers[refClassName].append( (fieldDescr, relationship))
|
self.referers[refClassName].append( (fieldDescr, relationship))
|
||||||
|
|
||||||
def generatePortlet(self):
|
|
||||||
rootClasses = ''
|
|
||||||
for classDescr in self.classes:
|
|
||||||
if classDescr.isRoot():
|
|
||||||
rootClasses += "'%s'," % classDescr.name
|
|
||||||
repls = self.repls.copy()
|
|
||||||
repls['rootClasses'] = rootClasses
|
|
||||||
self.copyFile('Portlet.pt', repls, destName='%s.pt' % self.portletName,
|
|
||||||
destFolder=self.skinsFolder)
|
|
||||||
self.copyFile('Query.pt', repls, destName='%s.pt' % self.queryName,
|
|
||||||
destFolder=self.skinsFolder)
|
|
||||||
|
|
||||||
def generateConfig(self):
|
def generateConfig(self):
|
||||||
# Compute referers
|
# Compute referers
|
||||||
referers = ''
|
referers = ''
|
||||||
|
@ -299,6 +271,11 @@ class Generator(AbstractGenerator):
|
||||||
theImport = 'import %s' % classDescr.klass.__module__
|
theImport = 'import %s' % classDescr.klass.__module__
|
||||||
if theImport not in imports:
|
if theImport not in imports:
|
||||||
imports.append(theImport)
|
imports.append(theImport)
|
||||||
|
# Compute root classes
|
||||||
|
rootClasses = ''
|
||||||
|
for classDescr in self.classes:
|
||||||
|
if classDescr.isRoot():
|
||||||
|
rootClasses += "'%s'," % classDescr.name
|
||||||
# Compute list of add permissions
|
# Compute list of add permissions
|
||||||
addPermissions = ''
|
addPermissions = ''
|
||||||
for classDescr in self.classes:
|
for classDescr in self.classes:
|
||||||
|
@ -308,6 +285,7 @@ class Generator(AbstractGenerator):
|
||||||
# Compute list of used roles for registering them if needed
|
# Compute list of used roles for registering them if needed
|
||||||
repls['roles'] = ','.join(['"%s"' % r for r in \
|
repls['roles'] = ','.join(['"%s"' % r for r in \
|
||||||
self.getAllUsedRoles(appOnly=True)])
|
self.getAllUsedRoles(appOnly=True)])
|
||||||
|
repls['rootClasses'] = rootClasses
|
||||||
repls['referers'] = referers
|
repls['referers'] = referers
|
||||||
repls['workflowInstancesInit'] = wfInit
|
repls['workflowInstancesInit'] = wfInit
|
||||||
repls['imports'] = '\n'.join(imports)
|
repls['imports'] = '\n'.join(imports)
|
||||||
|
@ -615,23 +593,6 @@ class Generator(AbstractGenerator):
|
||||||
repls['wrapperClass'] = '%s_Wrapper' % self.podTemplateDescr.name
|
repls['wrapperClass'] = '%s_Wrapper' % self.podTemplateDescr.name
|
||||||
self.copyFile('PodTemplate.py', repls,
|
self.copyFile('PodTemplate.py', repls,
|
||||||
destName='%s.py' % self.podTemplateName)
|
destName='%s.py' % self.podTemplateName)
|
||||||
for imgName in PodTemplate.podFormat.validator:
|
|
||||||
self.copyFile('%s.png' % imgName, {},
|
|
||||||
destFolder=self.skinsFolder)
|
|
||||||
|
|
||||||
refFiles = ('createAppyObject.cpy', 'createAppyObject.cpy.metadata',
|
|
||||||
'arrowUp.png', 'arrowDown.png', 'plus.png', 'appyConfig.gif',
|
|
||||||
'nextPhase.png', 'nextState.png', 'done.png', 'current.png')
|
|
||||||
prefixedRefFiles = ('AppyReference.pt',)
|
|
||||||
def generateAppyReference(self):
|
|
||||||
'''Generates what is needed to use Appy-specific references.'''
|
|
||||||
# Some i18n messages
|
|
||||||
Msg = PoMessage
|
|
||||||
for refFile in self.prefixedRefFiles:
|
|
||||||
self.copyFile(refFile, self.repls, destFolder=self.skinsFolder,
|
|
||||||
destName='%s%s' % (self.applicationName, refFile))
|
|
||||||
for refFile in self.refFiles:
|
|
||||||
self.copyFile(refFile, self.repls, destFolder=self.skinsFolder)
|
|
||||||
|
|
||||||
def generateClass(self, classDescr):
|
def generateClass(self, classDescr):
|
||||||
'''Is called each time an Appy class is found in the application, for
|
'''Is called each time an Appy class is found in the application, for
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import os, os.path
|
import os, os.path
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
from sets import Set
|
from sets import Set
|
||||||
|
import appy
|
||||||
from appy.gen.utils import produceNiceMessage
|
from appy.gen.utils import produceNiceMessage
|
||||||
from appy.gen.plone25.utils import updateRolesForPermission
|
from appy.gen.plone25.utils import updateRolesForPermission
|
||||||
|
|
||||||
|
@ -36,8 +37,7 @@ class PloneInstaller:
|
||||||
self.ploneStuff = ploneStuff # A dict of some Plone functions or vars
|
self.ploneStuff = ploneStuff # A dict of some Plone functions or vars
|
||||||
self.toLog = StringIO()
|
self.toLog = StringIO()
|
||||||
self.typeAliases = {'sharing': '', 'gethtml': '',
|
self.typeAliases = {'sharing': '', 'gethtml': '',
|
||||||
'(Default)': '%s_appy_view' % self.productName,
|
'(Default)': 'skyn/view', 'edit': 'skyn/edit',
|
||||||
'edit': '%s_appy_edit' % self.productName,
|
|
||||||
'index.html': '', 'properties': '', 'view': ''}
|
'index.html': '', 'properties': '', 'view': ''}
|
||||||
self.tool = None # The Plone version of the application tool
|
self.tool = None # The Plone version of the application tool
|
||||||
self.appyTool = None # The Appy version of the application tool
|
self.appyTool = None # The Appy version of the application tool
|
||||||
|
@ -96,7 +96,9 @@ class PloneInstaller:
|
||||||
def installRootFolder(self):
|
def installRootFolder(self):
|
||||||
'''Creates and/or configures, at the root of the Plone site and if
|
'''Creates and/or configures, at the root of the Plone site and if
|
||||||
needed, the folder where the application will store instances of
|
needed, the folder where the application will store instances of
|
||||||
root classes.'''
|
root classes. Creates also the 'appy' folder (more precisely,
|
||||||
|
a Filesystem Directory View) at the root of the site, for storing
|
||||||
|
appy-wide ZPTs an images.'''
|
||||||
# Register first our own Appy folder type if needed.
|
# Register first our own Appy folder type if needed.
|
||||||
site = self.ploneSite
|
site = self.ploneSite
|
||||||
if not hasattr(site.portal_types, self.appyFolderType):
|
if not hasattr(site.portal_types, self.appyFolderType):
|
||||||
|
@ -130,6 +132,10 @@ class PloneInstaller:
|
||||||
# have the main permission "Add portal content".
|
# have the main permission "Add portal content".
|
||||||
updateRolesForPermission('Add portal content', tuple(allCreators),
|
updateRolesForPermission('Add portal content', tuple(allCreators),
|
||||||
appFolder)
|
appFolder)
|
||||||
|
# Creates the "appy" Directory view
|
||||||
|
if not hasattr(site.aq_base, 'appy'):
|
||||||
|
addDirView = self.ploneStuff['manage_addDirectoryView']
|
||||||
|
addDirView(site, appy.getPath() + '/gen/plone25/skin',id='skyn')
|
||||||
|
|
||||||
def installTypes(self):
|
def installTypes(self):
|
||||||
'''Registers and configures the Plone content types that correspond to
|
'''Registers and configures the Plone content types that correspond to
|
||||||
|
@ -154,10 +160,10 @@ class PloneInstaller:
|
||||||
typeActions = typeInfo.listActions()
|
typeActions = typeInfo.listActions()
|
||||||
for action in typeActions:
|
for action in typeActions:
|
||||||
if action.id == 'view':
|
if action.id == 'view':
|
||||||
page = '%s_appy_view' % self.productName
|
page = 'skyn/view'
|
||||||
action.edit(action='string:${object_url}/%s' % page)
|
action.edit(action='string:${object_url}/%s' % page)
|
||||||
elif action.id == 'edit':
|
elif action.id == 'edit':
|
||||||
page = '%s_appy_edit' % self.productName
|
page = 'skyn/edit'
|
||||||
action.edit(action='string:${object_url}/%s' % page)
|
action.edit(action='string:${object_url}/%s' % page)
|
||||||
|
|
||||||
# Configure types for instance creation through portal_factory
|
# Configure types for instance creation through portal_factory
|
||||||
|
@ -459,8 +465,10 @@ class ZopeInstaller:
|
||||||
|
|
||||||
def installApplication(self):
|
def installApplication(self):
|
||||||
'''Performs some application-wide installation steps.'''
|
'''Performs some application-wide installation steps.'''
|
||||||
self.ploneStuff['DirectoryView'].registerDirectory('skins',
|
register = self.ploneStuff['DirectoryView'].registerDirectory
|
||||||
self.ploneStuff['product_globals'])
|
register('skins', self.ploneStuff['product_globals'])
|
||||||
|
# Register the appy skin folder among DirectoryView'able folders
|
||||||
|
register('skin', appy.getPath() + '/gen/plone25')
|
||||||
|
|
||||||
def installTool(self):
|
def installTool(self):
|
||||||
'''Installs the tool.'''
|
'''Installs the tool.'''
|
||||||
|
|
|
@ -86,6 +86,10 @@ class ToolMixin(AbstractMixin):
|
||||||
appName = self.getProductConfig().PROJECTNAME
|
appName = self.getProductConfig().PROJECTNAME
|
||||||
return getattr(portal, appName)
|
return getattr(portal, appName)
|
||||||
|
|
||||||
|
def getRootClasses(self):
|
||||||
|
'''Returns the list of root classes for this application.'''
|
||||||
|
return self.getProductConfig().rootClasses
|
||||||
|
|
||||||
def showPortlet(self):
|
def showPortlet(self):
|
||||||
return not self.portal_membership.isAnonymousUser()
|
return not self.portal_membership.isAnonymousUser()
|
||||||
|
|
||||||
|
@ -194,4 +198,12 @@ class ToolMixin(AbstractMixin):
|
||||||
self.portal_url.getPortalPath()
|
self.portal_url.getPortalPath()
|
||||||
appName = self.getProductConfig().PROJECTNAME
|
appName = self.getProductConfig().PROJECTNAME
|
||||||
return self.utranslate(label, self.translationMapping, domain=appName)
|
return self.utranslate(label, self.translationMapping, domain=appName)
|
||||||
|
|
||||||
|
def getPublishedObject(self):
|
||||||
|
'''Gets the currently published object.'''
|
||||||
|
rq = self.REQUEST
|
||||||
|
obj = rq['PUBLISHED']
|
||||||
|
parent = obj.getParentNode()
|
||||||
|
if parent.id == 'skyn': return parent.getParentNode()
|
||||||
|
return rq['PUBLISHED']
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -20,38 +20,91 @@ class AbstractMixin:
|
||||||
inherits from this class. It contains basic functions allowing to
|
inherits from this class. It contains basic functions allowing to
|
||||||
minimize the amount of generated code.'''
|
minimize the amount of generated code.'''
|
||||||
|
|
||||||
def content_edit_impl(self, state, id):
|
def createOrUpdate(self, created):
|
||||||
'''This method is called by the Plone machinery every time an object
|
'''This method creates (if p_created is True) or updates an object.
|
||||||
must be created or edited through the edit view.'''
|
In the case of an object creation, p_self is a temporary object
|
||||||
|
created in the request by portal_factory, and this method creates
|
||||||
|
the corresponding final object. In the case of an update, this
|
||||||
|
method simply updates fields of p_self.'''
|
||||||
rq = self.REQUEST
|
rq = self.REQUEST
|
||||||
newSelf = self.portal_factory.doCreate(self, id)
|
obj = self
|
||||||
newSelf.processForm()
|
if created:
|
||||||
|
obj = self.portal_factory.doCreate(self, self.id) # portal_factory
|
||||||
|
# creates the final object from the temp object.
|
||||||
|
obj.processForm()
|
||||||
|
|
||||||
# Get the current language and put it in the request
|
# Get the current language and put it in the request
|
||||||
if rq.form.has_key('current_lang'):
|
if rq.form.has_key('current_lang'):
|
||||||
rq.form['language'] = rq.form.get('current_lang')
|
rq.form['language'] = rq.form.get('current_lang')
|
||||||
|
|
||||||
# Generate the message returned to the user after creation/edition
|
# Manage references
|
||||||
portal_status_message = self.translate(
|
obj._appy_manageRefs(created)
|
||||||
msgid='message_content_changes_saved',
|
if obj.wrapperClass:
|
||||||
default='Content changes saved.')
|
# Get the wrapper first
|
||||||
portal_status_message = rq.get(
|
appyWrapper = obj._appy_getWrapper(force=True)
|
||||||
'portal_status_message', portal_status_message)
|
# Call the custom "onEdit" if available
|
||||||
|
try:
|
||||||
|
appyWrapper.onEdit(created)
|
||||||
|
except AttributeError, ae:
|
||||||
|
pass
|
||||||
|
# Manage "add" permissions
|
||||||
|
obj._appy_managePermissions()
|
||||||
|
# Re/unindex object
|
||||||
|
if obj._appy_meta_type == 'tool': self.unindexObject()
|
||||||
|
else: obj.reindexObject()
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def onUpdate(self):
|
||||||
|
'''This method is executed when a user wants to update an object.
|
||||||
|
The object may be a temporary object created by portal_factory in
|
||||||
|
the request. In this case, the update consists in the creation of
|
||||||
|
the "final" object in the database. If the object is not a temporary
|
||||||
|
one, this method updates its fields in the database.'''
|
||||||
|
rq = self.REQUEST
|
||||||
|
errors = {}
|
||||||
|
errorMessage = self.translate(
|
||||||
|
'Please correct the indicated errors.', domain='plone')
|
||||||
|
|
||||||
# What page must I display next ?
|
# Go back to the consult view if the user clicked on 'Cancel'
|
||||||
previousClicked = rq.get('form_previous', None)
|
if rq.get('buttonCancel', None):
|
||||||
nextClicked = rq.get('form_next', None)
|
urlBack = '%s/skyn/view?phase=%s&pageName=%s' % (
|
||||||
if previousClicked or nextClicked:
|
self.absolute_url(), rq.get('phase'), rq.get('pageName'))
|
||||||
# We must redirect the user to the previous or next page
|
self.plone_utils.addPortalMessage(
|
||||||
targetPage = rq.get('nextPage', None)
|
self.translate('Changes canceled.', domain='plone'))
|
||||||
if previousClicked:
|
return rq.RESPONSE.redirect(urlBack)
|
||||||
targetPage = rq.get('previousPage', None)
|
|
||||||
return state.set(status='next_schemata', context=newSelf,
|
# Trigger field-specific validation
|
||||||
fieldset=targetPage,
|
self.validate(REQUEST=rq, errors=errors, data=1, metadata=0)
|
||||||
portal_status_message=portal_status_message)
|
if errors:
|
||||||
|
rq.set('errors', errors)
|
||||||
|
self.plone_utils.addPortalMessage(errorMessage)
|
||||||
|
return self.skyn.edit(self)
|
||||||
else:
|
else:
|
||||||
return state.set(status='success', context=newSelf,
|
# Trigger inter-field validation
|
||||||
portal_status_message=portal_status_message)
|
self.validateAllFields(rq, errors)
|
||||||
|
if errors:
|
||||||
|
rq.set('errors', errors)
|
||||||
|
self.plone_utils.addPortalMessage(errorMessage)
|
||||||
|
return self.skyn.edit(self)
|
||||||
|
else:
|
||||||
|
# Create or update the object in the database
|
||||||
|
obj = self.createOrUpdate(rq.get('is_new') == 'True')
|
||||||
|
# Redirect the user to the appropriate page
|
||||||
|
if rq.get('buttonOk', None):
|
||||||
|
# Go to the consult view for this object
|
||||||
|
obj.plone_utils.addPortalMessage(
|
||||||
|
obj.translate('Changes saved.', domain='plone'))
|
||||||
|
urlBack = '%s/skyn/view?phase=%s&pageName=%s' % (
|
||||||
|
obj.absolute_url(), rq.get('phase'), rq.get('pageName'))
|
||||||
|
return rq.RESPONSE.redirect(urlBack)
|
||||||
|
elif rq.get('buttonPrevious', None):
|
||||||
|
# Go to the edit view (previous page) for this object
|
||||||
|
rq.set('fieldset', rq.get('previousPage'))
|
||||||
|
return obj.skyn.edit(obj)
|
||||||
|
elif rq.get('buttonNext', None):
|
||||||
|
# Go to the edit view (next page) for this object
|
||||||
|
rq.set('fieldset', rq.get('nextPage'))
|
||||||
|
return obj.skyn.edit(obj)
|
||||||
|
|
||||||
def getAppyType(self, fieldName):
|
def getAppyType(self, fieldName):
|
||||||
'''Returns the Appy type corresponding to p_fieldName.'''
|
'''Returns the Appy type corresponding to p_fieldName.'''
|
||||||
|
@ -653,24 +706,6 @@ class AbstractMixin:
|
||||||
updateRolesForPermission('Add portal content', tuple(allCreators),
|
updateRolesForPermission('Add portal content', tuple(allCreators),
|
||||||
folder)
|
folder)
|
||||||
|
|
||||||
def _appy_onEdit(self, created):
|
|
||||||
'''What happens when an object is created (p_created=True) or edited?'''
|
|
||||||
# Manage references
|
|
||||||
self._appy_manageRefs(created)
|
|
||||||
if self.wrapperClass:
|
|
||||||
# Get the wrapper first
|
|
||||||
appyWrapper = self._appy_getWrapper(force=True)
|
|
||||||
# Call the custom "onEdit" if available
|
|
||||||
try:
|
|
||||||
appyWrapper.onEdit(created)
|
|
||||||
except AttributeError, ae:
|
|
||||||
pass
|
|
||||||
# Manage "add" permissions
|
|
||||||
self._appy_managePermissions()
|
|
||||||
# Re/unindex object
|
|
||||||
if self._appy_meta_type == 'tool': self.unindexObject()
|
|
||||||
else: self.reindexObject()
|
|
||||||
|
|
||||||
def _appy_getDisplayList(self, values, labels, domain):
|
def _appy_getDisplayList(self, values, labels, domain):
|
||||||
'''Creates a DisplayList given a list of p_values and corresponding
|
'''Creates a DisplayList given a list of p_values and corresponding
|
||||||
i18n p_labels.'''
|
i18n p_labels.'''
|
||||||
|
@ -759,7 +794,7 @@ class AbstractMixin:
|
||||||
res = self.utranslate(msgId, domain=self.i18nDomain)
|
res = self.utranslate(msgId, domain=self.i18nDomain)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _appy_validateAllFields(self, REQUEST, errors):
|
def validateAllFields(self, REQUEST, errors):
|
||||||
'''This method is called when individual validation of all fields
|
'''This method is called when individual validation of all fields
|
||||||
succeed (when editing or creating an object). Then, this method
|
succeed (when editing or creating an object). Then, this method
|
||||||
performs inter-field validation. This way, the user must first
|
performs inter-field validation. This way, the user must first
|
||||||
|
@ -851,6 +886,7 @@ class AbstractMixin:
|
||||||
fieldValue = self.REQUEST[requestKey]
|
fieldValue = self.REQUEST[requestKey]
|
||||||
sortedRefField = getattr(self, '_appy_%s' % fieldName)
|
sortedRefField = getattr(self, '_appy_%s' % fieldName)
|
||||||
del sortedRefField[:]
|
del sortedRefField[:]
|
||||||
|
if not fieldValue: fieldValue = []
|
||||||
if isinstance(fieldValue, basestring):
|
if isinstance(fieldValue, basestring):
|
||||||
fieldValue = [fieldValue]
|
fieldValue = [fieldValue]
|
||||||
refObjects = []
|
refObjects = []
|
||||||
|
@ -874,4 +910,15 @@ class AbstractMixin:
|
||||||
if self.showField(fieldDescr, isEdit=True):
|
if self.showField(fieldDescr, isEdit=True):
|
||||||
exec 'self.set%s%s([])' % (fieldName[0].upper(),
|
exec 'self.set%s%s([])' % (fieldName[0].upper(),
|
||||||
fieldName[1:])
|
fieldName[1:])
|
||||||
|
|
||||||
|
def getUrl(self):
|
||||||
|
'''This method returns the URL of the consult view for this object.'''
|
||||||
|
return self.absolute_url() + '/skyn/view'
|
||||||
|
|
||||||
|
def translate(self, label, mapping={}, domain=None, default=None):
|
||||||
|
'''Translates a given p_label into p_domain with p_mapping.'''
|
||||||
|
cfg = self.getProductConfig()
|
||||||
|
if not domain: domain = cfg.PROJECTNAME
|
||||||
|
return self.translation_service.utranslate(
|
||||||
|
domain, label, mapping, self, default=default)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
0
gen/plone25/model.py
Executable file → Normal file
0
gen/plone25/templates/appyConfig.gif → gen/plone25/skin/appyConfig.gif
Executable file → Normal file
Before Width: | Height: | Size: 899 B After Width: | Height: | Size: 899 B |
0
gen/plone25/templates/arrowDown.png → gen/plone25/skin/arrowDown.png
Executable file → Normal file
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 174 B |
0
gen/plone25/templates/arrowUp.png → gen/plone25/skin/arrowUp.png
Executable file → Normal file
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 174 B |
0
gen/plone25/templates/current.png → gen/plone25/skin/current.png
Executable file → Normal file
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 244 B |
43
gen/plone25/templates/do.py → gen/plone25/skin/do.py
Executable file → Normal file
|
@ -1,15 +1,25 @@
|
||||||
## Python Script "<!applicationName!>_do.py"
|
## Python Script "do.py"
|
||||||
##bind container=container
|
|
||||||
##bind context=context
|
##bind context=context
|
||||||
##bind namespace=
|
##parameters=action
|
||||||
##bind script=script
|
|
||||||
##bind subpath=traverse_subpath
|
|
||||||
##parameters=actionType
|
|
||||||
##title=Executes an action
|
|
||||||
rq = context.REQUEST
|
rq = context.REQUEST
|
||||||
urlBack = rq['HTTP_REFERER']
|
urlBack = rq['HTTP_REFERER']
|
||||||
|
|
||||||
if actionType == 'appyAction':
|
if action == 'create':
|
||||||
|
# A user wants to create an object.
|
||||||
|
if rq.get('initiator', None):
|
||||||
|
# The object to create will be linked to an initiator object through a
|
||||||
|
# ref field.
|
||||||
|
initiatorRes= context.uid_catalog.searchResults(UID=rq.get('initiator'))
|
||||||
|
rq.SESSION['initiator'] = rq.get('initiator')
|
||||||
|
rq.SESSION['initiatorField'] = rq.get('field')
|
||||||
|
rq.SESSION['initiatorTarget'] = rq.get('type_name')
|
||||||
|
objId = context.generateUniqueId(rq.get('type_name'))
|
||||||
|
urlBack = '%s/portal_factory/%s/%s/skyn/edit' % \
|
||||||
|
(context.getParentNode().absolute_url(), rq.get('type_name'), objId)
|
||||||
|
|
||||||
|
elif action == 'edit': return context.getParentNode().onUpdate()
|
||||||
|
|
||||||
|
elif action == 'appyAction':
|
||||||
obj = context.uid_catalog(UID=rq['objectUid'])[0].getObject()
|
obj = context.uid_catalog(UID=rq['objectUid'])[0].getObject()
|
||||||
res, msg = obj.executeAppyAction(rq['fieldName'])
|
res, msg = obj.executeAppyAction(rq['fieldName'])
|
||||||
if not msg:
|
if not msg:
|
||||||
|
@ -18,11 +28,12 @@ if actionType == 'appyAction':
|
||||||
if res:
|
if res:
|
||||||
suffix = 'ok'
|
suffix = 'ok'
|
||||||
label = '%s_action_%s' % (obj.getLabelPrefix(rq['fieldName']), suffix)
|
label = '%s_action_%s' % (obj.getLabelPrefix(rq['fieldName']), suffix)
|
||||||
msg = context.utranslate(label, domain='<!applicationName!>')
|
msg = obj.translate(label)
|
||||||
context.plone_utils.addPortalMessage(msg)
|
context.plone_utils.addPortalMessage(msg)
|
||||||
|
|
||||||
elif actionType == 'changeRefOrder':
|
elif action == 'changeRefOrder':
|
||||||
# Move the item up (-1), down (+1) or at a given position ?
|
# Move the item up (-1), down (+1) or at a given position ?
|
||||||
|
obj = context.getParentNode()
|
||||||
move = -1 # Move up
|
move = -1 # Move up
|
||||||
isDelta = True
|
isDelta = True
|
||||||
if rq.get('moveDown.x', None) != None:
|
if rq.get('moveDown.x', None) != None:
|
||||||
|
@ -35,17 +46,19 @@ elif actionType == 'changeRefOrder':
|
||||||
isDelta = False
|
isDelta = False
|
||||||
except ValueError:
|
except ValueError:
|
||||||
context.plone_utils.addPortalMessage(
|
context.plone_utils.addPortalMessage(
|
||||||
context.utranslate('ref_invalid_index', domain='<!applicationName!>'))
|
obj.translate('ref_invalid_index'))
|
||||||
context.changeAppyRefOrder(rq['fieldName'], rq['objectUid'], move, isDelta)
|
obj.changeAppyRefOrder(rq['fieldName'], rq['objectUid'], move, isDelta)
|
||||||
|
|
||||||
elif actionType == 'triggerTransition':
|
elif action == 'triggerTransition':
|
||||||
|
obj = context.getParentNode()
|
||||||
from Products.CMFPlone import PloneMessageFactory as _
|
from Products.CMFPlone import PloneMessageFactory as _
|
||||||
context.portal_workflow.doActionFor(context, rq['workflow_action'],
|
context.portal_workflow.doActionFor(obj, rq['workflow_action'],
|
||||||
comment=rq.get('comment', ''))
|
comment=rq.get('comment', ''))
|
||||||
if urlBack.find('?') != -1:
|
if urlBack.find('?') != -1:
|
||||||
# Remove params; this way, the user may be redirected to correct phase
|
# Remove params; this way, the user may be redirected to correct phase
|
||||||
# when relevant.
|
# when relevant.
|
||||||
urlBack = urlBack[:urlBack.find('?')]
|
urlBack = urlBack[:urlBack.find('?')]
|
||||||
context.plone_utils.addPortalMessage(_(u'Your content\'s status has been modified.'))
|
context.plone_utils.addPortalMessage(
|
||||||
|
_(u'Your content\'s status has been modified.'))
|
||||||
|
|
||||||
return rq.RESPONSE.redirect(urlBack)
|
return rq.RESPONSE.redirect(urlBack)
|
0
gen/plone25/templates/doc.png → gen/plone25/skin/doc.png
Executable file → Normal file
Before Width: | Height: | Size: 818 B After Width: | Height: | Size: 818 B |
0
gen/plone25/templates/done.png → gen/plone25/skin/done.png
Executable file → Normal file
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
118
gen/plone25/skin/edit.pt
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
<tal:block metal:define-macro="master"
|
||||||
|
define="contextObj python:context.getParentNode();
|
||||||
|
errors request/errors | python:{};
|
||||||
|
Iterator python:modules['Products.Archetypes'].IndexIterator;
|
||||||
|
schematas contextObj/Schemata;
|
||||||
|
fieldsets python:[key for key in schematas.keys() if (key != 'metadata') and (schematas[key].editableFields(here, visible_only=True))];
|
||||||
|
default_fieldset python:(not schematas or schematas.has_key('default')) and 'default' or fieldsets[0];
|
||||||
|
fieldset request/fieldset|options/fieldset|default_fieldset;
|
||||||
|
fields python:schematas[fieldset].editableFields(here);
|
||||||
|
dummy python:here.at_isEditable(fields);
|
||||||
|
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
|
||||||
|
type_name here/getPortalTypeName|here/archetype_name;
|
||||||
|
lockable python:hasattr(here, 'wl_isLocked');
|
||||||
|
isLocked python:lockable and here.wl_isLocked();
|
||||||
|
tabindex tabindex|python:Iterator(pos=7000);
|
||||||
|
isEdit python:True;
|
||||||
|
tool contextObj/getTool;
|
||||||
|
flavour python: tool.getFlavour(contextObj);
|
||||||
|
appFolder tool/getAppFolder;
|
||||||
|
appName appFolder/id;
|
||||||
|
css python:here.getUniqueWidgetAttr(fields, 'helper_css');
|
||||||
|
js python:here.getUniqueWidgetAttr(fields, 'helper_js');
|
||||||
|
phaseInfo python: contextObj.getAppyPhases(fieldset=fieldset, forPlone=True);
|
||||||
|
phase request/phase|phaseInfo/name;
|
||||||
|
pageName python: contextObj.getAppyPage(isEdit, phaseInfo);">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
|
||||||
|
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||||
|
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
||||||
|
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
||||||
|
metal:use-macro="here/main_template/macros/master">
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">Disable the Standard Plone green tab</tal:comment>
|
||||||
|
<div metal:fill-slot="top_slot">
|
||||||
|
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
||||||
|
<div tal:define="dummy python:request.set('disable_border', 1)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">Archetypes stuff for managing Javascript and CSS.
|
||||||
|
If I remove this stuff, Javascript popup for dates does not work anyore.</tal:comment>
|
||||||
|
<metal:javascript_head fill-slot="javascript_head_slot">
|
||||||
|
<tal:block define="macro here/archetypes_custom_js/macros/javascript_head | nothing"
|
||||||
|
condition="macro">
|
||||||
|
<metal:block use-macro="macro" />
|
||||||
|
</tal:block>
|
||||||
|
<tal:js condition="js" repeat="item js">
|
||||||
|
<script type="text/javascript" charset="iso-8859-1"
|
||||||
|
tal:condition="python:exists('portal/%s' % item)"
|
||||||
|
tal:attributes="src string:$portal_url/$item">
|
||||||
|
</script>
|
||||||
|
</tal:js>
|
||||||
|
<tal:block define="macro edit_macros/javascript_head | nothing" condition="macro">
|
||||||
|
<metal:block use-macro="macro" />
|
||||||
|
</tal:block>
|
||||||
|
</metal:javascript_head>
|
||||||
|
|
||||||
|
<metal:css fill-slot="css_slot">
|
||||||
|
<tal:css condition="css" repeat="item css">
|
||||||
|
<style type="text/css" media="all"
|
||||||
|
tal:condition="python:exists('portal/%s' % item)"
|
||||||
|
tal:content="structure string:<!-- @import url($portal_url/$item); -->">
|
||||||
|
</style>
|
||||||
|
</tal:css>
|
||||||
|
<tal:block define="macro edit_macros/css | nothing" condition="macro">
|
||||||
|
<metal:block use-macro="macro" />
|
||||||
|
</tal:block>
|
||||||
|
</metal:css>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<metal:fill fill-slot="main">
|
||||||
|
<div metal:use-macro="here/skyn/macros/macros/showPagePrologue"/>
|
||||||
|
<div metal:use-macro="here/skyn/macros/macros/showPageHeader"/>
|
||||||
|
|
||||||
|
<form name="edit_form" method="post" enctype="multipart/form-data"
|
||||||
|
class="enableUnloadProtection atBaseEditForm"
|
||||||
|
tal:attributes="action python: contextObj.absolute_url()+'/skyn/do'">
|
||||||
|
<div metal:use-macro="here/skyn/macros/macros/listFields" />
|
||||||
|
<input type="hidden" name="action" value="edit"/>
|
||||||
|
<input type="hidden" name="fieldset" tal:attributes="value fieldset"/>
|
||||||
|
<input type="hidden" name="pageName" tal:attributes="value pageName"/>
|
||||||
|
<input type="hidden" name="phase" tal:attributes="value phase"/>
|
||||||
|
<input type="hidden" name="is_new"
|
||||||
|
tal:attributes="value python: '/portal_factory/' in contextObj.absolute_url()"/>
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">Buttons (Previous, Next, Save, etc)</tal:comment>
|
||||||
|
<metal:block define-slot="buttons"
|
||||||
|
tal:define="pages phaseInfo/pages;
|
||||||
|
pageIndex python:pages.index(fieldset);
|
||||||
|
numberOfPages python:len(pages)">
|
||||||
|
|
||||||
|
<tal:previousButton condition="python: pageIndex > 0">
|
||||||
|
<input class="context" type="submit" name="buttonPrevious"
|
||||||
|
i18n:attributes="value label_previous;" i18n:domain="plone"
|
||||||
|
tal:attributes="tabindex tabindex/next;
|
||||||
|
disabled python:test(isLocked, 'disabled', None);"/>
|
||||||
|
<input type="hidden" name="previousPage" tal:attributes="value python: pages[pageIndex-1]"/>
|
||||||
|
</tal:previousButton>
|
||||||
|
<tal:nextButton condition="python: pageIndex < numberOfPages - 1">
|
||||||
|
<input class="context" type="submit" name="buttonNext" value="Next"
|
||||||
|
i18n:attributes="value label_next;" i18n:domain="plone"
|
||||||
|
tal:attributes="tabindex tabindex/next;
|
||||||
|
disabled python:test(isLocked, 'disabled', None);"/>
|
||||||
|
<input type="hidden" name="nextPage" tal:attributes="value python: pages[pageIndex+1]"/>
|
||||||
|
</tal:nextButton>
|
||||||
|
<input class="context" type="submit" name="buttonOk"
|
||||||
|
i18n:attributes="value label_save;" i18n:domain="plone"
|
||||||
|
tal:attributes="tabindex tabindex/next;
|
||||||
|
disabled python:test(isLocked, 'disabled', None);"/>
|
||||||
|
<input class="standalone" type="submit" name="buttonCancel"
|
||||||
|
i18n:attributes="value label_cancel;" i18n:domain="plone"
|
||||||
|
tal:attributes="tabindex tabindex/next"/>
|
||||||
|
</metal:block>
|
||||||
|
</form>
|
||||||
|
<div metal:use-macro="here/skyn/macros/macros/showPageFooter"/>
|
||||||
|
</metal:fill>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</tal:block>
|
271
gen/plone25/templates/Macros.pt → gen/plone25/skin/macros.pt
Executable file → Normal file
|
@ -1,7 +1,5 @@
|
||||||
<div metal:define-macro="listPodTemplates" i18n:domain="<!applicationName!>" class="appyPod"
|
<div metal:define-macro="listPodTemplates" class="appyPod" tal:condition="podTemplates"
|
||||||
tal:define="flavour python: context.<!toolInstanceName!>.getFlavour(context);
|
tal:define="podTemplates python: flavour.getAvailablePodTemplates(contextObj, phase);">
|
||||||
podTemplates python: flavour.getAvailablePodTemplates(context, phase);"
|
|
||||||
tal:condition="podTemplates">
|
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
<!--
|
<!--
|
||||||
// Function that allows to generate a meeting document containing selected items.
|
// Function that allows to generate a meeting document containing selected items.
|
||||||
|
@ -16,35 +14,34 @@
|
||||||
|
|
||||||
<tal:comment replace="nothing">Form submitted when an object needs to be generated as a document.</tal:comment>
|
<tal:comment replace="nothing">Form submitted when an object needs to be generated as a document.</tal:comment>
|
||||||
<form name="podTemplateForm" method="post"
|
<form name="podTemplateForm" method="post"
|
||||||
tal:attributes="action python: context.absolute_url() + '/generateDocument'">
|
tal:attributes="action python: contextObj.absolute_url() + '/generateDocument'">
|
||||||
<input type="hidden" name="objectUid"/>
|
<input type="hidden" name="objectUid"/>
|
||||||
<input type="hidden" name="templateUid"/>
|
<input type="hidden" name="templateUid"/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<tal:podTemplates define="maxShownTemplates python: flavour.getMaxShownTemplates(context)">
|
<tal:podTemplates define="maxShownTemplates python: flavour.getMaxShownTemplates(contextObj)">
|
||||||
|
|
||||||
<tal:comment replace="nothing">Display templates as links if a few number of templates must be shown</tal:comment>
|
<tal:comment replace="nothing">Display templates as links if a few number of templates must be shown</tal:comment>
|
||||||
<span class="discreet" tal:condition="python: len(podTemplates)<=maxShownTemplates"
|
<span class="discreet" tal:condition="python: len(podTemplates)<=maxShownTemplates"
|
||||||
tal:repeat="podTemplate podTemplates">
|
tal:repeat="podTemplate podTemplates">
|
||||||
<a style="cursor: pointer"
|
<a style="cursor: pointer"
|
||||||
tal:define="podFormat podTemplate/getPodFormat"
|
tal:define="podFormat podTemplate/getPodFormat"
|
||||||
tal:attributes="onclick python: 'javascript:generatePodDocument(\'%s\',\'%s\')' % (context.UID(), podTemplate.UID())" >
|
tal:attributes="onclick python: 'javascript:generatePodDocument(\'%s\',\'%s\')' % (contextObj.UID(), podTemplate.UID())" >
|
||||||
<img tal:attributes="src string: $portal_url/$podFormat.png"/>
|
<img tal:attributes="src string: $portal_url/$podFormat.png"/>
|
||||||
<span tal:replace="podTemplate/Title"/>
|
<span tal:replace="podTemplate/Title"/>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<tal:comment replace="nothing">Display templates as a list if a lot of templates must be shown</tal:comment>
|
<tal:comment replace="nothing">Display templates as a list if a lot of templates must be shown</tal:comment>
|
||||||
<select tal:condition="python: len(podTemplates)>maxShownTemplates">
|
<select tal:condition="python: len(podTemplates)>maxShownTemplates">
|
||||||
<option value="" i18n:translate="">choose_a_doc</option>
|
<option value="" tal:content="python: tool.translate('choose_a_doc')"></option>
|
||||||
<option tal:repeat="podTemplate podTemplates" tal:content="podTemplate/Title"
|
<option tal:repeat="podTemplate podTemplates" tal:content="podTemplate/Title"
|
||||||
tal:attributes="onclick python: 'javascript:generatePodDocument(\'%s\',\'%s\')' % (context.UID(), podTemplate.UID())" />
|
tal:attributes="onclick python: 'javascript:generatePodDocument(\'%s\',\'%s\')' % (contextObj.UID(), podTemplate.UID())" />
|
||||||
</select>
|
</select>
|
||||||
</tal:podTemplates>
|
</tal:podTemplates>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<metal:editString define-macro="editString" i18n:domain="<!applicationName!>"
|
<metal:editString define-macro="editString" tal:define="vocab python:field.Vocabulary(contextObj)">
|
||||||
tal:define="vocab python:field.Vocabulary(contextObj);">
|
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/>
|
||||||
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/>
|
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0] > 0"></span>
|
||||||
<div class="discreet" tal:content="structure description"/>
|
<div class="discreet" tal:content="structure description"/>
|
||||||
<select tal:attributes="name fieldName;
|
<select tal:attributes="name fieldName;
|
||||||
id fieldName;
|
id fieldName;
|
||||||
|
@ -59,7 +56,7 @@
|
||||||
</select>
|
</select>
|
||||||
</metal:editString>
|
</metal:editString>
|
||||||
|
|
||||||
<metal:editBoolean define-macro="editBoolean" i18n:domain="<!applicationName!>">
|
<metal:editBoolean define-macro="editBoolean">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
tal:attributes="tabindex tabindex/next;
|
tal:attributes="tabindex tabindex/next;
|
||||||
name python: fieldName + '_visible';
|
name python: fieldName + '_visible';
|
||||||
|
@ -71,57 +68,56 @@
|
||||||
id string:${fieldName}_hidden;
|
id string:${fieldName}_hidden;
|
||||||
value python: test(contextObj.checkboxChecked(fieldName, value), 'True', 'False')"
|
value python: test(contextObj.checkboxChecked(fieldName, value), 'True', 'False')"
|
||||||
type="hidden" />
|
type="hidden" />
|
||||||
|
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0] > 0"></span>
|
||||||
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/>
|
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/>
|
||||||
<div class="discreet" tal:content="structure description"/>
|
<div class="discreet" tal:content="structure description"/>
|
||||||
</metal:editBoolean>
|
</metal:editBoolean>
|
||||||
|
|
||||||
<div metal:define-macro="editField" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="editField"
|
||||||
tal:define="fieldName field/getName;
|
tal:define="fieldName field/getName;
|
||||||
isMultiple python:test(appyType['multiplicity'][1]!=1, 'multiple', '');
|
isMultiple python:test(appyType['multiplicity'][1]!=1, 'multiple', '');
|
||||||
inError python:test(errors.has_key(fieldName), True, False);
|
inError python:test(errors.has_key(fieldName), True, False);
|
||||||
value python:field.getAccessor(contextObj)();
|
value python:field.getAccessor(contextObj)();
|
||||||
defaultValue python: contextObj.getDefault(fieldName);
|
defaultValue python: contextObj.getDefault(fieldName)"
|
||||||
label python: contextObj.utranslate(field.widget.label_msgid, domain='<!applicationName!>');
|
|
||||||
description python: contextObj.utranslate(field.widget.description_msgid, domain='<!applicationName!>')"
|
|
||||||
tal:attributes="class python:'field ' + test(inError, ' error', '')">
|
tal:attributes="class python:'field ' + test(inError, ' error', '')">
|
||||||
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]>0"></span>
|
|
||||||
<div tal:condition="inError" tal:content="python: errors[fieldName]"></div>
|
<div tal:condition="inError" tal:content="python: errors[fieldName]"></div>
|
||||||
<tal:stringField condition="python: appyType['type'] == 'String'">
|
<tal:stringField condition="python: appyType['type'] == 'String'">
|
||||||
<metal:edit use-macro="here/<!macros!>/macros/editString"/>
|
<metal:edit use-macro="here/skyn/macros/macros/editString"/>
|
||||||
</tal:stringField>
|
</tal:stringField>
|
||||||
<tal:booleanField condition="python: appyType['type'] == 'Boolean'">
|
<tal:booleanField condition="python: appyType['type'] == 'Boolean'">
|
||||||
<metal:edit use-macro="here/<!macros!>/macros/editBoolean"/>
|
<metal:edit use-macro="here/skyn/macros/macros/editBoolean"/>
|
||||||
</tal:booleanField>
|
</tal:booleanField>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showComputedField" i18n:domain="<!applicationName!>">
|
<div metal:define-macro="showComputedField">
|
||||||
<span class="appyLabel" tal:condition="showLabel"
|
<span class="appyLabel" tal:condition="showLabel" tal:content="label"></span>
|
||||||
tal:content="field/widget/label_msgid" i18n:translate=""></span>
|
|
||||||
<tal:showValue define="theValue python: contextObj.getComputedValue(appyType)">
|
<tal:showValue define="theValue python: contextObj.getComputedValue(appyType)">
|
||||||
<span tal:condition="appyType/plainText" tal:replace="theValue"/>
|
<span tal:condition="appyType/plainText" tal:replace="theValue"/>
|
||||||
<span tal:condition="not: appyType/plainText" tal:replace="structure theValue"/>
|
<span tal:condition="not: appyType/plainText" tal:replace="structure theValue"/>
|
||||||
</tal:showValue>
|
</tal:showValue>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showInfoField" i18n:domain="<!applicationName!>">
|
<div metal:define-macro="showInfoField">
|
||||||
<span class="appyLabel" tal:content="field/widget/label_msgid" i18n:translate=""></span>
|
<span class="appyLabel" tal:content="label"></span>
|
||||||
<span tal:content="field/widget/description_msgid" i18n:translate=""></span>
|
<span tal:content="structure description"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showActionField" i18n:domain="<!applicationName!>">
|
<div metal:define-macro="showActionField">
|
||||||
<form name="executeAppyAction" action="<!applicationName!>_do" method="POST">
|
<form name="executeAppyAction" action="skyn/do" method="POST">
|
||||||
<input type="hidden" name="actionType" value="appyAction"/>
|
<input type="hidden" name="actionType" value="appyAction"/>
|
||||||
<input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/>
|
<input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/>
|
||||||
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
|
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
|
||||||
<input type="submit" name="do" i18n:attributes="value"
|
<input type="submit" name="do" tal:attributes="value label"/>
|
||||||
tal:attributes="value field/widget/label_msgid"/>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showArchetypesField" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="showArchetypesField"
|
||||||
tal:define="field fieldDescr/atField|widgetDescr/atField;
|
tal:define="field fieldDescr/atField|widgetDescr/atField;
|
||||||
appyType fieldDescr/appyType|widgetDescr/appyType;
|
appyType fieldDescr/appyType|widgetDescr/appyType;
|
||||||
showLabel showLabel|python:True;"
|
showLabel showLabel|python:True;
|
||||||
|
label python: tool.translate(field.widget.label_msgid);
|
||||||
|
descrId field/widget/description_msgid|python:'';
|
||||||
|
description python: tool.translate(descrId)"
|
||||||
tal:attributes="class python: contextObj.getCssClasses(appyType, asSlave=True)">
|
tal:attributes="class python: contextObj.getCssClasses(appyType, asSlave=True)">
|
||||||
|
|
||||||
<tal:comment replace="nothing">For some fields we simply use the standard Archetypes
|
<tal:comment replace="nothing">For some fields we simply use the standard Archetypes
|
||||||
|
@ -137,18 +133,18 @@
|
||||||
<tal:viewField tal:condition="not: isEdit">
|
<tal:viewField tal:condition="not: isEdit">
|
||||||
<tal:defField>
|
<tal:defField>
|
||||||
<tal:fileField condition="python: (appyType['type'] == 'File')">
|
<tal:fileField condition="python: (appyType['type'] == 'File')">
|
||||||
<span tal:condition="showLabel" tal:content="field/widget/label_msgid" i18n:translate=""></span>
|
<span tal:condition="showLabel" tal:content="label"></span>
|
||||||
<metal:viewField use-macro="python: contextObj.widget(field.getName(), 'view', use_label=0)"/>
|
<metal:viewField use-macro="python: contextObj.widget(field.getName(), 'view', use_label=0)"/>
|
||||||
</tal:fileField>
|
</tal:fileField>
|
||||||
<tal:simpleField condition="python: (appyType['type'] in ('Integer', 'Float', 'Date', 'Boolean')) or (appyType['type'] == 'String' and (appyType['format'] == 0))">
|
<tal:simpleField condition="python: (appyType['type'] in ('Integer', 'Float', 'Date', 'Boolean')) or (appyType['type'] == 'String' and (appyType['format'] == 0))">
|
||||||
<span tal:condition="showLabel" tal:content="field/widget/label_msgid" i18n:translate=""
|
<span tal:condition="showLabel" tal:content="label"
|
||||||
tal:attributes="class python: 'appyLabel ' + contextObj.getCssClasses(appyType, asSlave=False);
|
tal:attributes="class python: 'appyLabel ' + contextObj.getCssClasses(appyType, asSlave=False);
|
||||||
id python: field.getAccessor(contextObj)()"></span>
|
id python: field.getAccessor(contextObj)()"></span>
|
||||||
<metal:viewField use-macro="python: contextObj.widget(field.getName(), 'view', use_label=0)"/>
|
<metal:viewField use-macro="python: contextObj.widget(field.getName(), 'view', use_label=0)"/>
|
||||||
</tal:simpleField>
|
</tal:simpleField>
|
||||||
<tal:formattedString condition="python: (appyType['type'] == 'String' and (appyType['format'] != 0))">
|
<tal:formattedString condition="python: (appyType['type'] == 'String' and (appyType['format'] != 0))">
|
||||||
<fieldset tal:define="value python:field.getAccessor(contextObj)()">
|
<fieldset tal:define="value python:field.getAccessor(contextObj)()">
|
||||||
<legend tal:condition="showLabel" i18n:translate="" tal:content="field/widget/label_msgid"></legend>
|
<legend tal:condition="showLabel" tal:content="label"></legend>
|
||||||
<span tal:condition="python: appyType['format'] == 1"
|
<span tal:condition="python: appyType['format'] == 1"
|
||||||
tal:replace="structure python: value.replace('\n', '<br>')"/>
|
tal:replace="structure python: value.replace('\n', '<br>')"/>
|
||||||
<span tal:condition="python: appyType['format'] == 2" tal:replace="structure value"/>
|
<span tal:condition="python: appyType['format'] == 2" tal:replace="structure value"/>
|
||||||
|
@ -163,59 +159,58 @@
|
||||||
<tal:ref define="isBack python:False;
|
<tal:ref define="isBack python:False;
|
||||||
fieldRel python:field.relationship;
|
fieldRel python:field.relationship;
|
||||||
objs python:contextObj.getAppyRefs(field.getName());
|
objs python:contextObj.getAppyRefs(field.getName());
|
||||||
labelMsgId field/widget/label_msgid;
|
|
||||||
descrMsgId field/widget/description_msgid;
|
|
||||||
innerRef innerRef|python:False">
|
innerRef innerRef|python:False">
|
||||||
<metal:viewRef use-macro="here/<!applicationName!>AppyReference/macros/showReference" />
|
<metal:viewRef use-macro="here/skyn/ref/macros/showReference" />
|
||||||
</tal:ref>
|
</tal:ref>
|
||||||
</tal:viewRef>
|
</tal:viewRef>
|
||||||
<tal:editRef condition="python: isEdit and (appyType['type'] == 'Ref')">
|
<tal:editRef condition="python: isEdit and (appyType['type'] == 'Ref')">
|
||||||
<tal:ref define="appyType fieldDescr/appyType|widgetDescr/appyType"
|
<tal:ref define="appyType fieldDescr/appyType|widgetDescr/appyType"
|
||||||
condition="python: appyType['link']==True">
|
condition="python: appyType['link']==True">
|
||||||
<metal:editRef use-macro="here/<!applicationName!>AppyReference/macros/editReference" />
|
<metal:editRef use-macro="here/skyn/ref/macros/editReference" />
|
||||||
</tal:ref>
|
</tal:ref>
|
||||||
</tal:editRef>
|
</tal:editRef>
|
||||||
<tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')">
|
<tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')">
|
||||||
<metal:cf use-macro="here/<!macros!>/macros/showComputedField" />
|
<metal:cf use-macro="here/skyn/macros/macros/showComputedField" />
|
||||||
</tal:computedField>
|
</tal:computedField>
|
||||||
<tal:actionField condition="python: (not isEdit) and (appyType['type'] == 'Action')">
|
<tal:actionField condition="python: (not isEdit) and (appyType['type'] == 'Action')">
|
||||||
<metal:af use-macro="here/<!macros!>/macros/showActionField" />
|
<metal:af use-macro="here/skyn/macros/macros/showActionField" />
|
||||||
</tal:actionField>
|
</tal:actionField>
|
||||||
<tal:masterString condition="python: isEdit and (appyType['type'] in ('String', 'Boolean')) and (appyType['slaves'])">
|
<tal:masterString condition="python: isEdit and (appyType['type'] in ('String', 'Boolean')) and (appyType['slaves'])">
|
||||||
<metal:mf use-macro="here/<!macros!>/macros/editField" />
|
<metal:mf use-macro="here/skyn/macros/macros/editField" />
|
||||||
</tal:masterString>
|
</tal:masterString>
|
||||||
<tal:infoField condition="python: (not isEdit) and (appyType['type'] == 'Info')">
|
<tal:infoField condition="python: (not isEdit) and (appyType['type'] == 'Info')">
|
||||||
<metal:af use-macro="here/<!macros!>/macros/showInfoField" />
|
<metal:af use-macro="here/skyn/macros/macros/showInfoField" />
|
||||||
</tal:infoField>
|
</tal:infoField>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showBackwardField" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="showBackwardField"
|
||||||
tal:define="isBack python:True;
|
tal:define="isBack python:True;
|
||||||
appyType widgetDescr/appyType;
|
appyType widgetDescr/appyType;
|
||||||
fieldRel widgetDescr/fieldRel;
|
fieldRel widgetDescr/fieldRel;
|
||||||
objs python:contextObj.getBRefs(fieldRel);
|
objs python:contextObj.getBRefs(fieldRel);
|
||||||
labelMsgId python:'%s_%s_back' % (contextObj.meta_type, appyType['backd']['attribute']);
|
label python:contextObj.translate('%s_%s_back' % (contextObj.meta_type, appyType['backd']['attribute']));
|
||||||
descrMsgId python:'';
|
description python:'';
|
||||||
innerRef innerRef|python:False">
|
innerRef innerRef|python:False">
|
||||||
<div metal:use-macro="here/<!applicationName!>AppyReference/macros/showReference" />
|
<div metal:use-macro="here/skyn/ref/macros/showReference" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span metal:define-macro="showGroup" i18n:domain="<!applicationName!>">
|
<span metal:define-macro="showGroup">
|
||||||
<fieldset class="appyGroup">
|
<fieldset class="appyGroup">
|
||||||
<legend><i i18n:translate=""
|
<legend><i tal:define="groupDescription python:contextObj.translate('%s_group_%s' % (contextObj.meta_type, widgetDescr['name']))"
|
||||||
tal:content="python: '%s_group_%s' % (contextObj.meta_type, widgetDescr['name'])"></i></legend>
|
tal:content="groupDescription"></i></legend>
|
||||||
<table tal:define="global fieldNb python:-1" width="100%">
|
<table tal:define="global fieldNb python:-1" width="100%">
|
||||||
<tr valign="top" tal:repeat="rowNb python:range(widgetDescr['rows'])">
|
<tr valign="top" tal:repeat="rowNb python:range(widgetDescr['rows'])">
|
||||||
<td tal:repeat="colNb python:range(widgetDescr['cols'])" tal:attributes="width python: str(100.0/widgetDescr['cols']) + '%'">
|
<td tal:repeat="colNb python:range(widgetDescr['cols'])"
|
||||||
|
tal:attributes="width python: str(100.0/widgetDescr['cols']) + '%'">
|
||||||
<tal:showField define="global fieldNb python:fieldNb+1;
|
<tal:showField define="global fieldNb python:fieldNb+1;
|
||||||
hasFieldDescr python: test(fieldNb < len(widgetDescr['fields']), True, False);"
|
hasFieldDescr python: test(fieldNb < len(widgetDescr['fields']), True, False);"
|
||||||
tal:condition="hasFieldDescr">
|
tal:condition="hasFieldDescr">
|
||||||
<tal:field define="fieldDescr python:widgetDescr['fields'][fieldNb]">
|
<tal:field define="fieldDescr python:widgetDescr['fields'][fieldNb]">
|
||||||
<tal:archetypesField condition="python: fieldDescr['widgetType'] == 'field'">
|
<tal:archetypesField condition="python: fieldDescr['widgetType'] == 'field'">
|
||||||
<metal:atField use-macro="here/<!macros!>/macros/showArchetypesField"/>
|
<metal:atField use-macro="here/skyn/macros/macros/showArchetypesField"/>
|
||||||
</tal:archetypesField>
|
</tal:archetypesField>
|
||||||
<tal:backwardRef tal:condition="python: (not isEdit) and (fieldDescr['widgetType'] == 'backField')">
|
<tal:backwardRef tal:condition="python: (not isEdit) and (fieldDescr['widgetType'] == 'backField')">
|
||||||
<metal:backRef use-macro="here/<!macros!>/macros/showBackwardField" />
|
<metal:backRef use-macro="here/skyn/macros/macros/showBackwardField" />
|
||||||
</tal:backwardRef>
|
</tal:backwardRef>
|
||||||
</tal:field>
|
</tal:field>
|
||||||
</tal:showField>
|
</tal:showField>
|
||||||
|
@ -226,33 +221,33 @@
|
||||||
<br/>
|
<br/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div metal:define-macro="listFields" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="listFields"
|
||||||
tal:repeat="widgetDescr python: contextObj.getAppyFields(isEdit, pageName)">
|
tal:repeat="widgetDescr python: contextObj.getAppyFields(isEdit, pageName)">
|
||||||
|
|
||||||
<tal:displayArchetypesField condition="python: widgetDescr['widgetType'] == 'field'">
|
<tal:displayArchetypesField condition="python: widgetDescr['widgetType'] == 'field'">
|
||||||
<tal:atField condition="python: widgetDescr['page'] == pageName">
|
<tal:atField condition="python: widgetDescr['page'] == pageName">
|
||||||
<metal:field use-macro="here/<!macros!>/macros/showArchetypesField" />
|
<metal:field use-macro="here/skyn/macros/macros/showArchetypesField" />
|
||||||
</tal:atField>
|
</tal:atField>
|
||||||
</tal:displayArchetypesField>
|
</tal:displayArchetypesField>
|
||||||
|
|
||||||
<tal:displayBackwardRef condition="python: (not isEdit) and (widgetDescr['widgetType'] == 'backField')">
|
<tal:displayBackwardRef condition="python: (not isEdit) and (widgetDescr['widgetType'] == 'backField')">
|
||||||
<tal:backRef condition="python: widgetDescr['appyType']['backd']['page'] == pageName">
|
<tal:backRef condition="python: widgetDescr['appyType']['backd']['page'] == pageName">
|
||||||
<metal:field metal:use-macro="here/<!macros!>/macros/showBackwardField" />
|
<metal:field metal:use-macro="here/skyn/macros/macros/showBackwardField" />
|
||||||
</tal:backRef>
|
</tal:backRef>
|
||||||
</tal:displayBackwardRef>
|
</tal:displayBackwardRef>
|
||||||
|
|
||||||
<tal:displayGroup condition="python: widgetDescr['widgetType'] == 'group'">
|
<tal:displayGroup condition="python: widgetDescr['widgetType'] == 'group'">
|
||||||
<tal:displayG condition="python: widgetDescr['page'] == pageName">
|
<tal:displayG condition="python: widgetDescr['page'] == pageName">
|
||||||
<metal:group metal:use-macro="here/<!macros!>/macros/showGroup" />
|
<metal:group metal:use-macro="here/skyn/macros/macros/showGroup" />
|
||||||
</tal:displayG>
|
</tal:displayG>
|
||||||
</tal:displayGroup>
|
</tal:displayGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span metal:define-macro="byline" i18n:domain="<!applicationName!>"
|
<span metal:define-macro="byline"
|
||||||
tal:condition="python: site_properties.allowAnonymousViewAbout or not isAnon"
|
tal:condition="python: site_properties.allowAnonymousViewAbout or not isAnon"
|
||||||
tal:define="creator here/Creator;" class="documentByLine">
|
tal:define="creator here/Creator;" class="documentByLine">
|
||||||
<tal:name tal:condition="creator"
|
<tal:name tal:condition="creator"
|
||||||
tal:define="author python:context.portal_membership.getMemberInfo(creator)">
|
tal:define="author python:contextObj.portal_membership.getMemberInfo(creator)">
|
||||||
<span class="documentAuthor" i18n:domain="plone" i18n:translate="label_by_author">
|
<span class="documentAuthor" i18n:domain="plone" i18n:translate="label_by_author">
|
||||||
by <a tal:attributes="href string:${portal_url}/author/${creator}"
|
by <a tal:attributes="href string:${portal_url}/author/${creator}"
|
||||||
tal:content="python:author and author['fullname'] or creator"
|
tal:content="python:author and author['fullname'] or creator"
|
||||||
|
@ -266,13 +261,13 @@
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span metal:define-macro="workflowHistory" i18n:domain="<!applicationName!>" class="reviewHistory"
|
<span metal:define-macro="workflowHistory" class="reviewHistory"
|
||||||
tal:define="history context/getWorkflowHistory" tal:condition="history">
|
tal:define="history contextObj/getWorkflowHistory" tal:condition="history">
|
||||||
<dl id="history" class="collapsible inline collapsedOnLoad">
|
<dl id="history" class="collapsible inline collapsedOnLoad">
|
||||||
<dt class="collapsibleHeader" i18n:translate="label_history" i18n:domain="plone">History</dt>
|
<dt class="collapsibleHeader" i18n:translate="label_history" i18n:domain="plone">History</dt>
|
||||||
<dd class="collapsibleContent">
|
<dd class="collapsibleContent">
|
||||||
<table width="100%" class="listing nosort" i18n:attributes="summary summary_review_history"
|
<table width="100%" class="listing nosort" i18n:attributes="summary summary_review_history"
|
||||||
tal:define="review_history python:context.portal_workflow.getInfoFor(context, 'review_history', []);
|
tal:define="review_history python:contextObj.portal_workflow.getInfoFor(contextObj, 'review_history', []);
|
||||||
review_history python:[review for review in review_history if review.get('action','')]"
|
review_history python:[review for review in review_history if review.get('action','')]"
|
||||||
tal:condition="review_history">
|
tal:condition="review_history">
|
||||||
<tr i18n:domain="plone">
|
<tr i18n:domain="plone">
|
||||||
|
@ -287,10 +282,10 @@
|
||||||
rhComments items/comments|nothing;
|
rhComments items/comments|nothing;
|
||||||
state items/review_state|nothing"
|
state items/review_state|nothing"
|
||||||
tal:attributes="class python:test(odd, 'even', 'odd')" tal:condition="items/action">
|
tal:attributes="class python:test(odd, 'even', 'odd')" tal:condition="items/action">
|
||||||
<td i18n:translate="" tal:content="python: context.getWorkflowLabel(items['action'])"
|
<td tal:content="python: tool.translate(contextObj.getWorkflowLabel(items['action']))"
|
||||||
tal:attributes="class string:state-${state}"/>
|
tal:attributes="class string:state-${state}"/>
|
||||||
<td tal:define="actorid python:items.get('actor');
|
<td tal:define="actorid python:items.get('actor');
|
||||||
actor python:context.portal_membership.getMemberInfo(actorid);
|
actor python:contextObj.portal_membership.getMemberInfo(actorid);
|
||||||
fullname actor/fullname|nothing;
|
fullname actor/fullname|nothing;
|
||||||
username actor/username|nothing"
|
username actor/username|nothing"
|
||||||
tal:content="python:fullname or username or actorid"/>
|
tal:content="python:fullname or username or actorid"/>
|
||||||
|
@ -305,7 +300,7 @@
|
||||||
</dl>
|
</dl>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div metal:define-macro="showPagePrologue" i18n:domain="<!applicationName!>">
|
<div metal:define-macro="showPagePrologue">
|
||||||
<tal:comment replace="nothing">Global Javascript functions, used in edit and
|
<tal:comment replace="nothing">Global Javascript functions, used in edit and
|
||||||
consult views, are defined gere.</tal:comment>
|
consult views, are defined gere.</tal:comment>
|
||||||
|
|
||||||
|
@ -357,55 +352,55 @@
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showPageHeader" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="showPageHeader"
|
||||||
tal:define="appyPages python: context.getAppyPages(phase);
|
tal:define="appyPages python: contextObj.getAppyPages(phase);
|
||||||
showCommonInfo python: not isEdit"
|
showCommonInfo python: not isEdit"
|
||||||
tal:condition="python: not context.portal_factory.isTemporary(context)">
|
tal:condition="python: not contextObj.portal_factory.isTemporary(contextObj)">
|
||||||
|
|
||||||
<tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment>
|
<tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment>
|
||||||
<table width="100%" tal:condition="showCommonInfo" class="appyCommonInfo">
|
<table width="100%" tal:condition="showCommonInfo" class="appyCommonInfo">
|
||||||
<tr valign="bottom">
|
<tr valign="bottom">
|
||||||
<tal:comment replace="nothing">Title, edit icon and state</tal:comment>
|
<tal:comment replace="nothing">Title, edit icon and state</tal:comment>
|
||||||
<td width="80%">
|
<td width="80%">
|
||||||
<b class="appyTitle" tal:content="title_string | here/title_or_id"></b>
|
<b class="appyTitle" tal:content="contextObj/title_or_id"></b>
|
||||||
<tal:comment replace="nothing">Show the phase name tied to this page</tal:comment>
|
<tal:comment replace="nothing">Show the phase name tied to this page</tal:comment>
|
||||||
<span class="discreet" tal:condition="python: phaseInfo['totalNbOfPhases']>1">−
|
<span class="discreet" tal:condition="python: phaseInfo['totalNbOfPhases']>1">−
|
||||||
<span i18n:translate="phase"></span>:
|
<span tal:replace="python:contextObj.translate('phase')"/>:
|
||||||
<span tal:define="label python:'%s_phase_%s' % (context.meta_type, phase)"
|
<span tal:replace="python:tool.translate('%s_phase_%s' % (contextObj.meta_type, phase))"/>
|
||||||
tal:content="label" i18n:translate=""></span>
|
|
||||||
</span>
|
</span>
|
||||||
<tal:comment replace="nothing">When no tabs are shown, we provide an edit icon.</tal:comment>
|
<tal:comment replace="nothing">When no tabs are shown, we provide an edit icon.</tal:comment>
|
||||||
<img tal:define="editPageName python:test(pageName=='main', 'default', pageName)"
|
<img tal:define="editPageName python:test(pageName=='main', 'default', pageName)"
|
||||||
src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title"
|
src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title"
|
||||||
style="cursor:pointer"
|
style="cursor:pointer"
|
||||||
tal:attributes="onClick python: 'href: window.location=\'%s/<!applicationName!>_appy_edit?fieldset=%s&phase=%s\'' % (context.absolute_url(), editPageName, phase)"
|
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/edit?fieldset=%s&phase=%s\'' % (contextObj.absolute_url(), editPageName, phase)"
|
||||||
tal:condition="python: (len(appyPages)==1) and member.has_permission('Modify portal content', context)"/>
|
tal:condition="python: (len(appyPages)==1) and member.has_permission('Modify portal content', contextObj)"/>
|
||||||
</td>
|
</td>
|
||||||
<td><metal:actions use-macro="here/document_actions/macros/document_actions"/>
|
<td><metal:actions use-macro="here/document_actions/macros/document_actions"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr tal:define="descrLabel python: here.utranslate('%s_edit_descr' % here.portal_type, domain='<!applicationName!>')" tal:condition="descrLabel/strip" >
|
<tr tal:define="descrLabel python: contextObj.translate('%s_edit_descr' % contextObj.portal_type)"
|
||||||
|
tal:condition="descrLabel" >
|
||||||
<tal:comment replace="nothing">Content type description</tal:comment>
|
<tal:comment replace="nothing">Content type description</tal:comment>
|
||||||
<td colspan="2" class="discreet" tal:content="descrLabel"/>
|
<td colspan="2" class="discreet" tal:content="descrLabel"/>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<metal:byLine use-macro="here/<!macros!>/macros/byline"/>
|
<metal:byLine use-macro="here/skyn/macros/macros/byline"/>
|
||||||
<tal:showWorkflow condition="showWorkflow">
|
<tal:showWorkflow condition="showWorkflow">
|
||||||
<metal:workflowHistory use-macro="here/<!macros!>/macros/workflowHistory"/>
|
<metal:workflowHistory use-macro="here/skyn/macros/macros/workflowHistory"/>
|
||||||
</tal:showWorkflow>
|
</tal:showWorkflow>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top"><metal:pod use-macro="here/<!macros!>/macros/listPodTemplates"/>
|
<td valign="top"><metal:pod use-macro="here/skyn/macros/macros/listPodTemplates"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Workflow-related information and actions</tal:comment>
|
<tal:comment replace="nothing">Workflow-related information and actions</tal:comment>
|
||||||
<tr tal:condition="python: showWorkflow and context.getWorkflowLabel()">
|
<tr tal:condition="python: showWorkflow and contextObj.getWorkflowLabel()">
|
||||||
<td colspan="2" class="appyWorkflow">
|
<td colspan="2" class="appyWorkflow">
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
<tr>
|
<tr>
|
||||||
<td><metal:states use-macro="here/<!macros!>/macros/states"/></td>
|
<td><metal:states use-macro="here/skyn/macros/macros/states"/></td>
|
||||||
<td align="right"><metal:states use-macro="here/<!macros!>/macros/transitions"/></td>
|
<td align="right"><metal:states use-macro="here/skyn/macros/macros/transitions"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -413,24 +408,24 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Tabs</tal:comment>
|
<tal:comment replace="nothing">Tabs</tal:comment>
|
||||||
<ul class="contentViews appyTabs" tal:condition="python: len(appyPages)>1">
|
<ul class="contentViews appyTabs" tal:condition="python: len(appyPages)>1">
|
||||||
<li tal:repeat="thePage appyPages"
|
<li tal:repeat="thePage appyPages"
|
||||||
tal:attributes="class python:test(thePage == pageName, 'selected', 'plain')">
|
tal:attributes="class python:test(thePage == pageName, 'selected', 'plain')">
|
||||||
<tal:tab define="pageLabel python: '%s_page_%s' % (here.meta_type, thePage)">
|
<tal:tab define="pageLabel python: tool.translate('%s_page_%s' % (contextObj.meta_type, thePage))">
|
||||||
<a i18n:translate="" tal:content="pageLabel"
|
<a tal:content="pageLabel"
|
||||||
tal:attributes="href python: here.absolute_url() + '/<!applicationName!>_appy_view?phase=%s&pageName=%s' % (phase, thePage)">
|
tal:attributes="href python: contextObj.absolute_url() + '/skyn/view?phase=%s&pageName=%s' % (phase, thePage)">
|
||||||
</a>
|
</a>
|
||||||
<img tal:define="editPageName python:test(thePage=='main', 'default', thePage)"
|
<img tal:define="editPageName python:test(thePage=='main', 'default', thePage)"
|
||||||
src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title"
|
src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title"
|
||||||
style="cursor:pointer" class="appyPlusImg"
|
style="cursor:pointer" class="appyPlusImg"
|
||||||
tal:attributes="onClick python: 'href: window.location=\'%s/<!applicationName!>_appy_edit?fieldset=%s&phase=%s\'' % (context.absolute_url(), editPageName, phase)"
|
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/edit?fieldset=%s&phase=%s\'' % (contextObj.absolute_url(), editPageName, phase)"
|
||||||
tal:condition="python: member.has_permission('Modify portal content', context)"/>
|
tal:condition="python: member.has_permission('Modify portal content', contextObj)"/>
|
||||||
</tal:tab>
|
</tal:tab>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showPageFooter" i18n:domain="<!applicationName!>">
|
<div metal:define-macro="showPageFooter">
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
<!--
|
<!--
|
||||||
// When the current page is loaded, we must set the correct state for all slave fields.
|
// When the current page is loaded, we must set the correct state for all slave fields.
|
||||||
|
@ -469,7 +464,7 @@
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="queryResult" i18n:domain="<!applicationName!>">
|
<div metal:define-macro="queryResult">
|
||||||
|
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
<!--
|
<!--
|
||||||
|
@ -592,11 +587,11 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<table class="vertical listing" width="100%"
|
<table class="vertical listing" width="100%"
|
||||||
tal:define="fieldDescrs python: context.<!toolInstanceName!>.getResultColumns(queryResult[0].getObject(), queryName);">
|
tal:define="fieldDescrs python: tool.getResultColumns(queryResult[0].getObject(), queryName);">
|
||||||
|
|
||||||
<tal:comment replace="nothing">Every item in fieldDescr is a FieldDescr instance,
|
<tal:comment replace="nothing">Every item in fieldDescr is a FieldDescr instance,
|
||||||
excepted for workflow state (which is not a field): in thi case it is simply string
|
excepted for workflow state (which is not a field): in this case it is simply the
|
||||||
"workflowState".</tal:comment>
|
string "workflowState".</tal:comment>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Headers, with filters and sort arrows</tal:comment>
|
<tal:comment replace="nothing">Headers, with filters and sort arrows</tal:comment>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -604,7 +599,7 @@
|
||||||
<th><img tal:attributes= "src string: $portal_url/arrowDown.gif;
|
<th><img tal:attributes= "src string: $portal_url/arrowDown.gif;
|
||||||
onClick python:'javascript:onSort(\'title\')';"
|
onClick python:'javascript:onSort(\'title\')';"
|
||||||
id="arrow_title" style="cursor:pointer"/>
|
id="arrow_title" style="cursor:pointer"/>
|
||||||
<span i18n:translate="ref_name"/>
|
<span tal:content="python: tool.translate('ref_name')"/>
|
||||||
<input id="filter_title" type="text" size="10" onkeyup="javascript:onTextEntered('title')"/>
|
<input id="filter_title" type="text" size="10" onkeyup="javascript:onTextEntered('title')"/>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
@ -617,11 +612,11 @@
|
||||||
style="cursor:pointer"/>
|
style="cursor:pointer"/>
|
||||||
<tal:comment replace="nothing">Display header for a "standard" field</tal:comment>
|
<tal:comment replace="nothing">Display header for a "standard" field</tal:comment>
|
||||||
<tal:standardField condition="python: fieldName != 'workflow_state'">
|
<tal:standardField condition="python: fieldName != 'workflow_state'">
|
||||||
<span i18n:translate="" tal:content="fieldDescr/atField/widget/label_msgid"/>
|
<span tal:replace="python: tool.translate(fieldDescr['atField'].widget.label_msgid)"/>
|
||||||
</tal:standardField>
|
</tal:standardField>
|
||||||
<tal:comment replace="nothing">Display header for the workflow state</tal:comment>
|
<tal:comment replace="nothing">Display header for the workflow state</tal:comment>
|
||||||
<tal:workflowState condition="python: fieldName == 'workflow_state'">
|
<tal:workflowState condition="python: fieldName == 'workflow_state'">
|
||||||
<span i18n:translate="workflow_state"/>
|
<span tal:replace="python: tool.translate('workflow_state')"/>
|
||||||
</tal:workflowState>
|
</tal:workflowState>
|
||||||
<input type="text" size="10"
|
<input type="text" size="10"
|
||||||
tal:attributes="id python: 'filter_%s' % fieldName;
|
tal:attributes="id python: 'filter_%s' % fieldName;
|
||||||
|
@ -634,13 +629,13 @@
|
||||||
tal:attributes= "src string: $portal_url/arrowDown.gif;
|
tal:attributes= "src string: $portal_url/arrowDown.gif;
|
||||||
onClick python:'javascript:onSort(\'root_type\')';"
|
onClick python:'javascript:onSort(\'root_type\')';"
|
||||||
id = "arrow_root_type" style="cursor:pointer"/>
|
id = "arrow_root_type" style="cursor:pointer"/>
|
||||||
<span i18n:translate="root_type"/>
|
<span tal:replace="python: tool.translate('root_type')"/>
|
||||||
<input type="text" size="10" id="filter_root_type"
|
<input type="text" size="10" id="filter_root_type"
|
||||||
tal:attributes="onkeyup python:'javascript:onTextEntered(\'root_type\')'"/>
|
tal:attributes="onkeyup python:'javascript:onTextEntered(\'root_type\')'"/>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Column "Actions"</tal:comment>
|
<tal:comment replace="nothing">Column "Actions"</tal:comment>
|
||||||
<th i18n:translate="ref_actions"></th>
|
<th tal:content="python: tool.translate('ref_actions')"></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Results</tal:comment>
|
<tal:comment replace="nothing">Results</tal:comment>
|
||||||
|
@ -648,8 +643,7 @@
|
||||||
<tal:row define="obj brain/getObject">
|
<tal:row define="obj brain/getObject">
|
||||||
|
|
||||||
<tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment>
|
<tal:comment replace="nothing">Mandatory column "Title"/"Name"</tal:comment>
|
||||||
<td id="field_title"><a tal:content="brain/Title"
|
<td id="field_title"><a tal:content="brain/Title" tal:attributes="href obj/getUrl"></a></td>
|
||||||
tal:attributes="href python: obj.absolute_url()"></a></td>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">Columns corresponding to other fields</tal:comment>
|
<tal:comment replace="nothing">Columns corresponding to other fields</tal:comment>
|
||||||
<tal:otherFields repeat="fieldDescr fieldDescrs">
|
<tal:otherFields repeat="fieldDescr fieldDescrs">
|
||||||
|
@ -661,7 +655,7 @@
|
||||||
showLabel python:False;
|
showLabel python:False;
|
||||||
innerRef python:True"
|
innerRef python:True"
|
||||||
condition="python: contextObj.showField(fieldDescr)">
|
condition="python: contextObj.showField(fieldDescr)">
|
||||||
<metal:field use-macro="here/<!macros!>/macros/showArchetypesField"/>
|
<metal:field use-macro="here/skyn/macros/macros/showArchetypesField"/>
|
||||||
</tal:field>
|
</tal:field>
|
||||||
</td>
|
</td>
|
||||||
<td tal:condition="not: fieldDescr/atField" style="color:red">Field
|
<td tal:condition="not: fieldDescr/atField" style="color:red">Field
|
||||||
|
@ -669,20 +663,20 @@
|
||||||
</td>
|
</td>
|
||||||
</tal:standardField>
|
</tal:standardField>
|
||||||
<tal:workflowState condition="python: fieldDescr == 'workflowState'">
|
<tal:workflowState condition="python: fieldDescr == 'workflowState'">
|
||||||
<td id="field_workflow_state" i18n:translate="" tal:content="obj/getWorkflowLabel"></td>
|
<td id="field_workflow_state" tal:content="python: tool.translate(obj.getWorkflowLabel())"></td>
|
||||||
</tal:workflowState>
|
</tal:workflowState>
|
||||||
</tal:otherFields>
|
</tal:otherFields>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Column "Object type", shown if we are on tab "consult all"</tal:comment>
|
<tal:comment replace="nothing">Column "Object type", shown if we are on tab "consult all"</tal:comment>
|
||||||
<td tal:condition="mainTabSelected" tal:content="obj/portal_type"
|
<td tal:condition="mainTabSelected" id="field_root_type"
|
||||||
i18n:translate="" id="field_root_type"></td>
|
tal:content="python: tool.translate(obj.portal_type)"></td>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Column "Actions"</tal:comment>
|
<tal:comment replace="nothing">Column "Actions"</tal:comment>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<table class="no-style-table" cellpadding="0" cellspacing="0">
|
<table class="no-style-table" cellpadding="0" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
<tal:comment replace="nothing">Edit the element</tal:comment>
|
<tal:comment replace="nothing">Edit the element</tal:comment>
|
||||||
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/edit'"
|
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/skyn/edit'"
|
||||||
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
||||||
<img src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title" />
|
<img src="edit.gif" title="Edit" i18n:domain="plone" i18n:attributes="title" />
|
||||||
</a></td>
|
</a></td>
|
||||||
|
@ -701,69 +695,96 @@
|
||||||
<div metal:use-macro="context/batch_macros/macros/navigation" />
|
<div metal:use-macro="context/batch_macros/macros/navigation" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<metal:phases define-macro="phases" i18n:domain="<!applicationName!>">
|
<metal:phases define-macro="phases">
|
||||||
<tal:comment replace="nothing">This macro displays phases defined for a given content type,
|
<tal:comment replace="nothing">This macro displays phases defined for a given content type,
|
||||||
only if more than one phase is defined.</tal:comment>
|
only if more than one phase is defined.</tal:comment>
|
||||||
<table width="100%" tal:define="phases context/getAppyPhases|nothing"
|
<table width="100%" tal:define="phases contextObj/getAppyPhases|nothing"
|
||||||
tal:condition="python: phases and (len(phases)>1)" cellspacing="1" cellpadding="0">
|
tal:condition="python: phases and (len(phases)>1)" cellspacing="1" cellpadding="0">
|
||||||
<tal:phase repeat="phase phases">
|
<tal:phase repeat="phase phases">
|
||||||
<tr>
|
<tr>
|
||||||
<td tal:define="label python:'%s_phase_%s' % (context.meta_type, phase['name']);
|
<td tal:define="label python:'%s_phase_%s' % (contextObj.meta_type, phase['name']);
|
||||||
displayLink python: (phase['phaseStatus'] != 'Future') and ('/portal_factory' not in context.absolute_url())"
|
displayLink python: (phase['phaseStatus'] != 'Future') and ('/portal_factory' not in contextObj.absolute_url())"
|
||||||
tal:attributes="class python: 'appyPhase step' + phase['phaseStatus']">
|
tal:attributes="class python: 'appyPhase step' + phase['phaseStatus']">
|
||||||
<a tal:attributes="href python: '%s?phase=%s&pageName=%s' % (context.absolute_url(), phase['name'], phase['pages'][0]);" tal:condition="displayLink"
|
<a tal:attributes="href python: '%s?phase=%s&pageName=%s' % (contextObj.getUrl(), phase['name'], phase['pages'][0]);" tal:condition="displayLink"
|
||||||
i18n:translate="" tal:content="label"/>
|
tal:content="python: tool.translate(label)"/>
|
||||||
<span tal:condition="not: displayLink" i18n:translate="" tal:content="label"/>
|
<span tal:condition="not: displayLink" tal:content="python: tool.translate(label)"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr tal:condition="python: phase['name'] != phases[-1]['name']">
|
<tr tal:condition="python: phase['name'] != phases[-1]['name']">
|
||||||
<td align="center"><img tal:attributes="src string: $portal_url/nextPhase.png"/></td>
|
<td align="center"><img tal:attributes="src string: $portal_url/skyn/nextPhase.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tal:phase>
|
</tal:phase>
|
||||||
</table>
|
</table>
|
||||||
</metal:phases>
|
</metal:phases>
|
||||||
|
|
||||||
<metal:states define-macro="states" i18n:domain="<!applicationName!>"
|
<metal:states define-macro="states"
|
||||||
tal:define="showAllStatesInPhase python: flavour.getAttr('showAllStatesInPhaseFor' + contextObj.meta_type);
|
tal:define="showAllStatesInPhase python: flavour.getAttr('showAllStatesInPhaseFor' + contextObj.meta_type);
|
||||||
states python: context.getAppyStates(phase, currentOnly=not showAllStatesInPhase)"
|
states python: contextObj.getAppyStates(phase, currentOnly=not showAllStatesInPhase)"
|
||||||
tal:condition="python: test(showAllStatesInPhase, len(states)>1, True)">
|
tal:condition="python: test(showAllStatesInPhase, len(states)>1, True)">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<tal:state repeat="stateInfo states">
|
<tal:state repeat="stateInfo states">
|
||||||
<td tal:attributes="class python: 'appyState step' + stateInfo['stateStatus']"
|
<td tal:attributes="class python: 'appyState step' + stateInfo['stateStatus']"
|
||||||
tal:content="python: context.getWorkflowLabel(stateInfo['name'])" i18n:translate="">
|
tal:content="python: tool.translate(contextObj.getWorkflowLabel(stateInfo['name']))">
|
||||||
</td>
|
</td>
|
||||||
<td tal:condition="python: stateInfo['name'] != states[-1]['name']">
|
<td tal:condition="python: stateInfo['name'] != states[-1]['name']">
|
||||||
<img tal:attributes="src string: $portal_url/nextState.png"/>
|
<img tal:attributes="src string: $portal_url/skyn/nextState.png"/>
|
||||||
</td>
|
</td>
|
||||||
</tal:state>
|
</tal:state>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</metal:states>
|
</metal:states>
|
||||||
|
|
||||||
<metal:transitions define-macro="transitions" i18n:domain="<!applicationName!>"
|
<metal:transitions define-macro="transitions"
|
||||||
tal:define="transitions python: contextObj.portal_workflow.getTransitionsFor(contextObj);"
|
tal:define="transitions python: contextObj.portal_workflow.getTransitionsFor(contextObj);"
|
||||||
tal:condition="transitions">
|
tal:condition="transitions">
|
||||||
<form id="triggerTransitionForm" method="post"
|
<form id="triggerTransitionForm" method="post"
|
||||||
tal:attributes="action python: contextObj.absolute_url() + '/<!applicationName!>_do'">
|
tal:attributes="action python: contextObj.absolute_url() + '/skyn/do'">
|
||||||
<input type="hidden" name="actionType" value="triggerTransition"/>
|
<input type="hidden" name="actionType" value="triggerTransition"/>
|
||||||
<input type="hidden" name="workflow_action"/>
|
<input type="hidden" name="workflow_action"/>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<tal:comment replace="nothing">Input field allowing to enter a comment before triggering a transition</tal:comment>
|
<tal:comment replace="nothing">Input field allowing to enter a comment before triggering a transition</tal:comment>
|
||||||
<td tal:define="showCommentsField python:flavour.getAttr('showWorkflowCommentFieldFor'+context.meta_type)"
|
<td tal:define="showCommentsField python:flavour.getAttr('showWorkflowCommentFieldFor'+contextObj.meta_type)"
|
||||||
align="right" tal:condition="showCommentsField">
|
align="right" tal:condition="showCommentsField">
|
||||||
<span i18n:translate="workflow_comment" class="discreet"></span>
|
<span tal:content="python: tool.translate('workflow_comment')" class="discreet"></span>
|
||||||
<input type="text" id="comment" name="comment" size="35"/>
|
<input type="text" id="comment" name="comment" size="35"/>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Buttons for triggering transitions</tal:comment>
|
<tal:comment replace="nothing">Buttons for triggering transitions</tal:comment>
|
||||||
<td align="right" tal:repeat="transition transitions">
|
<td align="right" tal:repeat="transition transitions">
|
||||||
<input type="button" i18n:attributes="value" class="context"
|
<input type="button" class="context"
|
||||||
tal:attributes="value python: transition['name'];
|
tal:attributes="value python: tool.translate(transition['name']);
|
||||||
onClick python: 'javascript: triggerTransition(\'%s\')' % transition['id']"/>
|
onClick python: 'javascript: triggerTransition(\'%s\')' % transition['id'];"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
</metal:transitions>
|
</metal:transitions>
|
||||||
|
|
||||||
|
<metal:portletContent define-macro="portletContent">
|
||||||
|
<tal:comment replace="nothing">Portlet title, with link to tool.</tal:comment>
|
||||||
|
<dt class="portletHeader">
|
||||||
|
<span tal:replace="python: tool.translate(appName)"/>
|
||||||
|
<img style="cursor:pointer"
|
||||||
|
tal:condition="python: member.has_role('Manager')"
|
||||||
|
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/view\'' % tool.absolute_url();
|
||||||
|
title python: tool.translate('%sTool' % appName);
|
||||||
|
src string:$portal_url/skyn/appyConfig.gif"/>
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">Links to flavours</tal:comment>
|
||||||
|
<dt class="portletAppyItem" tal:repeat="flavourInfo tool/getFlavoursInfo">
|
||||||
|
<a tal:define="flavourNumber flavourInfo/number;
|
||||||
|
rootTypes python: test(flavourNumber==1, rootClasses, ['%s_%s' % (rc, flavourNumber) for rc in rootClasses]);
|
||||||
|
rootClassesQuery python:','.join(rootTypes)"
|
||||||
|
tal:content="flavourInfo/title"
|
||||||
|
tal:attributes="title python: tool.translate('query_consult_all');
|
||||||
|
href python:'%s/skyn/query?query=%s&flavourNumber=%d' % (appFolder.absolute_url(), rootClassesQuery, flavourNumber)"></a>
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dt class="portletAppyItem" tal:define="contextObj tool/getPublishedObject"
|
||||||
|
tal:condition="python: contextObj.meta_type in rootClasses">
|
||||||
|
<metal:phases use-macro="here/skyn/macros/macros/phases"/>
|
||||||
|
</dt>
|
||||||
|
</metal:portletContent>
|
0
gen/plone25/templates/nextPhase.png → gen/plone25/skin/nextPhase.png
Executable file → Normal file
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
0
gen/plone25/templates/nextState.png → gen/plone25/skin/nextState.png
Executable file → Normal file
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
0
gen/plone25/templates/odt.png → gen/plone25/skin/odt.png
Executable file → Normal file
Before Width: | Height: | Size: 754 B After Width: | Height: | Size: 754 B |
0
gen/plone25/templates/pdf.png → gen/plone25/skin/pdf.png
Executable file → Normal file
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
0
gen/plone25/templates/plus.png → gen/plone25/skin/plus.png
Executable file → Normal file
Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 225 B |
64
gen/plone25/skin/query.pt
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
|
||||||
|
metal:use-macro="here/main_template/macros/master">
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">This page presents results of queries</tal:comment>
|
||||||
|
<body>
|
||||||
|
<div metal:fill-slot="top_slot">
|
||||||
|
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
||||||
|
<div tal:define="dummy python:request.set('disable_border', 1)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">We suppose we are in the app folder here.</tal:comment>
|
||||||
|
<div metal:fill-slot="main"
|
||||||
|
tal:define="appFolder context/getParentNode;
|
||||||
|
appName appFolder/id;
|
||||||
|
tool python: portal.get('portal_%s' % appName.lower());
|
||||||
|
queryName python:context.REQUEST.get('query');
|
||||||
|
flavourNumber python:context.REQUEST.get('flavourNumber');
|
||||||
|
rootClasses tool/getRootClasses;
|
||||||
|
rootTypes python: test(flavourNumber=='1', rootClasses, ['%s_%s' % (rc, flavourNumber) for rc in rootClasses]);
|
||||||
|
rootClassesQuery python:','.join(rootClasses);
|
||||||
|
mainTabSelected python: queryName.find(',') != -1">
|
||||||
|
|
||||||
|
<span tal:condition="python: queryName and (queryName != 'none')">
|
||||||
|
<span tal:define="queryResult python: tool.executeQuery(queryName, int(flavourNumber));
|
||||||
|
batch queryResult">
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">Tabs</tal:comment>
|
||||||
|
<ul class="contentViews appyTabs">
|
||||||
|
<tal:comment replace="nothing">Tab "All objects"</tal:comment>
|
||||||
|
<li tal:define="selected python:mainTabSelected"
|
||||||
|
tal:attributes="class python:test(selected, 'selected', 'plain')"
|
||||||
|
tal:condition="python: len(rootClasses)>1">
|
||||||
|
|
||||||
|
<a tal:content="python: tool.translate('query_consult_all')"
|
||||||
|
tal:attributes="href python: '%s/skyn/query?query=%s&flavourNumber=%s' % (appFolder.absolute_url(), rootClassesQuery, flavourNumber)"></a>
|
||||||
|
</li>
|
||||||
|
<tal:comment replace="nothing">One tab for each root content type</tal:comment>
|
||||||
|
<tal:tab repeat="rootContentType rootTypes">
|
||||||
|
<li tal:define="selected python:queryName == rootContentType"
|
||||||
|
tal:attributes="class python:test(selected, 'selected', 'plain')">
|
||||||
|
<a tal:content="python: tool.translate(rootContentType)"
|
||||||
|
tal:attributes="href python: '%s/skyn/query?query=%s&flavourNumber=%s' % (appFolder.absolute_url(), rootContentType, flavourNumber)"/>
|
||||||
|
<img style="cursor:pointer" class="appyPlusImg"
|
||||||
|
tal:define="addPermission python: '%s: Add %s' % (appName, rootContentType)"
|
||||||
|
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/do?action=create&type_name=%s\'' % (appFolder.absolute_url(), rootContentType);
|
||||||
|
src string: $portal_url/skyn/plus.png;
|
||||||
|
title python: tool.translate('query_create')"
|
||||||
|
tal:condition="python: member.has_permission(addPermission, appFolder)"/>
|
||||||
|
</li>
|
||||||
|
</tal:tab>
|
||||||
|
</ul>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<tal:comment replace="nothing">Query result</tal:comment>
|
||||||
|
<span tal:condition="queryResult">
|
||||||
|
<span metal:use-macro="here/skyn/macros/macros/queryResult"></span>
|
||||||
|
</span>
|
||||||
|
<span tal:condition="not: queryResult"
|
||||||
|
tal:content="python: tool.translate('query_no_result')">No result.</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
100
gen/plone25/templates/AppyReference.pt → gen/plone25/skin/ref.pt
Executable file → Normal file
|
@ -1,22 +1,22 @@
|
||||||
<tal:comment replace="nothing"> We begin with some sub-macros used within
|
<tal:comment replace="nothing"> We begin with some sub-macros used within
|
||||||
macro "showReference" defined below.</tal:comment>
|
macro "showReference" defined below.</tal:comment>
|
||||||
|
|
||||||
<metal:objectTitle define-macro="objectTitle" i18n:domain="<!applicationName!>">
|
<metal:objectTitle define-macro="objectTitle">
|
||||||
<tal:comment replace="nothing">Displays the title of a referenced object, with a link on
|
<tal:comment replace="nothing">Displays the title of a referenced object, with a link on
|
||||||
it to reach the consult view for this object. If we are on a back reference, the link
|
it to reach the consult view for this object. If we are on a back reference, the link
|
||||||
allows to reach the correct page where the forward reference is defined.</tal:comment>
|
allows to reach the correct page where the forward reference is defined.</tal:comment>
|
||||||
<a tal:define="viewUrl obj/absolute_url;
|
<a tal:define="viewUrl obj/getUrl;
|
||||||
fullUrl python: test(isBack, viewUrl + '/?pageName=%s&phase=%s' % (appyType['page'], appyType['phase']), viewUrl)"
|
fullUrl python: test(isBack, viewUrl + '/?pageName=%s&phase=%s' % (appyType['page'], appyType['phase']), viewUrl)"
|
||||||
tal:attributes="href fullUrl" tal:content="obj/Title"></a>
|
tal:attributes="href fullUrl" tal:content="obj/Title"></a>
|
||||||
</metal:objectTitle>
|
</metal:objectTitle>
|
||||||
|
|
||||||
<metal:objectActions define-macro="objectActions" i18n:domain="<!applicationName!>">
|
<metal:objectActions define-macro="objectActions">
|
||||||
<tal:comment replace="nothing">Displays icons for triggering actions on a given
|
<tal:comment replace="nothing">Displays icons for triggering actions on a given
|
||||||
referenced object (edit, delete, etc).</tal:comment>
|
referenced object (edit, delete, etc).</tal:comment>
|
||||||
<table class="no-style-table" cellpadding="0" cellspacing="0">
|
<table class="no-style-table" cellpadding="0" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
<tal:comment replace="nothing">Edit the element</tal:comment>
|
<tal:comment replace="nothing">Edit the element</tal:comment>
|
||||||
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/edit'"
|
<td class="noPadding"><a tal:attributes="href python: obj.absolute_url() + '/skyn/edit'"
|
||||||
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
tal:condition="python: member.has_permission('Modify portal content', obj)">
|
||||||
<img src="edit.gif" title="label_edit" i18n:domain="plone" i18n:attributes="title" />
|
<img src="edit.gif" title="label_edit" i18n:domain="plone" i18n:attributes="title" />
|
||||||
</a></td>
|
</a></td>
|
||||||
|
@ -28,20 +28,22 @@
|
||||||
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
|
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
|
||||||
<td class="noPadding" tal:condition="python: len(objs)>1">
|
<td class="noPadding" tal:condition="python: len(objs)>1">
|
||||||
<form tal:condition="python: member.has_permission('Modify portal content', obj)"
|
<form tal:condition="python: member.has_permission('Modify portal content', obj)"
|
||||||
tal:attributes="action python: contextObj.absolute_url() + '/<!applicationName!>_do'"
|
tal:attributes="action python: contextObj.absolute_url() + '/skyn/do'"
|
||||||
tal:define="objectIndex python:contextObj.getAppyRefIndex(field.getName(), obj)">
|
tal:define="objectIndex python:contextObj.getAppyRefIndex(field.getName(), obj)">
|
||||||
<input type="hidden" name="actionType" value="changeRefOrder"/>
|
<input type="hidden" name="actionType" value="changeRefOrder"/>
|
||||||
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
|
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
|
||||||
<input type="hidden" name="objectUid" tal:attributes="value obj/UID"/>
|
<input type="hidden" name="objectUid" tal:attributes="value obj/UID"/>
|
||||||
<tal:comment replace="nothing">Arrow up</tal:comment>
|
<tal:comment replace="nothing">Arrow up</tal:comment>
|
||||||
<span tal:condition="python: objectIndex > 0">
|
<span tal:condition="python: objectIndex > 0">
|
||||||
<input type="image" name="moveUp" tal:attributes="src python: contextObj.absolute_url() + '/arrowUp.png'"
|
<input type="image" name="moveUp" class="imageInput"
|
||||||
title="move_up" i18n:attributes="title" class="imageInput"/>
|
tal:attributes="src string: $portal_url/skyn/arrowUp.png;
|
||||||
|
title python: tool.translate('move_up')"/>
|
||||||
</span>
|
</span>
|
||||||
<tal:comment replace="nothing">Arrow down</tal:comment>
|
<tal:comment replace="nothing">Arrow down</tal:comment>
|
||||||
<span tal:condition="python: objectIndex < (len(objs)-1)">
|
<span tal:condition="python: objectIndex < (len(objs)-1)">
|
||||||
<input type="image" name="moveDown" tal:attributes="src python: contextObj.absolute_url() + '/arrowDown.png'"
|
<input type="image" name="moveDown" class="imageInput"
|
||||||
title="move_down" i18n:attributes="title" class="imageInput"/>
|
tal:attributes="src string: $portal_url/skyn/arrowDown.png;
|
||||||
|
title python: tool.translate('move_down')"/>
|
||||||
</span>
|
</span>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
|
@ -49,25 +51,25 @@
|
||||||
</table>
|
</table>
|
||||||
</metal:objectActions>
|
</metal:objectActions>
|
||||||
|
|
||||||
<metal:plusIcon define-macro="plusIcon" i18n:domain="<!applicationName!>">
|
<metal:plusIcon define-macro="plusIcon">
|
||||||
<tal:comment replace="nothing">Displays the "plus" icon that allows to add new object
|
<tal:comment replace="nothing">Displays the "plus" icon that allows to add new object
|
||||||
through a reference widget. Indeed, If field was declared as "addable", we must provide
|
through a reference widget. Indeed, If field was declared as "addable", we must provide
|
||||||
an icon for creating a new linked object (at least if multiplicities allow it).</tal:comment>
|
an icon for creating a new linked object (at least if multiplicities allow it).</tal:comment>
|
||||||
<img src="plus.png" i18n:attributes="title" style="cursor:pointer"
|
<img style="cursor:pointer" tal:condition="showPlusIcon"
|
||||||
tal:condition="showPlusIcon" title="add_ref"
|
tal:attributes="src string:$portal_url/skyn/plus.png;
|
||||||
tal:attributes="onClick python: 'href: window.location=\'%s/createAppyObject?initiator=%s&field=%s&type_name=%s\'' % (folder.absolute_url(), contextObj.UID(), field.getName(), linkedPortalType)"/>
|
title python: tool.translate('add_ref');
|
||||||
|
onClick python: 'href: window.location=\'%s/skyn/do?action=create&initiator=%s&field=%s&type_name=%s\'' % (folder.absolute_url(), contextObj.UID(), field.getName(), linkedPortalType)"/>
|
||||||
</metal:plusIcon>
|
</metal:plusIcon>
|
||||||
|
|
||||||
<div metal:define-macro="showReference" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="showReference"
|
||||||
tal:define="tool python: contextObj.<!toolInstanceName!>;
|
tal:define="folder python: test(contextObj.isPrincipiaFolderish, contextObj, contextObj.getParentNode());
|
||||||
flavour python:tool.getFlavour(contextObj);
|
flavour python:tool.getFlavour(contextObj);
|
||||||
folder python: test(contextObj.isPrincipiaFolderish, contextObj, contextObj.getParentNode());
|
|
||||||
linkedPortalType python:flavour.getPortalType(appyType['klass']);
|
linkedPortalType python:flavour.getPortalType(appyType['klass']);
|
||||||
addPermission python: '<!applicationName!>: Add %s' % linkedPortalType;
|
addPermission python: '%s: Add %s' % (appName, linkedPortalType);
|
||||||
multiplicity python:test(isBack, appyType['backd']['multiplicity'], appyType['multiplicity']);
|
multiplicity python:test(isBack, appyType['backd']['multiplicity'], appyType['multiplicity']);
|
||||||
maxReached python:(multiplicity[1] != None) and (len(objs) >= multiplicity[1]);
|
maxReached python:(multiplicity[1] != None) and (len(objs) >= multiplicity[1]);
|
||||||
showPlusIcon python:not isBack and appyType['add'] and not maxReached and member.has_permission(addPermission, folder);
|
showPlusIcon python:not isBack and appyType['add'] and not maxReached and member.has_permission(addPermission, folder);
|
||||||
atMostOneRef python: (multiplicity[1] == 1) and (len(objs)<=1)">
|
atMostOneRef python: (multiplicity[1] == 1) and (len(objs)<=1)">
|
||||||
|
|
||||||
<tal:comment replace="nothing">This macro displays the Reference widget on a "consult" page.
|
<tal:comment replace="nothing">This macro displays the Reference widget on a "consult" page.
|
||||||
|
|
||||||
|
@ -79,21 +81,20 @@
|
||||||
<tal:comment replace="nothing">Display a simplified widget if maximum number of
|
<tal:comment replace="nothing">Display a simplified widget if maximum number of
|
||||||
referenced objects is 1.</tal:comment>
|
referenced objects is 1.</tal:comment>
|
||||||
<table class="no-style-table" cellpadding="0" cellspacing="0"><tr valign="top">
|
<table class="no-style-table" cellpadding="0" cellspacing="0"><tr valign="top">
|
||||||
<td><span class="appyLabel" tal:condition="not: innerRef"
|
<td><span class="appyLabel" tal:condition="not: innerRef" tal:content="label"></span></td>
|
||||||
i18n:translate="" tal:content="labelMsgId"></span></td>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">If there is no object...</tal:comment>
|
<tal:comment replace="nothing">If there is no object...</tal:comment>
|
||||||
<tal:noObject condition="not:objs">
|
<tal:noObject condition="not:objs">
|
||||||
<td i18n:translate="">no_ref</td>
|
<td tal:content="python: tool.translate('no_ref')"></td>
|
||||||
<td><metal:plusIcon use-macro="here/<!applicationName!>AppyReference/macros/plusIcon"/></td>
|
<td><metal:plusIcon use-macro="here/skyn/ref/macros/plusIcon"/></td>
|
||||||
</tal:noObject>
|
</tal:noObject>
|
||||||
|
|
||||||
<tal:comment replace="nothing">If there is an object...</tal:comment>
|
<tal:comment replace="nothing">If there is an object...</tal:comment>
|
||||||
<tal:objectIsPresent condition="python: len(objs) == 1">
|
<tal:objectIsPresent condition="python: len(objs) == 1">
|
||||||
<tal:obj define="obj python:objs[0]">
|
<tal:obj define="obj python:objs[0]">
|
||||||
<td><metal:showObjectTitle use-macro="here/<!applicationName!>AppyReference/macros/objectTitle" /></td>
|
<td><metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle" /></td>
|
||||||
<td tal:condition="not: isBack">
|
<td tal:condition="not: isBack">
|
||||||
<metal:showObjectActions use-macro="here/<!applicationName!>AppyReference/macros/objectActions" />
|
<metal:showObjectActions use-macro="here/skyn/ref/macros/objectActions" />
|
||||||
</td>
|
</td>
|
||||||
</tal:obj>
|
</tal:obj>
|
||||||
</tal:objectIsPresent>
|
</tal:objectIsPresent>
|
||||||
|
@ -104,16 +105,16 @@
|
||||||
<tal:anyNumberOfReferences condition="not: atMostOneRef">
|
<tal:anyNumberOfReferences condition="not: atMostOneRef">
|
||||||
<fieldset tal:attributes="class python:test(innerRef, 'innerAppyFieldset', '')">
|
<fieldset tal:attributes="class python:test(innerRef, 'innerAppyFieldset', '')">
|
||||||
<legend tal:condition="python: not innerRef or showPlusIcon">
|
<legend tal:condition="python: not innerRef or showPlusIcon">
|
||||||
<span tal:condition="not: innerRef" i18n:translate="" tal:content="labelMsgId"/>
|
<span tal:condition="not: innerRef" tal:content="label"/>
|
||||||
<metal:plusIcon use-macro="here/<!applicationName!>AppyReference/macros/plusIcon"/>
|
<metal:plusIcon use-macro="here/skyn/ref/macros/plusIcon"/>
|
||||||
</legend>
|
</legend>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Object description</tal:comment>
|
<tal:comment replace="nothing">Object description</tal:comment>
|
||||||
<p tal:define="descr python:contextObj.utranslate(descrMsgId, domain='<!applicationName!>')"
|
<p tal:condition="python: not innerRef and description"
|
||||||
tal:condition="python: not innerRef and descr.strip()" tal:content="descr" class="discreet" ></p>
|
tal:content="description" class="discreet" ></p>
|
||||||
|
|
||||||
<tal:comment replace="nothing">No object is present</tal:comment>
|
<tal:comment replace="nothing">No object is present</tal:comment>
|
||||||
<p tal:condition="not:objs" i18n:translate="">no_ref</p>
|
<p tal:condition="not:objs" tal:content="python: tool.translate('no_ref')"></p>
|
||||||
|
|
||||||
<table width="100%" cellspacing="0" cellpadding="0" tal:condition="objs"
|
<table width="100%" cellspacing="0" cellpadding="0" tal:condition="objs"
|
||||||
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
|
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
|
||||||
|
@ -123,7 +124,7 @@
|
||||||
<table class="no-style-table" cellspacing="0" cellpadding="0"
|
<table class="no-style-table" cellspacing="0" cellpadding="0"
|
||||||
tal:condition="python: isBack and objs">
|
tal:condition="python: isBack and objs">
|
||||||
<tr tal:repeat="obj objs">
|
<tr tal:repeat="obj objs">
|
||||||
<td><metal:showObjectTitle use-macro="here/<!applicationName!>AppyReference/macros/objectTitle" />
|
<td><metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -133,27 +134,29 @@
|
||||||
width python:test(innerRef, '100%', test(appyType['wide'], '100%', ''))"
|
width python:test(innerRef, '100%', test(appyType['wide'], '100%', ''))"
|
||||||
align="right" tal:condition="python: not isBack and objs" cellpadding="0" cellspacing="0">
|
align="right" tal:condition="python: not isBack and objs" cellpadding="0" cellspacing="0">
|
||||||
<tr tal:condition="appyType/showHeaders">
|
<tr tal:condition="appyType/showHeaders">
|
||||||
<th tal:condition="python: 'title' not in appyType['shownInfo']" i18n:translate="ref_name"></th>
|
<th tal:condition="python: 'title' not in appyType['shownInfo']"
|
||||||
|
tal:content="python: tool.translate('ref_name')"></th>
|
||||||
<th tal:repeat="shownField appyType/shownInfo">
|
<th tal:repeat="shownField appyType/shownInfo">
|
||||||
<tal:showHeader condition="python: objs[0].getField(shownField)">
|
<tal:showHeader condition="python: objs[0].getField(shownField)">
|
||||||
<tal:titleHeader condition="python: shownField == 'title'" i18n:translate="ref_name"/>
|
<tal:titleHeader condition="python: shownField == 'title'"
|
||||||
|
content="python: tool.translate('ref_name')"/>
|
||||||
<tal:otherHeader condition="python: shownField != 'title'"
|
<tal:otherHeader condition="python: shownField != 'title'"
|
||||||
define="labelId python: objs[0].getField(shownField).widget.label_msgid"
|
define="labelId python: objs[0].getField(shownField).widget.label_msgid"
|
||||||
content="labelId" i18n:translate=""/>
|
content="python: tool.translate(labelId)"/>
|
||||||
</tal:showHeader>
|
</tal:showHeader>
|
||||||
</th>
|
</th>
|
||||||
<th i18n:translate="ref_actions"></th>
|
<th tal:content="python: tool.translate('ref_actions')"></th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr tal:repeat="obj objs" valign="top">
|
<tr tal:repeat="obj objs" valign="top">
|
||||||
<tal:comment replace="nothing">Object title, shown here if not specified somewhere
|
<tal:comment replace="nothing">Object title, shown here if not specified somewhere
|
||||||
else in appyType.shownInfo.</tal:comment>
|
else in appyType.shownInfo.</tal:comment>
|
||||||
<td tal:condition="python: 'title' not in appyType['shownInfo']"><metal:showObjectTitle
|
<td tal:condition="python: 'title' not in appyType['shownInfo']"><metal:showObjectTitle
|
||||||
use-macro="here/<!applicationName!>AppyReference/macros/objectTitle"/>
|
use-macro="here/skyn/ref/macros/objectTitle"/>
|
||||||
</td>
|
</td>
|
||||||
<tal:comment replace="nothing">Additional fields that must be shown</tal:comment>
|
<tal:comment replace="nothing">Additional fields that must be shown</tal:comment>
|
||||||
<td tal:repeat="shownField appyType/shownInfo">
|
<td tal:repeat="shownField appyType/shownInfo">
|
||||||
<tal:showTitle condition="python: shownField == 'title'">
|
<tal:showTitle condition="python: shownField == 'title'">
|
||||||
<metal:showObjectTitle use-macro="here/<!applicationName!>AppyReference/macros/objectTitle"/>
|
<metal:showObjectTitle use-macro="here/skyn/ref/macros/objectTitle"/>
|
||||||
</tal:showTitle>
|
</tal:showTitle>
|
||||||
<tal:showOtherField define="appyType python: obj.getAppyType(shownField);
|
<tal:showOtherField define="appyType python: obj.getAppyType(shownField);
|
||||||
field python:obj.getField(shownField);
|
field python:obj.getField(shownField);
|
||||||
|
@ -166,23 +169,21 @@
|
||||||
<tal:ref tal:define="isBack python:appyType['isBack'];
|
<tal:ref tal:define="isBack python:appyType['isBack'];
|
||||||
fieldRel python:field.relationship;
|
fieldRel python:field.relationship;
|
||||||
objs python:contextObj.getAppyRefs(field.getName());
|
objs python:contextObj.getAppyRefs(field.getName());
|
||||||
labelMsgId field/widget/label_msgid;
|
|
||||||
descrMsgId field/widget/description_msgid;
|
|
||||||
innerRef python:True">
|
innerRef python:True">
|
||||||
<metal:showField use-macro="here/<!applicationName!>AppyReference/macros/showReference" />
|
<metal:showField use-macro="here/skyn/ref/macros/showReference" />
|
||||||
</tal:ref>
|
</tal:ref>
|
||||||
</tal:showRef>
|
</tal:showRef>
|
||||||
<tal:showComputed condition="python: appyType['type'] == 'Computed'">
|
<tal:showComputed condition="python: appyType['type'] == 'Computed'">
|
||||||
<tal:computed content="python: obj.getComputedValue(appyType)"/>
|
<tal:computed content="python: obj.getComputedValue(appyType)"/>
|
||||||
</tal:showComputed>
|
</tal:showComputed>
|
||||||
<tal:showAction condition="python: appyType['type'] == 'Action'">
|
<tal:showAction condition="python: appyType['type'] == 'Action'">
|
||||||
<metal:action use-macro="here/<!macros!>/macros/showActionField" />
|
<metal:action use-macro="here/skyn/macros/macros/showActionField" />
|
||||||
</tal:showAction>
|
</tal:showAction>
|
||||||
</tal:showOtherField>
|
</tal:showOtherField>
|
||||||
</td>
|
</td>
|
||||||
<tal:comment replace="nothing">Actions</tal:comment>
|
<tal:comment replace="nothing">Actions</tal:comment>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<metal:showObjectActions use-macro="here/<!applicationName!>AppyReference/macros/objectActions" />
|
<metal:showObjectActions use-macro="here/skyn/ref/macros/objectActions" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -196,7 +197,7 @@
|
||||||
</tal:anyNumberOfReferences>
|
</tal:anyNumberOfReferences>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="editReference" i18n:domain="<!applicationName!>"
|
<div metal:define-macro="editReference"
|
||||||
tal:define="refPortalType python:here.getAppyRefPortalType(field.getName());
|
tal:define="refPortalType python:here.getAppyRefPortalType(field.getName());
|
||||||
appyType python:here.getAppyType(field.getName());
|
appyType python:here.getAppyType(field.getName());
|
||||||
allBrains python:here.uid_catalog(portal_type=refPortalType);
|
allBrains python:here.uid_catalog(portal_type=refPortalType);
|
||||||
|
@ -205,23 +206,22 @@
|
||||||
isMultiple python:test(appyType['multiplicity'][1]!=1, 'multiple', '');
|
isMultiple python:test(appyType['multiplicity'][1]!=1, 'multiple', '');
|
||||||
appyFieldName python: 'appy_ref_%s' % field.getName();
|
appyFieldName python: 'appy_ref_%s' % field.getName();
|
||||||
inError python:test(errors.has_key(field.getName()), True, False);
|
inError python:test(errors.has_key(field.getName()), True, False);
|
||||||
defaultValue python: here.getDefault(field.getName());
|
defaultValue python: contextObj.getDefault(field.getName());
|
||||||
defaultValueUID defaultValue/UID|nothing;
|
defaultValueUID defaultValue/UID|nothing;
|
||||||
isBeingCreated python: context.portal_factory.isTemporary(context) or ('/portal_factory/' in context.absolute_url())"
|
isBeingCreated python: contextObj.portal_factory.isTemporary(contextObj) or ('/portal_factory/' in contextObj.absolute_url())"
|
||||||
tal:attributes="class python:'appyRefEdit field' + test(inError, ' error', '')">
|
tal:attributes="class python:'appyRefEdit field' + test(inError, ' error', '')">
|
||||||
|
|
||||||
<tal:comment replace="nothing">This macro displays the Reference widget on an "edit" page</tal:comment>
|
<tal:comment replace="nothing">This macro displays the Reference widget on an "edit" page</tal:comment>
|
||||||
|
|
||||||
<label tal:attributes="for python:appyFieldName"
|
<label tal:attributes="for python:appyFieldName" tal:content="label"></label>
|
||||||
i18n:translate="" tal:content="field/widget/label_msgid"></label>
|
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]>0"></span><br/>
|
||||||
<span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]>0"></span><br/>
|
|
||||||
<div tal:condition="inError" tal:content="python: errors[field.getName()]"></div>
|
<div tal:condition="inError" tal:content="python: errors[field.getName()]"></div>
|
||||||
<select tal:define="valueIsInReq python:test(request.get(appyFieldName, None) != None, True, False)"
|
<select tal:define="valueIsInReq python:test(request.get(appyFieldName, None) != None, True, False)"
|
||||||
tal:attributes="name python:'appy_ref_%s' % field.getName();
|
tal:attributes="name python:'appy_ref_%s' % field.getName();
|
||||||
multiple isMultiple">
|
multiple isMultiple">
|
||||||
<option tal:condition="not: isMultiple" value="" i18n:translate="choose_a_value"/>
|
<option tal:condition="not: isMultiple" value="" i18n:translate="choose_a_value"/>
|
||||||
<option tal:repeat="brain brains"
|
<option tal:repeat="brain brains"
|
||||||
tal:content="python: here.<!toolInstanceName!>.getReferenceLabel(brain, appyType)"
|
tal:content="python: tool.getReferenceLabel(brain, appyType)"
|
||||||
tal:attributes="value brain/UID;
|
tal:attributes="value brain/UID;
|
||||||
selected python:test((valueIsInReq and (brain.UID in request.get(appyFieldName, []))) or (not valueIsInReq and ((brain.UID in refUids) or (isBeingCreated and (brain.UID==defaultValueUID)))), True, False)"/>
|
selected python:test((valueIsInReq and (brain.UID in request.get(appyFieldName, []))) or (not valueIsInReq and ((brain.UID in refUids) or (isBeingCreated and (brain.UID==defaultValueUID)))), True, False)"/>
|
||||||
</select>
|
</select>
|
0
gen/plone25/templates/rtf.png → gen/plone25/skin/rtf.png
Executable file → Normal file
Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 225 B |
13
gen/plone25/templates/appy_view.pt → gen/plone25/skin/view.pt
Executable file → Normal file
|
@ -1,5 +1,4 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
|
||||||
i18n:domain="<!applicationName!>"
|
|
||||||
lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"
|
lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||||
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
||||||
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
||||||
|
@ -16,20 +15,22 @@
|
||||||
<tal:comment replace="nothing">Fill main slot of Plone main_template</tal:comment>
|
<tal:comment replace="nothing">Fill main slot of Plone main_template</tal:comment>
|
||||||
<body>
|
<body>
|
||||||
<metal:fill fill-slot="main"
|
<metal:fill fill-slot="main"
|
||||||
tal:define="contextObj python:context;
|
tal:define="contextObj python:context.getParentNode();
|
||||||
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
|
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
|
||||||
errors python:request.get('errors', {});
|
errors python:request.get('errors', {});
|
||||||
isEdit python:False;
|
isEdit python:False;
|
||||||
tool contextObj/getTool;
|
tool contextObj/getTool;
|
||||||
flavour python: tool.getFlavour(contextObj);
|
flavour python: tool.getFlavour(contextObj);
|
||||||
|
appFolder tool/getAppFolder;
|
||||||
|
appName appFolder/id;
|
||||||
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, forPlone=False);
|
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, forPlone=False);
|
||||||
phase request/phase|phaseInfo/name;
|
phase request/phase|phaseInfo/name;
|
||||||
pageName python: contextObj.getAppyPage(isEdit, phaseInfo);
|
pageName python: contextObj.getAppyPage(isEdit, phaseInfo);
|
||||||
showWorkflow python: flavour.getAttr('showWorkflowFor' + contextObj.meta_type)">
|
showWorkflow python: flavour.getAttr('showWorkflowFor' + contextObj.meta_type)">
|
||||||
<div metal:use-macro="here/<!macros!>/macros/showPagePrologue"/>
|
<div metal:use-macro="here/skyn/macros/macros/showPagePrologue"/>
|
||||||
<div metal:use-macro="here/<!macros!>/macros/showPageHeader"/>
|
<div metal:use-macro="here/skyn/macros/macros/showPageHeader"/>
|
||||||
<div metal:use-macro="here/<!macros!>/macros/listFields" />
|
<div metal:use-macro="here/skyn/macros/macros/listFields" />
|
||||||
<div metal:use-macro="here/<!macros!>/macros/showPageFooter"/>
|
<div metal:use-macro="here/skyn/macros/macros/showPageFooter"/>
|
||||||
</metal:fill>
|
</metal:fill>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -20,8 +20,8 @@ class <!genClassName!>(<!parents!>):
|
||||||
allowed_content_types = []
|
allowed_content_types = []
|
||||||
filter_content_types = 0
|
filter_content_types = 0
|
||||||
global_allow = 1
|
global_allow = 1
|
||||||
immediate_view = '<!applicationName!>_appy_view'
|
immediate_view = 'skyn/view'
|
||||||
default_view = '<!applicationName!>_appy_view'
|
default_view = 'skyn/view'
|
||||||
suppl_views = ()
|
suppl_views = ()
|
||||||
typeDescription = '<!genClassName!>'
|
typeDescription = '<!genClassName!>'
|
||||||
typeDescMsgId = '<!genClassName!>_edit_descr'
|
typeDescMsgId = '<!genClassName!>_edit_descr'
|
||||||
|
|
|
@ -22,8 +22,8 @@ class <!flavourName!>(OrderedBaseFolder, FlavourMixin):
|
||||||
filter_content_types = 0
|
filter_content_types = 0
|
||||||
global_allow = 1
|
global_allow = 1
|
||||||
#content_icon = '<!flavourName!>.gif'
|
#content_icon = '<!flavourName!>.gif'
|
||||||
immediate_view = '<!applicationName!>_appy_view'
|
immediate_view = 'skyn/view'
|
||||||
default_view = '<!applicationName!>_appy_view'
|
default_view = 'skyn/view'
|
||||||
suppl_views = ()
|
suppl_views = ()
|
||||||
typeDescription = "<!flavourName!>"
|
typeDescription = "<!flavourName!>"
|
||||||
typeDescMsgId = '<!flavourName!>_edit_descr'
|
typeDescMsgId = '<!flavourName!>_edit_descr'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<!codeHeader!>
|
<!codeHeader!>
|
||||||
from zExceptions import BadRequest
|
from zExceptions import BadRequest
|
||||||
|
from Products.CMFCore.DirectoryView import manage_addDirectoryView
|
||||||
from Products.ExternalMethod.ExternalMethod import ExternalMethod
|
from Products.ExternalMethod.ExternalMethod import ExternalMethod
|
||||||
from Products.Archetypes.Extensions.utils import installTypes
|
from Products.Archetypes.Extensions.utils import installTypes
|
||||||
from Products.Archetypes.Extensions.utils import install_subskin
|
from Products.Archetypes.Extensions.utils import install_subskin
|
||||||
|
|
|
@ -21,8 +21,8 @@ class <!applicationName!>PodTemplate(BaseContent, PodTemplateMixin):
|
||||||
filter_content_types = 0
|
filter_content_types = 0
|
||||||
global_allow = 1
|
global_allow = 1
|
||||||
#content_icon = '<!applicationName!>PodTemplate.gif'
|
#content_icon = '<!applicationName!>PodTemplate.gif'
|
||||||
immediate_view = '<!applicationName!>_appy_view'
|
immediate_view = 'skyn/view'
|
||||||
default_view = '<!applicationName!>_appy_view'
|
default_view = 'skyn/view'
|
||||||
suppl_views = ()
|
suppl_views = ()
|
||||||
typeDescription = "<!applicationName!>PodTemplate"
|
typeDescription = "<!applicationName!>PodTemplate"
|
||||||
typeDescMsgId = '<!applicationName!>_edit_descr'
|
typeDescMsgId = '<!applicationName!>_edit_descr'
|
||||||
|
|
|
@ -1,45 +1,16 @@
|
||||||
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
|
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||||
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
||||||
i18n:domain="<!applicationName!>">
|
i18n:domain="<!applicationName!>">
|
||||||
<body>
|
<body>
|
||||||
|
<div metal:define-macro="portlet"
|
||||||
<div metal:define-macro="portlet"
|
tal:define="tool python: context.<!toolInstanceName!>"
|
||||||
tal:define="tool python: context.<!toolInstanceName!>"
|
tal:condition="tool/showPortlet">
|
||||||
tal:condition="tool/showPortlet">
|
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
||||||
|
<dl tal:define="rootClasses tool/getRootClasses;
|
||||||
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
appName string:<!applicationName!>;
|
||||||
|
appFolder tool/getAppFolder" class="portlet">
|
||||||
<dl class="portlet"
|
<metal:content use-macro="here/skyn/macros/macros/portletContent"/>
|
||||||
tal:define="rootClasses python:[<!rootClasses!>];
|
</dl>
|
||||||
appFolder tool/getAppFolder">
|
</div>
|
||||||
|
</body>
|
||||||
<tal:comment replace="nothing">Portlet title, with link to tool.</tal:comment>
|
|
||||||
<dt class="portletHeader">
|
|
||||||
<span i18n:translate="" tal:content="python: '<!applicationName!>'">
|
|
||||||
</span>
|
|
||||||
<img i18n:attributes="title" style="cursor:pointer" title="<!applicationName!>Tool"
|
|
||||||
tal:condition="python: member.has_role('Manager')"
|
|
||||||
tal:attributes="onClick python: 'href: window.location=\'%s/\'' % tool.absolute_url();
|
|
||||||
src python: here.<!toolInstanceName!>.absolute_url() + '/appyConfig.gif'"/>
|
|
||||||
</dt>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">Links to flavours</tal:comment>
|
|
||||||
<dt class="portletAppyItem" tal:repeat="flavourInfo tool/getFlavoursInfo">
|
|
||||||
<a tal:define="flavourNumber flavourInfo/number;
|
|
||||||
rootTypes python: test(flavourNumber==1, rootClasses, ['%s_%s' % (rc, flavourNumber) for rc in rootClasses]);
|
|
||||||
rootClassesQuery python:','.join(rootTypes)"
|
|
||||||
tal:content="flavourInfo/title"
|
|
||||||
i18n:translate="" title="query_consult_all" i18n:attributes="title"
|
|
||||||
tal:attributes="href python:'%s/<!queryName!>?query=%s&flavourNumber=%d' % (appFolder.absolute_url(), rootClassesQuery, flavourNumber)"></a>
|
|
||||||
</dt>
|
|
||||||
|
|
||||||
<dt class="portletAppyItem" tal:condition="python: context.meta_type in rootClasses">
|
|
||||||
<metal:phases use-macro="here/<!macros!>/macros/phases"/>
|
|
||||||
</dt>
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
|
|
||||||
metal:use-macro="here/main_template/macros/master"
|
|
||||||
i18n:domain="<!applicationName!>">
|
|
||||||
|
|
||||||
<!-- This page presents results of queries -->
|
|
||||||
<body>
|
|
||||||
<div metal:fill-slot="top_slot">
|
|
||||||
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
|
||||||
<div tal:define="dummy python:request.set('disable_border', 1)" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div metal:fill-slot="main"
|
|
||||||
tal:define="tool python: context.<!toolInstanceName!>;
|
|
||||||
queryName python:context.REQUEST.get('query');
|
|
||||||
flavourNumber python:context.REQUEST.get('flavourNumber');
|
|
||||||
rootClasses python:[<!rootClasses!>];
|
|
||||||
rootTypes python: test(flavourNumber=='1', rootClasses, ['%s_%s' % (rc, flavourNumber) for rc in rootClasses]);
|
|
||||||
rootClassesQuery python:','.join(rootClasses);
|
|
||||||
mainTabSelected python: queryName.find(',') != -1;
|
|
||||||
appFolder tool/getAppFolder">
|
|
||||||
|
|
||||||
<span tal:condition="python: queryName and (queryName != 'none')">
|
|
||||||
<span tal:define="queryResult python: context.<!toolInstanceName!>.executeQuery(queryName, int(flavourNumber));
|
|
||||||
batch queryResult">
|
|
||||||
|
|
||||||
<!-- Tabs -->
|
|
||||||
<ul class="contentViews appyTabs">
|
|
||||||
|
|
||||||
<!-- Tab "All objects" -->
|
|
||||||
<li tal:define="selected python:mainTabSelected"
|
|
||||||
tal:attributes="class python:test(selected, 'selected', 'plain')"
|
|
||||||
tal:condition="python: len(rootClasses)>1">
|
|
||||||
|
|
||||||
<a tal:attributes="href python: '%s/<!queryName!>?query=%s&flavourNumber=%s' % (appFolder.absolute_url(), rootClassesQuery, flavourNumber)"
|
|
||||||
i18n:translate="">query_consult_all</a>
|
|
||||||
</li>
|
|
||||||
<!-- One tab for each root content type -->
|
|
||||||
<tal:tab repeat="rootContentType rootTypes">
|
|
||||||
<li tal:define="selected python:queryName == rootContentType"
|
|
||||||
tal:attributes="class python:test(selected, 'selected', 'plain')">
|
|
||||||
<a i18n:translate="" tal:content="rootContentType"
|
|
||||||
tal:attributes="href python: '%s/<!queryName!>?query=%s&flavourNumber=%s' % (appFolder.absolute_url(), rootContentType, flavourNumber)"/>
|
|
||||||
<img i18n:attributes="title" style="cursor:pointer" title="query_create" class="appyPlusImg"
|
|
||||||
tal:define="addPermission python: '<!applicationName!>: Add %s' % rootContentType"
|
|
||||||
tal:attributes="onClick python: 'href: window.location=\'%s/createObject?type_name=%s\'' % (appFolder.absolute_url(), rootContentType);
|
|
||||||
src python: here.<!toolInstanceName!>.absolute_url() + '/plus.png'"
|
|
||||||
tal:condition="python: member.has_permission(addPermission, appFolder)"/>
|
|
||||||
</li>
|
|
||||||
</tal:tab>
|
|
||||||
</ul>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<!-- Query result -->
|
|
||||||
<span tal:condition="queryResult">
|
|
||||||
<span metal:use-macro="here/<!macros!>/macros/queryResult"></span>
|
|
||||||
</span>
|
|
||||||
<span tal:condition="not: queryResult"
|
|
||||||
i18n:translate="query_no_result">No result.</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -52,14 +52,14 @@
|
||||||
/* stepxx classes are used for displaying status of a phase or state. */
|
/* stepxx classes are used for displaying status of a phase or state. */
|
||||||
.stepDone {
|
.stepDone {
|
||||||
background-color: #cde2a7;
|
background-color: #cde2a7;
|
||||||
background-image: url(&dtml-portal_url;/done.png);
|
background-image: url(&dtml-portal_url;/skyn/done.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center left;
|
background-position: center left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stepCurrent {
|
.stepCurrent {
|
||||||
background-color: #ffce7b;
|
background-color: #ffce7b;
|
||||||
background-image: url(&dtml-portal_url;/current.png);
|
background-image: url(&dtml-portal_url;/skyn/current.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center left;
|
background-position: center left;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ class <!toolName!>(UniqueObject, OrderedBaseFolder, ToolMixin):
|
||||||
filter_content_types = 0
|
filter_content_types = 0
|
||||||
global_allow = 0
|
global_allow = 0
|
||||||
#content_icon = '<!toolName!>.gif'
|
#content_icon = '<!toolName!>.gif'
|
||||||
immediate_view = '<!applicationName!>_appy_view'
|
immediate_view = 'skyn/view'
|
||||||
default_view = '<!applicationName!>_appy_view'
|
default_view = 'skyn/view'
|
||||||
suppl_views = ()
|
suppl_views = ()
|
||||||
typeDescription = "<!toolName!>"
|
typeDescription = "<!toolName!>"
|
||||||
typeDescMsgId = '<!toolName!>_edit_descr'
|
typeDescMsgId = '<!toolName!>_edit_descr'
|
||||||
|
@ -35,7 +35,7 @@ class <!toolName!>(UniqueObject, OrderedBaseFolder, ToolMixin):
|
||||||
schema = fullSchema
|
schema = fullSchema
|
||||||
schema["id"].widget.visible = False
|
schema["id"].widget.visible = False
|
||||||
schema["title"].widget.visible = False
|
schema["title"].widget.visible = False
|
||||||
# When browsing into the tool, the 'configure' portlet should be dislayed.
|
# When browsing into the tool, the 'configure' portlet should be displayed.
|
||||||
left_slots = ['here/portlet_prefs/macros/portlet']
|
left_slots = ['here/portlet_prefs/macros/portlet']
|
||||||
right_slots = []
|
right_slots = []
|
||||||
for elem in dir(ToolMixin):
|
for elem in dir(ToolMixin):
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
<tal:block metal:define-macro="master"
|
|
||||||
define="errors options/state/getErrors | nothing;
|
|
||||||
Iterator python:modules['Products.Archetypes'].IndexIterator;
|
|
||||||
schematas here/Schemata;
|
|
||||||
fieldsets python:[key for key in schematas.keys() if (key != 'metadata') and (schematas[key].editableFields(here, visible_only=True))];
|
|
||||||
default_fieldset python:(not schematas or schematas.has_key('default')) and 'default' or fieldsets[0];
|
|
||||||
fieldset request/fieldset|options/fieldset|default_fieldset;
|
|
||||||
fields python:schematas[fieldset].editableFields(here);
|
|
||||||
dummy python:here.at_isEditable(fields);
|
|
||||||
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
|
|
||||||
type_name here/getPortalTypeName|here/archetype_name;
|
|
||||||
lockable python:hasattr(here, 'wl_isLocked');
|
|
||||||
isLocked python:lockable and here.wl_isLocked();
|
|
||||||
tabindex tabindex|python:Iterator(pos=7000);
|
|
||||||
isEdit python:True;
|
|
||||||
contextObj python:context;
|
|
||||||
css python:here.getUniqueWidgetAttr(fields, 'helper_css');
|
|
||||||
js python:here.getUniqueWidgetAttr(fields, 'helper_js');
|
|
||||||
phaseInfo python: context.getAppyPhases(fieldset=fieldset, forPlone=True);
|
|
||||||
phase request/phase|phaseInfo/name;
|
|
||||||
pageName python: context.getAppyPage(isEdit, phaseInfo);">
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
|
|
||||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
|
||||||
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
|
||||||
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
||||||
metal:use-macro="here/main_template/macros/master">
|
|
||||||
|
|
||||||
<!-- Disable the Standard Plone green tab -->
|
|
||||||
<div metal:fill-slot="top_slot">
|
|
||||||
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
|
||||||
<div tal:define="dummy python:request.set('disable_border', 1)" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Archetypes stuff for managing Javascript and CSS. If I remove this stuff,
|
|
||||||
Javascript popup for dates does not work anyore -->
|
|
||||||
<metal:javascript_head fill-slot="javascript_head_slot">
|
|
||||||
<tal:block define="macro here/archetypes_custom_js/macros/javascript_head | nothing"
|
|
||||||
condition="macro">
|
|
||||||
<metal:block use-macro="macro" />
|
|
||||||
</tal:block>
|
|
||||||
<tal:js condition="js" repeat="item js">
|
|
||||||
<script type="text/javascript" charset="iso-8859-1"
|
|
||||||
tal:condition="python:exists('portal/%s' % item)"
|
|
||||||
tal:attributes="src string:$portal_url/$item">
|
|
||||||
</script>
|
|
||||||
</tal:js>
|
|
||||||
<tal:block define="macro edit_macros/javascript_head | nothing" condition="macro">
|
|
||||||
<metal:block use-macro="macro" />
|
|
||||||
</tal:block>
|
|
||||||
</metal:javascript_head>
|
|
||||||
|
|
||||||
<metal:css fill-slot="css_slot">
|
|
||||||
<tal:css condition="css" repeat="item css">
|
|
||||||
<style type="text/css" media="all"
|
|
||||||
tal:condition="python:exists('portal/%s' % item)"
|
|
||||||
tal:content="structure string:<!-- @import url($portal_url/$item); -->">
|
|
||||||
</style>
|
|
||||||
</tal:css>
|
|
||||||
<tal:block define="macro edit_macros/css | nothing" condition="macro">
|
|
||||||
<metal:block use-macro="macro" />
|
|
||||||
</tal:block>
|
|
||||||
</metal:css>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<metal:fill fill-slot="main">
|
|
||||||
<div metal:use-macro="here/<!macros!>/macros/showPagePrologue"/>
|
|
||||||
<div metal:use-macro="here/<!macros!>/macros/showPageHeader"/>
|
|
||||||
|
|
||||||
<form name="edit_form" method="post" enctype="multipart/form-data"
|
|
||||||
class="enableUnloadProtection atBaseEditForm"
|
|
||||||
tal:attributes="action python:here.absolute_url()+'/'+template.id;
|
|
||||||
id string:${portal_type}-base-edit">
|
|
||||||
|
|
||||||
<div metal:use-macro="here/<!macros!>/macros/listFields" />
|
|
||||||
|
|
||||||
<div class="formControls">
|
|
||||||
<input type="hidden" name="fieldset" tal:attributes="value fieldset"/>
|
|
||||||
<input type="hidden" name="form.submitted" value="1"/>
|
|
||||||
<input type="hidden" name="add_reference.field:record" value=""/>
|
|
||||||
<input type="hidden" name="add_reference.type:record" value=""/>
|
|
||||||
<input type="hidden" name="add_reference.destination:record" value=""/>
|
|
||||||
|
|
||||||
<tal:env define="env request/controller_state/kwargs">
|
|
||||||
<tal:loop repeat="varname python:('reference_source_url', 'reference_source_field', 'reference_source_fieldset')">
|
|
||||||
<tal:reference define="items python:env.get(varname, request.get(varname))"
|
|
||||||
condition="items">
|
|
||||||
<input tal:repeat="item items" type="hidden"
|
|
||||||
tal:attributes="value item;
|
|
||||||
name string:form_env.${varname}:list:record"/>
|
|
||||||
</tal:reference>
|
|
||||||
</tal:loop>
|
|
||||||
</tal:env>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">Turn 'persistent_' variables from controller_state persistent
|
|
||||||
</tal:comment>
|
|
||||||
<tal:env repeat="env request/controller_state/kwargs/items">
|
|
||||||
<input type="hidden"
|
|
||||||
tal:define="key python:env[0];
|
|
||||||
value python:env[1]"
|
|
||||||
tal:condition="python:key.startswith('persistent_')"
|
|
||||||
tal:attributes="name string:form_env.${key}:record;
|
|
||||||
value value"/>
|
|
||||||
</tal:env>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">Turn 'persistent_' variables from forms (GET/POST) persistent
|
|
||||||
</tal:comment>
|
|
||||||
<tal:env repeat="env request/form">
|
|
||||||
<input type="hidden"
|
|
||||||
tal:define="key env;
|
|
||||||
value request/?env"
|
|
||||||
tal:condition="python:key.startswith('persistent_')"
|
|
||||||
tal:attributes="name string:form_env.${key}:record;
|
|
||||||
value value"/>
|
|
||||||
</tal:env>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">Store referrer to remember where to go back
|
|
||||||
</tal:comment>
|
|
||||||
<input type="hidden" name="last_referer"
|
|
||||||
tal:define="last_referer python:here.session_restore_value('HTTP_REFERER', request.form.get('last_referer', request.get('HTTP_REFERER')))"
|
|
||||||
tal:attributes="value python:(last_referer and '%s/%s' % (here.absolute_url(), template.id) not in last_referer) and last_referer or (here.getParentNode() and here.getParentNode().absolute_url())"/>
|
|
||||||
|
|
||||||
<tal:comment replace="nothing">Buttons (Previous, Next, Save, etc)</tal:comment>
|
|
||||||
<metal:block define-slot="buttons"
|
|
||||||
tal:define="pages phaseInfo/pages;
|
|
||||||
pageIndex python:pages.index(fieldset);
|
|
||||||
numberOfPages python:len(pages)">
|
|
||||||
|
|
||||||
<tal:previousButton condition="python: pageIndex > 0">
|
|
||||||
<input class="context" type="submit" name="form_previous"
|
|
||||||
i18n:attributes="value label_previous;" i18n:domain="plone"
|
|
||||||
tal:attributes="tabindex tabindex/next;
|
|
||||||
disabled python:test(isLocked, 'disabled', None);"/>
|
|
||||||
<input type="hidden" name="previousPage" tal:attributes="value python: pages[pageIndex-1]"/>
|
|
||||||
</tal:previousButton>
|
|
||||||
<tal:nextButton condition="python: pageIndex < numberOfPages - 1">
|
|
||||||
<input class="context" type="submit" name="form_next" value="Next"
|
|
||||||
i18n:attributes="value label_next;" i18n:domain="plone"
|
|
||||||
tal:attributes="tabindex tabindex/next;
|
|
||||||
disabled python:test(isLocked, 'disabled', None);"/>
|
|
||||||
<input type="hidden" name="nextPage" tal:attributes="value python: pages[pageIndex+1]"/>
|
|
||||||
</tal:nextButton>
|
|
||||||
<input class="context" type="submit" name="form_submit"
|
|
||||||
i18n:attributes="value label_save;" i18n:domain="plone"
|
|
||||||
tal:attributes="tabindex tabindex/next;
|
|
||||||
disabled python:test(isLocked, 'disabled', None);"/>
|
|
||||||
<input class="standalone" type="submit" name="form.button.cancel"
|
|
||||||
i18n:attributes="value label_cancel;" i18n:domain="plone"
|
|
||||||
tal:attributes="tabindex tabindex/next"/>
|
|
||||||
</metal:block>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
<div metal:use-macro="here/<!macros!>/macros/showPageFooter"/>
|
|
||||||
</metal:fill>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
||||||
</tal:block>
|
|
|
@ -1,13 +0,0 @@
|
||||||
[default]
|
|
||||||
title = Edit
|
|
||||||
|
|
||||||
[validators]
|
|
||||||
validators = validate_base
|
|
||||||
validators..form_add =
|
|
||||||
validators..cancel =
|
|
||||||
|
|
||||||
[actions]
|
|
||||||
action.success = traverse_to:string:content_edit
|
|
||||||
action.success..form_add = traverse_to:string:add_reference
|
|
||||||
action.success..cancel = traverse_to:string:go_back
|
|
||||||
action.failure = traverse_to_action:string:edit
|
|
|
@ -13,24 +13,24 @@ import Extensions.appyWrappers
|
||||||
# every Archetype instance has a method "getProductConfig" that returns this
|
# every Archetype instance has a method "getProductConfig" that returns this
|
||||||
# module.
|
# module.
|
||||||
from persistent.list import PersistentList
|
from persistent.list import PersistentList
|
||||||
from Products.Archetypes.utils import DisplayList
|
|
||||||
from OFS.Image import File
|
from OFS.Image import File
|
||||||
from DateTime import DateTime
|
from DateTime import DateTime
|
||||||
from Products.CMFCore.utils import getToolByName
|
from Products.CMFCore.utils import getToolByName
|
||||||
from Products.CMFPlone.PloneBatch import Batch
|
from Products.CMFPlone.PloneBatch import Batch
|
||||||
from OFS.Image import File
|
from Products.Archetypes.utils import DisplayList
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger('<!applicationName!>')
|
logger = logging.getLogger('<!applicationName!>')
|
||||||
|
|
||||||
# Some global variables --------------------------------------------------------
|
# Some global variables --------------------------------------------------------
|
||||||
|
PROJECTNAME = '<!applicationName!>'
|
||||||
defaultAddRoles = [<!defaultAddRoles!>]
|
defaultAddRoles = [<!defaultAddRoles!>]
|
||||||
DEFAULT_ADD_CONTENT_PERMISSION = "Add portal content"
|
DEFAULT_ADD_CONTENT_PERMISSION = "Add portal content"
|
||||||
ADD_CONTENT_PERMISSIONS = {
|
ADD_CONTENT_PERMISSIONS = {
|
||||||
<!addPermissions!>}
|
<!addPermissions!>}
|
||||||
setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, tuple(defaultAddRoles))
|
setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, tuple(defaultAddRoles))
|
||||||
product_globals = globals()
|
product_globals = globals()
|
||||||
PROJECTNAME = '<!applicationName!>'
|
|
||||||
applicationRoles = [<!roles!>]
|
applicationRoles = [<!roles!>]
|
||||||
|
rootClasses = [<!rootClasses!>]
|
||||||
referers = {
|
referers = {
|
||||||
<!referers!>
|
<!referers!>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
## Controller Python Script "createAppyObject"
|
|
||||||
##bind container=container
|
|
||||||
##bind context=context
|
|
||||||
##bind namespace=
|
|
||||||
##bind script=script
|
|
||||||
##bind state=state
|
|
||||||
##bind subpath=traverse_subpath
|
|
||||||
##parameters=initiator, field, type_name
|
|
||||||
##title=createAppyObject
|
|
||||||
##
|
|
||||||
if not initiator or not field:
|
|
||||||
raise Exception, 'You must specify the uid of the object that initiates ' \
|
|
||||||
'this creation in the "initiator" parameter and the ' \
|
|
||||||
'related field in the "field" param.'
|
|
||||||
|
|
||||||
if not type_name:
|
|
||||||
raise Exception, 'You must specify the target type name in the "type_name" ' \
|
|
||||||
'parameter.'
|
|
||||||
|
|
||||||
initiatorRes = context.uid_catalog.searchResults(UID=initiator)
|
|
||||||
if not initiatorRes:
|
|
||||||
raise Exception, 'Given initiator UID does not correspond to a valid object.'
|
|
||||||
|
|
||||||
context.REQUEST.SESSION['initiator'] = initiator
|
|
||||||
context.REQUEST.SESSION['initiatorField'] = field
|
|
||||||
context.REQUEST.SESSION['initiatorTarget'] = type_name
|
|
||||||
return state.set(status='success')
|
|
|
@ -1,2 +0,0 @@
|
||||||
[actions]
|
|
||||||
action.success=redirect_to:python:'createObject?type_name=%s' % request.SESSION.get('initiatorTarget')
|
|
0
gen/plone25/utils.py
Executable file → Normal file
|
@ -180,8 +180,8 @@ class AbstractWrapper:
|
||||||
return appyObj
|
return appyObj
|
||||||
|
|
||||||
def translate(self, label, mapping={}, domain=None):
|
def translate(self, label, mapping={}, domain=None):
|
||||||
if not domain: domain = self.o.getProductConfig().PROJECTNAME
|
'''Check documentation of self.o.translate.'''
|
||||||
return self.o.utranslate(label, mapping, domain=domain)
|
return self.o.translate(label, mapping, domain)
|
||||||
|
|
||||||
def do(self, transition, comment='', doAction=False, doNotify=False):
|
def do(self, transition, comment='', doAction=False, doNotify=False):
|
||||||
'''This method allows to trigger on p_self a workflow p_transition
|
'''This method allows to trigger on p_self a workflow p_transition
|
||||||
|
|
1092
pod/test/Tests.rtf
95
pod/test/contexts/XhtmlComplex3.py
Executable file
|
@ -0,0 +1,95 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
xhtmlInput = '''
|
||||||
|
<ol><li>
|
||||||
|
<p>Test du champ kupu<br />A la ligne
|
||||||
|
1, j'y suis</p>
|
||||||
|
<ol><li>
|
||||||
|
<p>Ligne 1 de 1<br />A la ligne 1 de 1
|
||||||
|
fdsfds fsd fsd fksdf sdfs dfd sfsd fsd fsd fdsf dsfds fsdfa azra
|
||||||
|
zeeamr earkl kfl flks dlfksd lfklsd fklmsdfkl dskflmdsk flmsdf
|
||||||
|
lmdsflm dflsdfs fksd fmlsd flmdsk flmdsf mlsfkmls<br />A la ligne 2
|
||||||
|
de 1 cds fdsn sfd dsjfl dsjfhjds fhjdsf lqdhf klsfql kjfk jfkj
|
||||||
|
qfklmqds fjdlksqfj kdlfj klqfk qfjk ljfqklq djfklqjf qfk jkfljqd
|
||||||
|
sklfjqdklfjqdkl fjdqklf jdqlkfj qfq</p>
|
||||||
|
</li><li>
|
||||||
|
<p>Ligne 2 de 1<br />A la ligne 1 de 2
|
||||||
|
fdsfds fsd fsd fksdf sdfs dfd sfsd fsd fsd fdsf dsfds fsdfa azra
|
||||||
|
zeeamr earkl kfl flks dlfksd lfklsd fklmsdfkl dskflmdsk flmsdf
|
||||||
|
lmdsflm dflsdfs fksd fmlsd flmdsk flmdsf mlsfkmls<br />A la ligne 2
|
||||||
|
de 2 cds fdsn sfd dsjfl dsjfhjds fhjdsf lqdhf klsfql kjfk jfkj
|
||||||
|
qfklmqds fjdlksqfj kdlfj klqfk qfjk ljfqklq djfklqjf qfk jkfljqd
|
||||||
|
sklfjqdklfjqdkl fjdqklf jdqlkfj qf</p>
|
||||||
|
</li></ol>
|
||||||
|
</li><li>
|
||||||
|
<p>Ligne 2 tout court</p>
|
||||||
|
<ol><li>
|
||||||
|
<p>Ligne bullet dg fg dgd fgdf gdfg
|
||||||
|
dgq fg fgfq gfqd gfqg qfg qgkqlglk lgkl fkgkfq lmgkl mfqfkglmfk
|
||||||
|
gmlqf gmlqfgml kfmglk qmglk qmlgk qmlgkqmflgk qmlqg fmdlmslgk
|
||||||
|
mlsgml fskfmglk gmlkflmg ksfmlgk mlsgk</p>
|
||||||
|
</li><li>
|
||||||
|
<p>dsfl kqfs dmflm dsfsdf lskfmls
|
||||||
|
dkflmsdkf sdlmkf dslmfk sdmlfksd mlfksdmfl ksflmksdflmd slfmskd
|
||||||
|
lsmlfk mlsdfkl mskfmlsfk lmskfsfs</p>
|
||||||
|
</li><li>
|
||||||
|
<p>fmlsdm ùfkùds fldsf ùsfsdmfù
|
||||||
|
mdsfù msdùfms</p>
|
||||||
|
</li><li>
|
||||||
|
<p>fds fsd fdsf sdfds fsmd fmjdfklm
|
||||||
|
sdflmkd lfqlmklmdsqkflmq dskflmkd slmgkqdfmglklfmgksmldgk
|
||||||
|
dmlsgdkdlm fgkmdl fkgdmlfsgk mlfgksmdl fgkmldsf klmmdfkg mlsdfkgml
|
||||||
|
skfdgml skgmlkfd smlgksd mlkgml kml</p>
|
||||||
|
</li><li>
|
||||||
|
<p>lgd ksmlgjk mlsdfgkml sdfkglm
|
||||||
|
kdsfmlgk dlmskgsldmgk lms</p>
|
||||||
|
</li></ol>
|
||||||
|
</li><li>
|
||||||
|
<p>Ligne 3 tout court</p>
|
||||||
|
</li></ol>
|
||||||
|
<br />'''
|
||||||
|
|
||||||
|
xhtmlInput2 = '''
|
||||||
|
<ol start="1"><li>Le Gouvernement approuve la réaffectation de 20.056.989 € attribués dans le cadre du CRAC II et l’affectation du solde de 20.855.107 € du solde des CRAC Ibis et II au sein du secteur des hôpitaux de l’enveloppe de financement alternatif pour un montant total de 40.921.096 €, au bénéfice des établissements suivants :<br /><br /></li>
|
||||||
|
<table align="center">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<b>Etablissement</b></td>
|
||||||
|
<td>
|
||||||
|
<p align="center" style="text-align: center;"><b>CRAC II Phase II</b></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>C.H. Chrétien Liège</p>
|
||||||
|
</td>
|
||||||
|
<td nowrap="-1">
|
||||||
|
<p align="center" style="text-align: center;">11.097.377</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td nowrap="-1">
|
||||||
|
<p>Hôp. St-Joseph, Ste-Thérèse et IMTR Gilly</p>
|
||||||
|
</td>
|
||||||
|
<td nowrap="-1">
|
||||||
|
<p align="center" style="text-align: center;">8.297.880</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<br /><li>Il prend acte des décisions du Ministre de la Santé relatives à l’octroi de la règle de 10/90 pour la subsidiation des infrastructures des établissements concernés.<br /></li>
|
||||||
|
<li>Le Gouvernement charge le Ministre de la Santé d’appliquer, le cas échéant, les nouveaux plafonds à la construction visés dans l’arrêté ministériel du 11 mai 2007 fixant le coût maximal pouvant être pris en considération pour l’octroi des subventions pour la construction de nouveaux bâtiments, les travaux d’extension et de reconditionnement d’un hôpital ou d’un service, aux demandes d’octroi de subventions antérieures au 1<sup>er</sup> janvier 2006, pour autant que ces demandes d’octroi de subventions n’aient pas encore donné lieu à l’exploitation à cette même date.<br /></li>
|
||||||
|
<li>Il charge le Ministre de la Santé de l’exécution de la présente décision</li></ol>
|
||||||
|
<p></p>
|
||||||
|
'''
|
||||||
|
|
||||||
|
xhtmlInput3 = '''
|
||||||
|
<ol><li>Le Gouvernement l'exercice 2008.</li><li>Il approuve 240.000€ de007-2008.</li><li>Le Gouvernement approuve:
|
||||||
|
<ul><li>le projet d'arrêté ministériel 008;</li><li>le projet d'arrêté ministériel mique 2008-2009.</li></ul></li><li>Le Gouvernement charge le Ministre de l'Economie de l'exécution de la présente décision.</li></ol>
|
||||||
|
'''
|
||||||
|
|
||||||
|
xhtmlInput4 = '''
|
||||||
|
<div><strong>Programmes FSE Convergence et Compétitivité régionale et emploi.</strong></div>
|
||||||
|
<div><strong>Axe 1, mesure 1, et Axe 2, mesures 2, 3, 4 et 5 : formation.</strong></div>
|
||||||
|
<div><strong>Portefeuille de projets « Enseignement supérieur - Formation continue ».</strong></div>
|
||||||
|
'''
|
|
@ -1,4 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
xhtmlInput = '''
|
xhtmlInput = '''
|
||||||
<p>Some HTML entities: é: é, è: è, Atilde: Ã.</p>
|
<p>Some HTML entities: é: é, è: è, Atilde: Ã.</p>
|
||||||
<p>XML entities: amp: &, quote: ", apos: ', lt: <, gt: >.</p>'''
|
<p>XML entities: amp: &, quote: ", apos: ', lt: <, gt: >.</p>
|
||||||
|
<p> </p><p>Para</p>'''
|
||||||
|
|
BIN
pod/test/results/xhtmlComplex3.odt
Normal file
BIN
pod/test/results/xhtmlEntities.odt
Executable file → Normal file
BIN
pod/test/templates/XhtmlComplex3.odt
Executable file
|
@ -1 +0,0 @@
|
||||||
0.2.1 (2008-06-04)
|
|
131
pod/xhtml2odt.py
|
@ -25,8 +25,8 @@ from appy.pod import *
|
||||||
|
|
||||||
# To which ODT tag does HTML tags correspond ?
|
# To which ODT tag does HTML tags correspond ?
|
||||||
HTML_2_ODT = {'h1':'h', 'h2':'h', 'h3':'h', 'h4':'h', 'h5':'h', 'h6':'h',
|
HTML_2_ODT = {'h1':'h', 'h2':'h', 'h3':'h', 'h4':'h', 'h5':'h', 'h6':'h',
|
||||||
'p':'p', 'b':'span', 'i':'span', 'strong':'span', 'em': 'span',
|
'p':'p', 'b':'span', 'i':'span', 'strong':'span', 'em': 'span',
|
||||||
'sub': 'span', 'sup': 'span', 'br': 'line-break', 'div': 'span'}
|
'sub': 'span', 'sup': 'span', 'br': 'line-break', 'div': 'span'}
|
||||||
DEFAULT_ODT_STYLES = {'b': 'podBold', 'strong':'podBold', 'i': 'podItalic',
|
DEFAULT_ODT_STYLES = {'b': 'podBold', 'strong':'podBold', 'i': 'podItalic',
|
||||||
'em': 'podItalic', 'sup': 'podSup', 'sub':'podSub',
|
'em': 'podItalic', 'sup': 'podSup', 'sub':'podSub',
|
||||||
'td': 'podCell', 'th': 'podHeaderCell'}
|
'td': 'podCell', 'th': 'podHeaderCell'}
|
||||||
|
@ -35,6 +35,7 @@ TABLE_CELL_TAGS = ('td', 'th')
|
||||||
OUTER_TAGS = TABLE_CELL_TAGS + ('li',)
|
OUTER_TAGS = TABLE_CELL_TAGS + ('li',)
|
||||||
NOT_INSIDE_P = ('table', 'ol', 'ul') # Those elements can't be rendered inside
|
NOT_INSIDE_P = ('table', 'ol', 'ul') # Those elements can't be rendered inside
|
||||||
# paragraphs.
|
# paragraphs.
|
||||||
|
NOT_INSIDE_LIST = ('table',)
|
||||||
IGNORABLE_TAGS = ('meta', 'title', 'style')
|
IGNORABLE_TAGS = ('meta', 'title', 'style')
|
||||||
HTML_ENTITIES = {
|
HTML_ENTITIES = {
|
||||||
'iexcl': '¡', 'cent': '¢', 'pound': '£', 'curren': '€', 'yen': '¥',
|
'iexcl': '¡', 'cent': '¢', 'pound': '£', 'curren': '€', 'yen': '¥',
|
||||||
|
@ -56,8 +57,8 @@ HTML_ENTITIES = {
|
||||||
'ntilde':'ñ', 'ograve':'ò', 'oacute':'ó', 'ocirc':'ô', 'otilde':'õ',
|
'ntilde':'ñ', 'ograve':'ò', 'oacute':'ó', 'ocirc':'ô', 'otilde':'õ',
|
||||||
'ouml':'ö', 'divide':'÷', 'oslash':'ø', 'ugrave':'ù', 'uacute':'ú',
|
'ouml':'ö', 'divide':'÷', 'oslash':'ø', 'ugrave':'ù', 'uacute':'ú',
|
||||||
'ucirc':'û', 'uuml':'ü', 'yacute':'ý', 'thorn':'þ', 'yuml':'ÿ',
|
'ucirc':'û', 'uuml':'ü', 'yacute':'ý', 'thorn':'þ', 'yuml':'ÿ',
|
||||||
'euro':'€', 'nbsp':' ', "rsquo":"'", 'ndash': ' ', 'oelig':'oe',
|
'euro':'€', 'nbsp':' ', "rsquo":"'", "lsquo":"'", "ldquo":"'",
|
||||||
'quot': "'", 'mu': 'µ'}
|
"rdquo":"'", 'ndash': ' ', 'oelig':'oe', 'quot': "'", 'mu': 'µ'}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Entity:
|
class Entity:
|
||||||
|
@ -71,6 +72,8 @@ class HtmlElement:
|
||||||
'''Every time an HTML element is encountered during the SAX parsing,
|
'''Every time an HTML element is encountered during the SAX parsing,
|
||||||
an instance of this class is pushed on the stack of currently parsed
|
an instance of this class is pushed on the stack of currently parsed
|
||||||
elements.'''
|
elements.'''
|
||||||
|
elemTypes = {'p':'para', 'li':'para','ol':'list','ul':'list'}
|
||||||
|
odfElems = {'p':'p', 'li':'list-item', 'ol': 'list', 'ul': 'list'}
|
||||||
def __init__(self, elem, attrs):
|
def __init__(self, elem, attrs):
|
||||||
self.elem = elem
|
self.elem = elem
|
||||||
# Keep "class" attribute (useful for finding the corresponding ODT
|
# Keep "class" attribute (useful for finding the corresponding ODT
|
||||||
|
@ -80,34 +83,42 @@ class HtmlElement:
|
||||||
self.classAttr = None
|
self.classAttr = None
|
||||||
if attrs.has_key('class'):
|
if attrs.has_key('class'):
|
||||||
self.classAttr = attrs['class']
|
self.classAttr = attrs['class']
|
||||||
self.tagsToReopen = '' # When the HTML element corresponding to self
|
self.tagsToReopen = [] # When the HTML element corresponding to self
|
||||||
# is completely dumped, if there was a problem related to tags
|
# is completely dumped, if there was a problem related to tags
|
||||||
# inclusion, we may need to dump start tags corresponding to
|
# inclusion, we may need to dump start tags corresponding to
|
||||||
# tags that we had to close before dumping this element.
|
# tags that we had to close before dumping this element. This list
|
||||||
self.tagsToClose = '' # Before dumping the closing tag corresponding
|
# contains HtmlElement instances.
|
||||||
|
self.tagsToClose = [] # Before dumping the closing tag corresponding
|
||||||
# to self, we may need to close other tags (ie closing a paragraph
|
# to self, we may need to close other tags (ie closing a paragraph
|
||||||
# before closing a cell).
|
# before closing a cell). This list contains HtmlElement instances.
|
||||||
def isParagraph(self, env):
|
self.elemType = self.elem
|
||||||
'''This methods returns True if:
|
if self.elemTypes.has_key(self.elem):
|
||||||
- self is a "p";
|
self.elemType = self.elemTypes[self.elem]
|
||||||
- self is a "td" or "th" inside which a "p" was added.'''
|
|
||||||
return (self.elem == 'p') or \
|
def getOdfTag(self, env):
|
||||||
( (self.elem in OUTER_TAGS) and \
|
'''Gets the ODF tag that corresponds to me.'''
|
||||||
(self.tagsToClose == '</%s:p>' % env.textNs))
|
return '%s:%s' % (env.textNs, self.odfElems[self.elem])
|
||||||
|
|
||||||
def getConflictualElements(self, env):
|
def getConflictualElements(self, env):
|
||||||
'''self was just parsed. In some cases, this element can't be dumped
|
'''self was just parsed. In some cases, this element can't be dumped
|
||||||
in the result because there are conflictual elements among previously
|
in the result because there are conflictual elements among previously
|
||||||
parsed opening elements (p_currentElements). For example, if we just
|
parsed opening elements (p_currentElements). For example, if we just
|
||||||
dumped a "p", we can't dump a table within the "p". Such constraints
|
dumped a "p", we can't dump a table within the "p". Such constraints
|
||||||
do not hold in XHTML code but hold in ODF code.
|
do not hold in XHTML code but hold in ODF code.'''
|
||||||
|
|
||||||
!! Conflictual elements must be listed in HTML_2_ODT !! '''
|
|
||||||
res = ()
|
|
||||||
if env.currentElements:
|
if env.currentElements:
|
||||||
if (env.currentElements[-1].isParagraph(env)) and \
|
parentElem = env.currentElements[-1]
|
||||||
(self.elem in NOT_INSIDE_P):
|
# Check elements that can't be found within a paragraph
|
||||||
res = ('p',)
|
if (parentElem.elemType=='para') and (self.elem in NOT_INSIDE_P):
|
||||||
return res
|
return (parentElem,)
|
||||||
|
if (parentElem.elem in OUTER_TAGS) and parentElem.tagsToClose and \
|
||||||
|
(parentElem.tagsToClose[-1].elem == 'p') and \
|
||||||
|
(self.elem in NOT_INSIDE_P):
|
||||||
|
return (parentElem.tagsToClose[-1],)
|
||||||
|
# Check elements that can't be found within a list
|
||||||
|
if (parentElem.elemType=='list') and (self.elem in NOT_INSIDE_LIST):
|
||||||
|
return (parentElem,)
|
||||||
|
return ()
|
||||||
|
|
||||||
def addInnerParagraph(self, env):
|
def addInnerParagraph(self, env):
|
||||||
'''Dump an inner paragraph inside self (if not already done).'''
|
'''Dump an inner paragraph inside self (if not already done).'''
|
||||||
if not self.tagsToClose:
|
if not self.tagsToClose:
|
||||||
|
@ -124,7 +135,36 @@ class HtmlElement:
|
||||||
env.dumpString(' %s:style-name="%s"' % (env.textNs,
|
env.dumpString(' %s:style-name="%s"' % (env.textNs,
|
||||||
env.itemStyles[itemStyle]))
|
env.itemStyles[itemStyle]))
|
||||||
env.dumpString('>')
|
env.dumpString('>')
|
||||||
self.tagsToClose = '</%s:p>' % env.textNs
|
self.tagsToClose.append(HtmlElement('p',{}))
|
||||||
|
|
||||||
|
def dump(self, start, env):
|
||||||
|
'''Dumps the start or stop (depending onp_start) tag of this HTML
|
||||||
|
element. We must take care of potential innerTags.'''
|
||||||
|
# Compute the tag in itself
|
||||||
|
tag = ''
|
||||||
|
prefix = '<'
|
||||||
|
if not start: prefix += '/'
|
||||||
|
# Compute tag attributes
|
||||||
|
attrs = ''
|
||||||
|
if start:
|
||||||
|
if self.elemType == 'list':
|
||||||
|
# I must specify the list style
|
||||||
|
attrs += ' %s:style-name="%s"' % (
|
||||||
|
env.textNs, env.listStyles[self.elem])
|
||||||
|
if self.elem == 'ol':
|
||||||
|
# I have interrupted a numbered list. I need to continue
|
||||||
|
# the numbering.
|
||||||
|
attrs += ' %s:continue-numbering="true"' % env.textNs
|
||||||
|
tag = prefix + self.getOdfTag(env) + attrs + '>'
|
||||||
|
# Close/open subTags if any
|
||||||
|
for subElem in self.tagsToClose:
|
||||||
|
subTag = subElem.dump(start, env)
|
||||||
|
if start: tag += subTag
|
||||||
|
else: tag = subTag + tag
|
||||||
|
return tag
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<Html "%s">' % self.elem
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class HtmlTable:
|
class HtmlTable:
|
||||||
|
@ -156,6 +196,7 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
itemStyles = {'ul': 'podBulletItem', 'ol': 'podNumberItem',
|
itemStyles = {'ul': 'podBulletItem', 'ol': 'podNumberItem',
|
||||||
'ul_kwn': 'podBulletItemKeepWithNext',
|
'ul_kwn': 'podBulletItemKeepWithNext',
|
||||||
'ol_kwn': 'podNumberItemKeepWithNext'}
|
'ol_kwn': 'podNumberItemKeepWithNext'}
|
||||||
|
listStyles = {'ul': 'podBulletedList', 'ol': 'podNumberedList'}
|
||||||
def __init__(self, ns):
|
def __init__(self, ns):
|
||||||
XmlEnvironment.__init__(self)
|
XmlEnvironment.__init__(self)
|
||||||
self.res = u''
|
self.res = u''
|
||||||
|
@ -255,6 +296,16 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
self.textNs, odtStyle.outlineLevel))
|
self.textNs, odtStyle.outlineLevel))
|
||||||
self.dumpString('>')
|
self.dumpString('>')
|
||||||
|
|
||||||
|
def dumpTags(self, elems, start=True):
|
||||||
|
'''Dumps a series of start or end tags (depending on p_start) of
|
||||||
|
HtmlElement instances in p_elems.'''
|
||||||
|
tags = ''
|
||||||
|
for elem in elems:
|
||||||
|
tag = elem.dump(start, self)
|
||||||
|
if start: tags += tag
|
||||||
|
else: tags = tag + tags
|
||||||
|
self.dumpString(tags)
|
||||||
|
|
||||||
def dumpString(self, s):
|
def dumpString(self, s):
|
||||||
'''Dumps arbitrary content p_s.
|
'''Dumps arbitrary content p_s.
|
||||||
If the table stack is not empty, we must dump p_s into the buffer
|
If the table stack is not empty, we must dump p_s into the buffer
|
||||||
|
@ -269,6 +320,14 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
else:
|
else:
|
||||||
self.res += s
|
self.res += s
|
||||||
|
|
||||||
|
def getTagsToReopen(self, conflictElems):
|
||||||
|
'''Normally, tags to reopen are equal to p_conflictElems. But we have a
|
||||||
|
special case. Indeed, if a conflict elem has itself tagsToClose,
|
||||||
|
the last tag to close may not be needed anymore on the tag to
|
||||||
|
reopen, so we remove it.'''
|
||||||
|
conflictElems[-1].tagsToClose = []
|
||||||
|
return conflictElems
|
||||||
|
|
||||||
def onElementStart(self, elem, attrs):
|
def onElementStart(self, elem, attrs):
|
||||||
previousElem = self.getCurrentElement()
|
previousElem = self.getCurrentElement()
|
||||||
if previousElem and (previousElem.elem == 'podxhtml'):
|
if previousElem and (previousElem.elem == 'podxhtml'):
|
||||||
|
@ -281,14 +340,8 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
if conflictElems:
|
if conflictElems:
|
||||||
# We must close the conflictual elements, and once the currentElem
|
# We must close the conflictual elements, and once the currentElem
|
||||||
# will be dumped, we will re-open the conflictual elements.
|
# will be dumped, we will re-open the conflictual elements.
|
||||||
closingTags = ''
|
self.dumpTags(conflictElems, start=False)
|
||||||
openingTags = ''
|
currentElem.tagsToReopen = self.getTagsToReopen(conflictElems)
|
||||||
for conflictElem in conflictElems:
|
|
||||||
odtElem = HTML_2_ODT[conflictElem]
|
|
||||||
closingTags = ('</%s:%s>' % (self.textNs, odtElem))+ closingTags
|
|
||||||
openingTags += '<%s:%s>' % (self.textNs, odtElem)
|
|
||||||
self.dumpString(closingTags)
|
|
||||||
currentElem.tagsToReopen = openingTags
|
|
||||||
# Manage missing elements
|
# Manage missing elements
|
||||||
if self.anElementIsMissing(previousElem, currentElem):
|
if self.anElementIsMissing(previousElem, currentElem):
|
||||||
previousElem.addInnerParagraph(self)
|
previousElem.addInnerParagraph(self)
|
||||||
|
@ -333,14 +386,13 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
lastTable.res += lastTable.tempRes
|
lastTable.res += lastTable.tempRes
|
||||||
lastTable.tempRes = u''
|
lastTable.tempRes = u''
|
||||||
if currentElem.tagsToClose:
|
if currentElem.tagsToClose:
|
||||||
self.dumpString(currentElem.tagsToClose)
|
self.dumpTags(currentElem.tagsToClose, start=False)
|
||||||
if currentElem.tagsToReopen:
|
if currentElem.tagsToReopen:
|
||||||
res = currentElem.tagsToReopen
|
res = currentElem.tagsToReopen
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class XhtmlParser(XmlParser):
|
class XhtmlParser(XmlParser):
|
||||||
listStyles = {'ul': 'podBulletedList', 'ol': 'podNumberedList'}
|
|
||||||
# Initialize entities recognized by this parser
|
# Initialize entities recognized by this parser
|
||||||
entities = {}
|
entities = {}
|
||||||
for name, value in HTML_ENTITIES.iteritems():
|
for name, value in HTML_ENTITIES.iteritems():
|
||||||
|
@ -398,7 +450,7 @@ class XhtmlParser(XmlParser):
|
||||||
# must be surrounded by a list-item element.
|
# must be surrounded by a list-item element.
|
||||||
prologue = '<%s:list-item>' % e.textNs
|
prologue = '<%s:list-item>' % e.textNs
|
||||||
e.dumpString('%s<%s:list %s:style-name="%s">' % (
|
e.dumpString('%s<%s:list %s:style-name="%s">' % (
|
||||||
prologue, e.textNs, e.textNs, self.listStyles[elem]))
|
prologue, e.textNs, e.textNs, e.listStyles[elem]))
|
||||||
elif elem == 'li':
|
elif elem == 'li':
|
||||||
e.dumpString('<%s:list-item>' % e.textNs)
|
e.dumpString('<%s:list-item>' % e.textNs)
|
||||||
elif elem == 'table':
|
elif elem == 'table':
|
||||||
|
@ -424,6 +476,9 @@ class XhtmlParser(XmlParser):
|
||||||
e = XmlParser.endElement(self, elem)
|
e = XmlParser.endElement(self, elem)
|
||||||
elemsToReopen = e.onElementEnd(elem)
|
elemsToReopen = e.onElementEnd(elem)
|
||||||
if HTML_2_ODT.has_key(elem):
|
if HTML_2_ODT.has_key(elem):
|
||||||
|
# For "div" elements, we put append a carriage return.
|
||||||
|
if elem == 'div':
|
||||||
|
e.dumpString('<%s:line-break/>' % e.textNs)
|
||||||
e.dumpString('</%s:%s>' % (e.textNs, HTML_2_ODT[elem]))
|
e.dumpString('</%s:%s>' % (e.textNs, HTML_2_ODT[elem]))
|
||||||
elif elem == 'a':
|
elif elem == 'a':
|
||||||
e.dumpString('</%s:a>' % e.textNs)
|
e.dumpString('</%s:a>' % e.textNs)
|
||||||
|
@ -447,7 +502,7 @@ class XhtmlParser(XmlParser):
|
||||||
elif elem in IGNORABLE_TAGS:
|
elif elem in IGNORABLE_TAGS:
|
||||||
e.ignore = False
|
e.ignore = False
|
||||||
if elemsToReopen:
|
if elemsToReopen:
|
||||||
e.dumpString(elemsToReopen)
|
e.dumpTags(elemsToReopen)
|
||||||
|
|
||||||
def characters(self, content):
|
def characters(self, content):
|
||||||
e = XmlParser.characters(self, content)
|
e = XmlParser.characters(self, content)
|
||||||
|
@ -469,11 +524,7 @@ class Xhtml2OdtConverter:
|
||||||
self.xhtmlParser = XhtmlParser(XhtmlEnvironment(ns), self)
|
self.xhtmlParser = XhtmlParser(XhtmlEnvironment(ns), self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
#print 'XHTML is **', self.xhtmlString, '**'
|
|
||||||
#print
|
|
||||||
self.xhtmlParser.parse(self.xhtmlString)
|
self.xhtmlParser.parse(self.xhtmlString)
|
||||||
#print 'ODT chunk is **', self.xhtmlParser.env.res, '**'
|
|
||||||
#print
|
|
||||||
return self.xhtmlParser.env.res
|
return self.xhtmlParser.env.res
|
||||||
|
|
||||||
def findStyle(self, elem, attrs=None, classValue=None):
|
def findStyle(self, elem, attrs=None, classValue=None):
|
||||||
|
|