Allowed to express layouts in a more concise manner and various graphical improvements.
This commit is contained in:
parent
eb52c1bb7d
commit
0b4f6e1f79
13 changed files with 187 additions and 96 deletions
|
@ -652,6 +652,7 @@ class Generator(AbstractGenerator):
|
|||
Flavour._appy_addImportRelatedFields(classDescr)
|
||||
Flavour._appy_addWorkflowFields(self.flavour)
|
||||
Flavour._appy_addWorkflowFields(self.podTemplate)
|
||||
Flavour._appy_addWorkflowFields(self.user)
|
||||
# Complete self.flavour.orderedAttributes from the attributes that we
|
||||
# just added to the Flavour model class.
|
||||
for fieldName in Flavour._appy_attributes:
|
||||
|
|
|
@ -139,7 +139,15 @@ class PloneInstaller:
|
|||
site.invokeFactory(self.appyFolderType, self.productName,
|
||||
title=self.productName)
|
||||
getattr(site.portal_types, self.appyFolderType).global_allow = 0
|
||||
appFolder = getattr(site, self.productName)
|
||||
# Manager has been granted Add permissions for all root classes.
|
||||
# This may not be desired, so remove this.
|
||||
appFolder = getattr(site, self.productName)
|
||||
for className in self.config.rootClasses:
|
||||
permission = self.getAddPermission(className)
|
||||
print 'Permission is', permission
|
||||
appFolder.manage_permission(permission, (), acquire=0)
|
||||
else:
|
||||
appFolder = getattr(site, self.productName)
|
||||
# All roles defined as creators should be able to create the
|
||||
# corresponding root content types in this folder.
|
||||
i = -1
|
||||
|
|
|
@ -46,6 +46,7 @@ class AbstractMixin:
|
|||
appyType.store(obj, value)
|
||||
if created:
|
||||
# Now we have a title for the object, so we derive a nice id
|
||||
obj.unmarkCreationFlag()
|
||||
obj._renameAfterCreation(check_auto_id=True)
|
||||
if previousData:
|
||||
# Keep in history potential changes on historized fields
|
||||
|
@ -181,31 +182,45 @@ class AbstractMixin:
|
|||
obj.plone_utils.addPortalMessage(msg)
|
||||
return self.goto('%s/skyn/view' % obj.absolute_url(), True)
|
||||
if rq.get('buttonPrevious.x', None):
|
||||
# Go to the previous page (edit mode) for this object.
|
||||
# Go to the previous page for this object.
|
||||
# We recompute the list of phases and pages because things
|
||||
# may have changed since the object has been updated (ie,
|
||||
# additional pages may be shown or hidden now, so the next and
|
||||
# previous pages may have changed).
|
||||
# previous pages may have changed). Moreover, previous and next
|
||||
# pages may not be available in "edit" mode, so we return the edit
|
||||
# or view pages depending on page.show.
|
||||
currentPage = rq.get('page')
|
||||
phaseInfo = self.getAppyPhases(page=currentPage)
|
||||
previousPage = self.getPreviousPage(phaseInfo, currentPage)
|
||||
previousPage, show = self.getPreviousPage(phaseInfo, currentPage)
|
||||
if previousPage:
|
||||
rq.set('page', previousPage)
|
||||
return obj.skyn.edit(obj)
|
||||
# Return the edit or view page?
|
||||
if show != 'view':
|
||||
rq.set('page', previousPage)
|
||||
return obj.skyn.edit(obj)
|
||||
else:
|
||||
urlBack = '%s/skyn/view?page=%s' % (obj.absolute_url(),
|
||||
previousPage)
|
||||
return self.goto(urlBack)
|
||||
else:
|
||||
obj.plone_utils.addPortalMessage(msg)
|
||||
return self.goto('%s/skyn/view' % obj.absolute_url(), True)
|
||||
return self.goto('%s/skyn/view' % obj.absolute_url())
|
||||
if rq.get('buttonNext.x', None):
|
||||
# Go to the next page (edit mode) for this object
|
||||
# Go to the next page for this object
|
||||
currentPage = rq.get('page')
|
||||
phaseInfo = self.getAppyPhases(page=currentPage)
|
||||
nextPage = self.getNextPage(phaseInfo, currentPage)
|
||||
nextPage, show = self.getNextPage(phaseInfo, currentPage)
|
||||
if nextPage:
|
||||
rq.set('page', nextPage)
|
||||
return obj.skyn.edit(obj)
|
||||
# Return the edit or view page?
|
||||
if show != 'view':
|
||||
rq.set('page', nextPage)
|
||||
return obj.skyn.edit(obj)
|
||||
else:
|
||||
urlBack = '%s/skyn/view?page=%s' % (obj.absolute_url(),
|
||||
nextPage)
|
||||
return self.goto(urlBack)
|
||||
else:
|
||||
obj.plone_utils.addPortalMessage(msg)
|
||||
return self.goto('%s/skyn/view' % obj.absolute_url(), True)
|
||||
return self.goto('%s/skyn/view' % obj.absolute_url())
|
||||
return obj.skyn.edit(obj)
|
||||
|
||||
def onDelete(self):
|
||||
|
@ -575,28 +590,36 @@ class AbstractMixin:
|
|||
pageIndex = phase['pages'].index(page)
|
||||
if pageIndex > 0:
|
||||
# We stay on the same phase, previous page
|
||||
return phase['pages'][pageIndex-1]
|
||||
res = phase['pages'][pageIndex-1]
|
||||
show = phase['pageShows'][res]
|
||||
return res, show
|
||||
else:
|
||||
if phase['previousPhase']:
|
||||
# We go to the last page of previous phase
|
||||
previousPhase = phase['previousPhase']
|
||||
return previousPhase['pages'][-1]
|
||||
res = previousPhase['pages'][-1]
|
||||
show = previousPhase['pageShows'][res]
|
||||
return res, show
|
||||
else:
|
||||
return None
|
||||
return None, None
|
||||
|
||||
def getNextPage(self, phase, page):
|
||||
'''Returns the page that follows p_page which is in p_phase.'''
|
||||
pageIndex = phase['pages'].index(page)
|
||||
if pageIndex < len(phase['pages'])-1:
|
||||
# We stay on the same phase, next page
|
||||
return phase['pages'][pageIndex+1]
|
||||
res = phase['pages'][pageIndex+1]
|
||||
show = phase['pageShows'][res]
|
||||
return res, show
|
||||
else:
|
||||
if phase['nextPhase']:
|
||||
# We go to the first page of next phase
|
||||
nextPhase = phase['nextPhase']
|
||||
return nextPhase['pages'][0]
|
||||
res = nextPhase['pages'][0]
|
||||
show = nextPhase['pageShows'][res]
|
||||
return res, show
|
||||
else:
|
||||
return None
|
||||
return None, None
|
||||
|
||||
def changeRefOrder(self, fieldName, objectUid, newIndex, isDelta):
|
||||
'''This method changes the position of object with uid p_objectUid in
|
||||
|
@ -873,12 +896,6 @@ class AbstractMixin:
|
|||
res = [o.appy() for o in objs]
|
||||
return res
|
||||
|
||||
def _appy_showPage(self, page, pageShow):
|
||||
'''Must I show p_page?'''
|
||||
if callable(pageShow):
|
||||
return pageShow(self.appy())
|
||||
else: return pageShow
|
||||
|
||||
def _appy_showState(self, workflow, stateShow):
|
||||
'''Must I show a state whose "show value" is p_stateShow?'''
|
||||
if callable(stateShow):
|
||||
|
|
|
@ -78,7 +78,7 @@ class User(ModelClass):
|
|||
firstName = String(**gm)
|
||||
def showLogin(self): pass
|
||||
def validateLogin(self): pass
|
||||
login = String(show=showLogin, validator=validateLogin, **gm)
|
||||
login = String(show=showLogin, validator=validateLogin, indexed=True, **gm)
|
||||
def showPassword(self): pass
|
||||
def validatePassword(self): pass
|
||||
password1 = String(format=String.PASSWORD, show=showPassword,
|
||||
|
@ -142,7 +142,7 @@ class Flavour(ModelClass):
|
|||
res.group = copy.copy(appyType.group)
|
||||
res.phase = 'main'
|
||||
# Set default layouts for all Flavour fields
|
||||
res.layouts = None
|
||||
res.layouts = res.formatLayouts(None)
|
||||
res.specificReadPermission = False
|
||||
res.specificWritePermission = False
|
||||
res.multiplicity = (0, appyType.multiplicity[1])
|
||||
|
|
|
@ -651,8 +651,8 @@
|
|||
This macro shows the range of buttons (next, previous, save,...).
|
||||
</tal:comment>
|
||||
<div metal:define-macro="buttons"
|
||||
tal:define="previousPage python: contextObj.getPreviousPage(phaseInfo, page);
|
||||
nextPage python: contextObj.getNextPage(phaseInfo, page);
|
||||
tal:define="previousPage python: contextObj.getPreviousPage(phaseInfo, page)[0];
|
||||
nextPage python: contextObj.getNextPage(phaseInfo, page)[0];
|
||||
isEdit python: layoutType == 'edit';">
|
||||
<br/>
|
||||
<tal:previousButton condition="previousPage">
|
||||
|
@ -682,7 +682,7 @@
|
|||
tal:attributes="src string:$portal_url/skyn/cancel.png"/>
|
||||
</tal:cancelButton>
|
||||
|
||||
<tal:editLink condition="not:isEdit">
|
||||
<tal:editLink condition="python: not isEdit and (phaseInfo['pageShows'][page] != 'view')">
|
||||
<img tal:define="nav request/nav|nothing;
|
||||
nav python: test(nav, '&nav=%s' % nav, '')"
|
||||
title="Edit" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
|
||||
|
|
|
@ -153,19 +153,20 @@
|
|||
<table tal:define="phases contextObj/getAppyPhases|nothing;
|
||||
page python: request.get('page', 'main')"
|
||||
tal:condition="python: phases and not ((len(phases)==1) and len(phases[0]['pages'])==1)"
|
||||
cellspacing="1" cellpadding="0" width="100%">
|
||||
cellspacing="1" cellpadding="2" width="100%">
|
||||
<tal:phase repeat="phase phases">
|
||||
<tal:comment replace="nothing">The box containing phase-related information</tal:comment>
|
||||
<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: (len(phases) > 1) and ('appyPhase step%s' % phase['phaseStatus']) or 'appyPhase'">
|
||||
<span class="portletGroup" tal:condition="python: len(phases) > 1">
|
||||
<div class="portletGroup" tal:condition="python: len(phases) > 1">
|
||||
<a tal:attributes="href python: '%s?page=%s' % (contextObj.getUrl(), phase['pages'][0]);"
|
||||
tal:condition="displayLink"
|
||||
tal:content="python: tool.translate(label)"></a>
|
||||
<span tal:condition="not: displayLink" tal:replace="python: tool.translate(label)"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="portletMenu">
|
||||
<table width="100%" cellpadding="0" cellspacing="0"
|
||||
tal:condition="python: len(phase['pages']) > 1">
|
||||
<tr tal:repeat="aPage phase/pages" valign="top">
|
||||
|
@ -184,6 +185,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tal:comment replace="nothing">The down arrow pointing to the next phase (if any)</tal:comment>
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
<tal:comment replace="nothing">First row: the tabs.</tal:comment>
|
||||
<tr valign="middle"><td style="border-bottom: 1px solid #ff8040">
|
||||
<table cellpadding="0" cellspacing="0" style="position:relative; bottom:-1px;">
|
||||
<tr valign="bottom">
|
||||
<tr valign="middle">
|
||||
<tal:tab repeat="widgetRow widget/widgets">
|
||||
<tal:id define="tabId python:'tab_%s_%d_%d' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))">
|
||||
<td><img tal:attributes="src string: $portal_url/skyn/tabLeft.png;
|
||||
|
@ -134,12 +134,13 @@
|
|||
This macro displays the content of a group of widgets.
|
||||
It is exclusively called by macro "group" above.
|
||||
</tal:comment>
|
||||
<table metal:define-macro="groupContent" align="center"
|
||||
tal:attributes="width python: test(widget['wide'], '100%', '')">
|
||||
<table metal:define-macro="groupContent"
|
||||
tal:attributes="width python: test(widget['wide'], '100%', '');
|
||||
align widget/align">
|
||||
<tal:comment replace="nothing">Display the title of the group if it is not rendered a fieldset.</tal:comment>
|
||||
<tr tal:condition="python: (widget['style'] != 'fieldset') and widget['hasLabel']">
|
||||
<td tal:attributes="colspan python: len(widget['columnsWidths']);
|
||||
class widget/style">
|
||||
class widget/style" align="left">
|
||||
<span tal:replace="structure python: contextObj.translate(widget['labelId'])"/>
|
||||
<tal:help condition="widget/hasHelp">
|
||||
<metal:call use-macro="portal/skyn/widgets/show/macros/help"/>
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
border-left: 1px solid #8cacbb;
|
||||
border-right: 1px solid #8cacbb;
|
||||
}
|
||||
.portletGroup {
|
||||
font-size: 85%;
|
||||
padding-left: 0.7em;
|
||||
}
|
||||
|
||||
/* Stylesheet with Internet Explorer-specific workarounds. */
|
||||
* html #portal-columns {
|
||||
|
|
|
@ -6,7 +6,7 @@ textarea { width: 99%; }
|
|||
|
||||
#portal-breadcrumbs { display: none; }
|
||||
#importedElem { color: grey; font-style: italic; }
|
||||
label { font-weight: bold; font-style: italic; }
|
||||
label { font-weight: bold; font-style: italic; line-height: 1.4em;}
|
||||
.discreet { font-size: 94%; }
|
||||
.appyList { line-height: 1.1em; margin: 0 0 0.5em 1.2em; padding: 0; }
|
||||
.appyBullet { margin: 0; }
|
||||
|
@ -26,7 +26,7 @@ label { font-weight: bold; font-style: italic; }
|
|||
.appyPhase {
|
||||
border-style: dashed;
|
||||
border-width: thin;
|
||||
padding: 0 0.1em 0 1em;
|
||||
padding: 0 0.6em 0 1em;
|
||||
}
|
||||
|
||||
.appyState {
|
||||
|
@ -68,14 +68,14 @@ label { font-weight: bold; font-style: italic; }
|
|||
background-color: #cde2a7;
|
||||
background-image: url(&dtml-portal_url;/skyn/done.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: -1px 4px;
|
||||
background-position: -1px 7px;
|
||||
}
|
||||
|
||||
.stepCurrent {
|
||||
background-color: #eef3f5;
|
||||
background-image: url(&dtml-portal_url;/skyn/current.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: -1px 4px;
|
||||
background-position: -1px 7px;
|
||||
}
|
||||
|
||||
.stepFuture {
|
||||
|
@ -224,11 +224,13 @@ th {
|
|||
font-variant: small-caps;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
margin: 0.3em 0 0.3em 0;
|
||||
}
|
||||
.portletSep { border-top: 1px dashed #8cacbb; }
|
||||
.portletGroupItem { padding-left: 0.8em; font-style: italic; }
|
||||
.portletPageItem { font-style: italic; }
|
||||
.portletCurrent { font-weight: bold; }
|
||||
.portletMenu { margin-bottom: 0.4em; }
|
||||
|
||||
div.appyGrey {
|
||||
display: none;
|
||||
|
|
|
@ -63,6 +63,9 @@ class UserWrapper(AbstractWrapper):
|
|||
# Perform updates on the corresponding Plone user
|
||||
ploneUser = self.o.portal_membership.getMemberById(self.login)
|
||||
ploneUser.setMemberProperties({'fullname': self.title})
|
||||
# This object must be owned by its Plone user
|
||||
if 'Owner' not in self.o.get_local_roles_for_userid(self.login):
|
||||
self.o.manage_addLocalRoles(self.login, ('Owner',))
|
||||
# Change group membership according to self.roles. Indeed, instead of
|
||||
# granting roles directly to the user, we will add the user to a
|
||||
# Appy-created group having this role.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue