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.

This commit is contained in:
Gaetan Delannay 2009-10-18 14:52:27 +02:00
parent 280c5fe0c0
commit cbc7d257d4
50 changed files with 1317 additions and 1189 deletions

View file

@ -1 +1,3 @@
import os.path
def getPath(): return os.path.dirname(__file__)

0
gen/plone25/__init__.py Executable file → Normal file
View file

0
gen/plone25/descriptors.py Executable file → Normal file
View file

55
gen/plone25/generator.py Executable file → Normal file
View 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

View file

@ -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.'''

View file

@ -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']
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -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
View file

View file

Before

Width:  |  Height:  |  Size: 899 B

After

Width:  |  Height:  |  Size: 899 B

View file

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View file

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View 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
View 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)

View file

Before

Width:  |  Height:  |  Size: 818 B

After

Width:  |  Height:  |  Size: 818 B

View file

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 248 B

118
gen/plone25/skin/edit.pt Normal file
View 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 &gt; 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 &lt; 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>

View 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)&lt;=maxShownTemplates" <span class="discreet" tal:condition="python: len(podTemplates)&lt;=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>
&nbsp;</span> &nbsp;</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)&gt;maxShownTemplates"> <select tal:condition="python: len(podTemplates)&gt;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"/>&nbsp;
<label tal:attributes="for fieldName" tal:condition="showLabel" tal:content="label"/> <span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0] &gt; 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] &gt; 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', '&lt;br&gt;')"/> tal:replace="structure python: value.replace('\n', '&lt;br&gt;')"/>
<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']&gt;1">&minus; <span class="discreet" tal:condition="python: phaseInfo['totalNbOfPhases']&gt;1">&minus;
<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)&gt;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)&gt;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)&gt;1, True)"> tal:condition="python: test(showAllStatesInPhase, len(states)&gt;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)"/>&nbsp;
<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>

View file

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 201 B

View file

Before

Width:  |  Height:  |  Size: 192 B

After

Width:  |  Height:  |  Size: 192 B

View file

Before

Width:  |  Height:  |  Size: 754 B

After

Width:  |  Height:  |  Size: 754 B

View file

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 228 B

View file

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

64
gen/plone25/skin/query.pt Normal file
View 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>

View 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 &gt; 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 &lt; (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)&lt;=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"/>&nbsp; use-macro="here/skyn/ref/macros/objectTitle"/>&nbsp;
</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>&nbsp; </tal:showOtherField>&nbsp;
</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>&nbsp;
i18n:translate="" tal:content="field/widget/label_msgid"></label> <span class="fieldRequired" tal:condition="python: appyType['multiplicity'][0]&gt;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>

View file

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

View 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>

View file

@ -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'

View file

@ -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'

View file

@ -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

View file

@ -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'

View file

@ -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>&nbsp;
<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>

View file

@ -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>

View file

@ -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;
} }

View file

@ -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):

View file

@ -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 &gt; 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 &lt; 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>

View file

@ -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

View file

@ -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!>
} }

View file

@ -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')

View file

@ -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
View file

View 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

File diff suppressed because it is too large Load diff

View 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 laffectation du solde de 20.855.107 du solde des CRAC Ibis et II au sein du secteur des hôpitaux de lenveloppe 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 à loctroi 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é dappliquer, le cas échéant, les nouveaux plafonds à la construction visés dans larrêté ministériel du 11 mai 2007 fixant le coût maximal pouvant être pris en considération pour loctroi des subventions pour la construction de nouveaux bâtiments, les travaux dextension et de reconditionnement dun hôpital ou dun service, aux demandes doctroi de subventions antérieures au 1<sup>er</sup> janvier 2006, pour autant que ces demandes doctroi de subventions naient pas encore donné lieu à lexploitation à cette même date.<br /></li>
<li>Il charge le Ministre de la Santé de lexé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>
'''

View file

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
xhtmlInput = ''' xhtmlInput = '''
<p>Some HTML entities: é: &eacute;, è: &egrave;, Atilde: &Atilde;.</p> <p>Some HTML entities: é: &eacute;, è: &egrave;, Atilde: &Atilde;.</p>
<p>XML entities: amp: &amp;, quote: &quot;, apos: &apos;, lt: &lt;, gt: &gt;.</p>''' <p>XML entities: amp: &amp;, quote: &quot;, apos: &apos;, lt: &lt;, gt: &gt;.</p>
<p>&nbsp;</p><p>Para</p>'''

Binary file not shown.

Binary file not shown.

BIN
pod/test/results/xhtmlEntities.odt Executable file → Normal file

Binary file not shown.

Binary file not shown.

View file

@ -1 +0,0 @@
0.2.1 (2008-06-04)

View file

@ -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):