new.py now can create instances for Plone 2.5.5, Plone 3.0 to Plone 3.3.5. specificWritePermission and specificReadPermission can hold named (string) permissions instead of simple boolean values (which is still allowed). frontPage can call a custom macro. When launching generate.py with -c option, labels prefixed with custom_ are kept.
This commit is contained in:
parent
bfd2357f69
commit
dbcadc506d
17 changed files with 188 additions and 126 deletions
|
@ -156,11 +156,8 @@ class Generator(AbstractGenerator):
|
|||
self.generateWorkflows()
|
||||
self.generateWrappers()
|
||||
self.generateTests()
|
||||
if self.config.frontPage == True:
|
||||
self.labels.append(msg('front_page_text', '', msg.FRONT_PAGE_TEXT))
|
||||
self.copyFile('frontPage.pt', self.repls,
|
||||
destFolder=self.skinsFolder,
|
||||
destName='%sFrontPage.pt' % self.applicationName)
|
||||
if self.config.frontPage:
|
||||
self.generateFrontPage()
|
||||
self.copyFile('configure.zcml', self.repls)
|
||||
self.copyFile('import_steps.xml', self.repls,
|
||||
destFolder='profiles/default')
|
||||
|
@ -169,8 +166,6 @@ class Generator(AbstractGenerator):
|
|||
self.copyFile('Portlet.pt', self.repls,
|
||||
destName='%s.pt' % self.portletName, destFolder=self.skinsFolder)
|
||||
self.copyFile('tool.gif', {})
|
||||
self.copyFile(
|
||||
'global_statusmessage.pt', {}, destFolder=self.skinsFolder)
|
||||
self.copyFile('Styles.css.dtml',self.repls, destFolder=self.skinsFolder,
|
||||
destName = '%s.css.dtml' % self.applicationName)
|
||||
self.copyFile('IEFixes.css.dtml',self.repls,destFolder=self.skinsFolder)
|
||||
|
@ -418,7 +413,7 @@ class Generator(AbstractGenerator):
|
|||
repls['appClasses'] = "[%s]" % ','.join(appClasses)
|
||||
repls['minimalistPlone'] = self.config.minimalistPlone
|
||||
repls['showPortlet'] = self.config.showPortlet
|
||||
repls['appFrontPage'] = self.config.frontPage == True
|
||||
repls['appFrontPage'] = bool(self.config.frontPage)
|
||||
repls['workflows'] = workflows
|
||||
self.copyFile('Install.py', repls, destFolder='Extensions')
|
||||
|
||||
|
@ -576,6 +571,27 @@ class Generator(AbstractGenerator):
|
|||
repls['modulesWithTests'] = ','.join(modules)
|
||||
self.copyFile('testAll.py', repls, destFolder='tests')
|
||||
|
||||
def generateFrontPage(self):
|
||||
fp = self.config.frontPage
|
||||
repls = self.repls.copy()
|
||||
if fp == True:
|
||||
# We need a front page, but no specific one has been given.
|
||||
# So we will create a basic one that will simply display
|
||||
# some translated text.
|
||||
self.labels.append(msg('front_page_text', '', msg.FRONT_PAGE_TEXT))
|
||||
repls['pageContent'] = '<span tal:replace="structure python: ' \
|
||||
'tool.translateWithMapping(\'front_page_text\')"/>'
|
||||
else:
|
||||
# The user has specified a macro to show. So in the generated front
|
||||
# page, we will call this macro. The user will need to add itself
|
||||
# a .pt file containing this macro in the skins folder of the
|
||||
# generated Plone product.
|
||||
page, macro = fp.split('/')
|
||||
repls['pageContent'] = '<metal:call use-macro=' \
|
||||
'"context/%s/macros/%s"/>' % (page, macro)
|
||||
self.copyFile('frontPage.pt', repls, destFolder=self.skinsFolder,
|
||||
destName='%sFrontPage.pt' % self.applicationName)
|
||||
|
||||
def generateTool(self):
|
||||
'''Generates the Plone tool that corresponds to this application.'''
|
||||
# Generate the tool class in itself and related i18n messages
|
||||
|
|
|
@ -74,8 +74,16 @@ class ToolMixin(AbstractMixin):
|
|||
'''Returns the list of root classes for this application.'''
|
||||
return self.getProductConfig().rootClasses
|
||||
|
||||
def showPortlet(self):
|
||||
return not self.portal_membership.isAnonymousUser()
|
||||
def showPortlet(self, context):
|
||||
if self.portal_membership.isAnonymousUser(): return False
|
||||
if context.id == 'skyn': context = context.getParentNode()
|
||||
res = True
|
||||
if not self.getRootClasses():
|
||||
res = False
|
||||
# If there is no root class, show the portlet only if we are within
|
||||
# the configuration.
|
||||
if (self.id in context.absolute_url()): res = True
|
||||
return res
|
||||
|
||||
def getObject(self, uid, appy=False):
|
||||
'''Allows to retrieve an object from its p_uid.'''
|
||||
|
@ -630,7 +638,7 @@ class ToolMixin(AbstractMixin):
|
|||
contentType, flavourNumber = d1.split(':')
|
||||
flavourNumber = int(flavourNumber)
|
||||
searchName = keySuffix = d2
|
||||
batchSize = self.getNumberOfResultsPerPage()
|
||||
batchSize = self.appy().numberOfResultsPerPage
|
||||
if not searchName: keySuffix = contentType
|
||||
s = self.REQUEST.SESSION
|
||||
searchKey = 'search_%s_%s' % (flavourNumber, keySuffix)
|
||||
|
|
|
@ -285,23 +285,23 @@ class AbstractMixin:
|
|||
'''Returns the method named p_methodName.'''
|
||||
return getattr(self, methodName, None)
|
||||
|
||||
def getFormattedValue(self, name, useParamValue=False, value=None,
|
||||
forMasterId=False):
|
||||
def getFieldValue(self, name, useParamValue=False, value=None,
|
||||
formatted=True):
|
||||
'''Returns the value of field named p_name for this object (p_self).
|
||||
|
||||
If p_useParamValue is True, the method uses p_value instead of the
|
||||
real field value (useful for rendering a value from the object
|
||||
history, for example).
|
||||
|
||||
If p_forMasterId is True, it returns the value as will be needed to
|
||||
produce an identifier used within HTML pages for master/slave
|
||||
relationships.'''
|
||||
If p_formatted is False, it will return the true database
|
||||
(or default) value. Else, it will produce a nice, string and
|
||||
potentially translated value.'''
|
||||
appyType = self.getAppyType(name)
|
||||
# Which value will we use ?
|
||||
if not useParamValue:
|
||||
value = appyType.getValue(self)
|
||||
# Return the value as is if it is None or forMasterId
|
||||
if forMasterId: return value
|
||||
if not formatted: return value
|
||||
# Return the formatted value else
|
||||
return appyType.getFormattedValue(self, value)
|
||||
|
||||
|
@ -741,7 +741,7 @@ class AbstractMixin:
|
|||
res = brains
|
||||
return res
|
||||
|
||||
def fieldValueSelected(self, fieldName, vocabValue):
|
||||
def fieldValueSelected(self, fieldName, vocabValue, dbValue):
|
||||
'''When displaying a selection box (ie a String with a validator being a
|
||||
list), must the _vocabValue appear as selected?'''
|
||||
rq = self.REQUEST
|
||||
|
@ -749,14 +749,14 @@ class AbstractMixin:
|
|||
if rq.has_key(fieldName):
|
||||
compValue = rq.get(fieldName)
|
||||
else:
|
||||
compValue = self.getAppyType(fieldName).getValue(self)
|
||||
compValue = dbValue
|
||||
# Compare the value
|
||||
if type(compValue) in sequenceTypes:
|
||||
if vocabValue in compValue: return True
|
||||
else:
|
||||
if vocabValue == compValue: return True
|
||||
|
||||
def checkboxChecked(self, fieldName):
|
||||
def checkboxChecked(self, fieldName, dbValue):
|
||||
'''When displaying a checkbox, must it be checked or not?'''
|
||||
rq = self.REQUEST
|
||||
# Get the value we must compare (from request or from database)
|
||||
|
@ -764,11 +764,11 @@ class AbstractMixin:
|
|||
compValue = rq.get(fieldName)
|
||||
compValue = compValue in ('True', 1, '1')
|
||||
else:
|
||||
compValue = self.getAppyType(fieldName).getValue(self)
|
||||
compValue = dbValue
|
||||
# Compare the value
|
||||
return compValue
|
||||
|
||||
def dateValueSelected(self, fieldName, fieldPart, dateValue):
|
||||
def dateValueSelected(self, fieldName, fieldPart, dateValue, dbValue):
|
||||
'''When displaying a date field, must the particular p_dateValue be
|
||||
selected in the field corresponding to the date part?'''
|
||||
# Get the value we must compare (from request or from database)
|
||||
|
@ -779,7 +779,7 @@ class AbstractMixin:
|
|||
if compValue.isdigit():
|
||||
compValue = int(compValue)
|
||||
else:
|
||||
compValue = self.getAppyType(fieldName).getValue(self)
|
||||
compValue = dbValue
|
||||
if compValue:
|
||||
compValue = getattr(compValue, fieldPart)()
|
||||
# Compare the value
|
||||
|
|
|
@ -455,7 +455,7 @@
|
|||
</tr>
|
||||
<tr tal:repeat="change event/changes/items" valign="top">
|
||||
<td tal:content="python: tool.translate(change[1][1])"></td>
|
||||
<td tal:define="appyValue python: contextObj.getFormattedValue(change[0], useParamValue=True, value=change[1][0]);
|
||||
<td tal:define="appyValue python: contextObj.getFieldValue(change[0], useParamValue=True, value=change[1][0]);
|
||||
appyType python:contextObj.getAppyType(change[0], asDict=True);
|
||||
severalValues python: (appyType['multiplicity'][1] > 1) or (appyType['multiplicity'][1] == None)">
|
||||
<span tal:condition="not: severalValues" tal:replace="appyValue"></span>
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
<table cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<a tal:condition="python: len(flavours)==1"
|
||||
<a tal:condition="python: len(flavours)==1 and rootClasses"
|
||||
tal:attributes="href python:'%s?type_name=%s&flavourNumber=1' % (queryUrl, ','.join(rootClasses))"
|
||||
tal:content="python: tool.translate(appName)"></a>
|
||||
<span tal:condition="python: len(flavours)>1"
|
||||
<span tal:condition="python: len(flavours)>1 or not rootClasses"
|
||||
tal:replace="python: tool.translate(appName)"/>
|
||||
</td>
|
||||
<td align="right">
|
||||
|
@ -159,7 +159,7 @@
|
|||
<tr>
|
||||
<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()) and (len(phase['pages']) == 1)"
|
||||
tal:attributes="class python: 'appyPhase step' + phase['phaseStatus']">
|
||||
tal:attributes="class python: (len(phases) > 1) and ('appyPhase step%s' % phase['phaseStatus']) or 'appyPhase'">
|
||||
<span class="portletGroup" tal:condition="python: len(phases) > 1">
|
||||
<a tal:attributes="href python: '%s?page=%s' % (contextObj.getUrl(), phase['pages'][0]);"
|
||||
tal:condition="displayLink"
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<input type="checkbox"
|
||||
tal:attributes="name python: name + '_visible';
|
||||
id name;
|
||||
checked python:contextObj.checkboxChecked(name);
|
||||
checked python:contextObj.checkboxChecked(name, rawValue);
|
||||
onClick python:'toggleCheckbox(\'%s\', \'%s_hidden\');;updateSlaves(getMasterValue(this), \'%s\')' % (name, name, widget['id']);
|
||||
class python: 'noborder ' + widget['master_css']"/>
|
||||
<input tal:attributes="name name;
|
||||
id string:${name}_hidden;
|
||||
value python: test(contextObj.checkboxChecked(name), 'True', 'False')"
|
||||
value python: test(contextObj.checkboxChecked(name, rawValue), 'True', 'False')"
|
||||
type="hidden" />
|
||||
</metal:edit>
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<tal:days repeat="day days">
|
||||
<option tal:define="zDay python: str(day).zfill(2)"
|
||||
tal:attributes="value zDay;
|
||||
selected python:contextObj.dateValueSelected(name, 'day', day)"
|
||||
selected python:contextObj.dateValueSelected(name, 'day', day, rawValue)"
|
||||
tal:content="zDay"></option>
|
||||
</tal:days>
|
||||
</select>
|
||||
|
@ -28,7 +28,7 @@
|
|||
<tal:months repeat="month months">
|
||||
<option tal:define="zMonth python: str(month).zfill(2)"
|
||||
tal:attributes="value zMonth;
|
||||
selected python:contextObj.dateValueSelected(name, 'month', month)"
|
||||
selected python:contextObj.dateValueSelected(name, 'month', month, rawValue)"
|
||||
tal:content="zMonth"></option>
|
||||
</tal:months>
|
||||
</select>
|
||||
|
@ -39,7 +39,7 @@
|
|||
<option value="">-</option>
|
||||
<option tal:repeat="year years"
|
||||
tal:attributes="value year;
|
||||
selected python:contextObj.dateValueSelected(name, 'year', year)"
|
||||
selected python:contextObj.dateValueSelected(name, 'year', year, rawValue)"
|
||||
tal:content="year"></option>
|
||||
</select>
|
||||
<tal:comment replace="nothing">The icon for displaying the date chooser</tal:comment>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<tal:hours repeat="hour hours">
|
||||
<option tal:define="zHour python: str(hour).zfill(2)"
|
||||
tal:attributes="value zHour;
|
||||
selected python:contextObj.dateValueSelected(name, 'hour', hour)"
|
||||
selected python:contextObj.dateValueSelected(name, 'hour', hour, rawValue)"
|
||||
tal:content="zHour"></option>
|
||||
</tal:hours>
|
||||
</select> :
|
||||
|
@ -64,7 +64,7 @@
|
|||
<tal:minutes repeat="minute minutes">
|
||||
<option tal:define="zMinute python: str(minute).zfill(2)"
|
||||
tal:attributes="value zMinute;
|
||||
selected python:contextObj.dateValueSelected(name, 'minute', minute)"
|
||||
selected python:contextObj.dateValueSelected(name, 'minute', minute, rawValue)"
|
||||
tal:content="zMinute"></option>
|
||||
</tal:minutes>
|
||||
</select>
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
tal:define="contextMacro python: portal.skyn.widgets;
|
||||
layout python: widget['layouts'][layoutType];
|
||||
name widget/name;
|
||||
value python: contextObj.getFormattedValue(name);
|
||||
value python: contextObj.getFieldValue(name);
|
||||
rawValue python: contextObj.getFieldValue(name, formatted=False);
|
||||
requestValue python: request.get(name, None);
|
||||
inRequest python: request.has_key(name);
|
||||
errors errors | python: ();
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
maxMult python: widget['multiplicity'][1];
|
||||
severalValues python: (maxMult == None) or (maxMult > 1)">
|
||||
<span tal:condition="python: fmt in (0, 3)"
|
||||
tal:attributes="class widget/master_css;
|
||||
id python: contextObj.getFormattedValue(name, forMasterId=True)">
|
||||
tal:attributes="class widget/master_css; id rawValue">
|
||||
<ul class="appyList" tal:condition="python: value and severalValues">
|
||||
<li class="appyBullet" tal:repeat="sv value"><i tal:content="structure sv"></i></li>
|
||||
</ul>
|
||||
|
@ -29,15 +28,17 @@
|
|||
isOneLine python: fmt in (0,3)">
|
||||
|
||||
<tal:choice condition="isSelect">
|
||||
<select tal:define="possibleValues python:contextObj.getPossibleValues(name, withTranslations=True, withBlankValue=True)"
|
||||
<select tal:define="possibleValues python:contextObj.getPossibleValues(name, withTranslations=True, withBlankValue=True);
|
||||
multiValued python: (widget['multiplicity'][1] != 1) and True or False"
|
||||
tal:attributes="name name;
|
||||
id name;
|
||||
multiple python: test(widget['multiplicity'][1] != 1, 'multiple', '');
|
||||
onchange python: test(isMaster, 'javascript:updateSlaves(getMasterValue(this), \'%s\')' % widget['id'], '');
|
||||
class widget/master_css">
|
||||
multiple python: multiValued and 'multiple' or '';
|
||||
onchange python: isMaster and ('javascript:updateSlaves(getMasterValue(this), \'%s\')' % widget['id']) or '';
|
||||
class widget/master_css;
|
||||
size python: multiValued and widget['height'] or 1">
|
||||
<option tal:repeat="possibleValue possibleValues"
|
||||
tal:attributes="value python: possibleValue[0];
|
||||
selected python:contextObj.fieldValueSelected(name, possibleValue[0])"
|
||||
selected python:contextObj.fieldValueSelected(name, possibleValue[0], rawValue)"
|
||||
tal:content="python:tool.truncateValue(possibleValue[1], widget)"></option>
|
||||
</select>
|
||||
</tal:choice>
|
||||
|
@ -83,7 +84,7 @@
|
|||
validator defines a list of values, with a "AND/OR" checkbox.</tal:comment>
|
||||
<tal:selectSearch condition="widget/isSelect">
|
||||
<tal:comment replace="nothing">The "and" / "or" radio buttons</tal:comment>
|
||||
<tal:operator define="operName python: 'o_%s' % fieldName;
|
||||
<tal:operator define="operName python: 'o_%s' % name;
|
||||
orName python: '%s_or' % operName;
|
||||
andName python: '%s_and' % operName;"
|
||||
condition="python: widget['multiplicity'][1]!=1">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div metal:define-macro="portlet"
|
||||
tal:define="tool python: context.<!toolInstanceName!>;
|
||||
flavour python: tool.getFlavour(tool);"
|
||||
tal:condition="tool/showPortlet">
|
||||
tal:condition="python: tool.showPortlet(context)">
|
||||
<metal:block metal:use-macro="here/global_defines/macros/defines" />
|
||||
<metal:prologue use-macro="here/skyn/page/macros/prologue"/>
|
||||
<dl tal:define="rootClasses tool/getRootClasses;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
/* <dtml-with base_properties> (do not remove this :) */
|
||||
/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
|
||||
|
||||
textarea { width: 99%; }
|
||||
|
||||
#portal-breadcrumbs { display: none; }
|
||||
#importedElem { color: grey; font-style: italic; }
|
||||
label { font-weight: bold; font-style: italic; }
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
|
||||
metal:use-macro="here/main_template/macros/master" i18n:domain="<!applicationName!>">
|
||||
|
||||
<!-- Disable standard Plone green tabs -->
|
||||
<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>
|
||||
|
||||
<metal:disable fill-slot="top_slot"
|
||||
tal:define="dummy python:request.set('disable_border',1)" />
|
||||
<body>
|
||||
<div metal:fill-slot="main">
|
||||
<span tal:replace="structure python: context.<!toolInstanceName!>.translateWithMapping('front_page_text')"/>
|
||||
<div metal:fill-slot="main" tal:define="tool python: context.<!toolInstanceName!>">
|
||||
<!pageContent!>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" i18n:domain="plone">
|
||||
<body>
|
||||
<tal:message metal:define-macro="portal_message"></tal:message>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue