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