appy.gen: removed fields Tool.showWorkflowCommentFieldForxx (workflow comment may not be entered into the confirm popup); appy.gen: security-related bugfixes.
This commit is contained in:
parent
cbb8d5cd12
commit
f6a828bc13
|
@ -564,11 +564,6 @@ class ToolClassDescriptor(ClassDescriptor):
|
|||
fieldType = gen.Boolean(default=defaultValue, page='userInterface',
|
||||
group=groupName)
|
||||
self.addField(fieldName, fieldType)
|
||||
# Adds the boolean field for showing or not the field "enter comments".
|
||||
fieldName = 'showWorkflowCommentFieldFor%s' % className
|
||||
fieldType = gen.Boolean(default=defaultValue, page='userInterface',
|
||||
group=groupName)
|
||||
self.addField(fieldName, fieldType)
|
||||
# Adds the boolean field for showing all states in current state or not.
|
||||
# If this boolean is True but the current phase counts only one state,
|
||||
# we will not show the state at all: the fact of knowing in what phase
|
||||
|
|
|
@ -417,6 +417,8 @@ class ZopeInstaller:
|
|||
self.configureSessions()
|
||||
self.installBaseObjects()
|
||||
self.installCatalog()
|
||||
# The following line cleans and rebuilds the catalog entirely.
|
||||
#self.app.config.appy().refreshCatalog()
|
||||
self.installTool()
|
||||
self.installUi()
|
||||
# Perform migrations if required
|
||||
|
|
|
@ -896,7 +896,11 @@ class BaseMixin:
|
|||
self.log('Wrong workflow info for a "%s"; is not in state "%s".' % \
|
||||
(self.meta_type, stateName))
|
||||
# Update permission attributes on the object if required
|
||||
return state.updatePermissions(wf, self)
|
||||
updated = state.updatePermissions(wf, self)
|
||||
if updated:
|
||||
# Reindex the object because security-related info is indexed.
|
||||
self.reindex()
|
||||
return updated
|
||||
|
||||
def hasHistory(self):
|
||||
'''Has this object an history?'''
|
||||
|
|
|
@ -188,7 +188,7 @@ class Translation(ModelClass):
|
|||
toolFieldPrefixes = ('defaultValue', 'podTemplate', 'formats', 'resultColumns',
|
||||
'enableAdvancedSearch', 'numberOfSearchColumns',
|
||||
'searchFields', 'optionalFields', 'showWorkflow',
|
||||
'showWorkflowCommentField', 'showAllStatesInPhase')
|
||||
'showAllStatesInPhase')
|
||||
defaultToolFields = ('title', 'users', 'groups', 'translations',
|
||||
'enableNotifications', 'unoEnabledPython','openOfficePort',
|
||||
'numberOfResultsPerPage', 'listBoxesMaximumWidth',
|
||||
|
|
|
@ -38,9 +38,6 @@ class PoMessage:
|
|||
MSG_searchFields = "Search fields"
|
||||
MSG_optionalFields = 'Optional fields'
|
||||
MSG_showWorkflow = 'Show workflow-related information'
|
||||
MSG_showWorkflowCommentField = 'Show field allowing to enter a ' \
|
||||
'comment every time a transition is ' \
|
||||
'triggered'
|
||||
MSG_showAllStatesInPhase = 'Show all states in phase'
|
||||
POD_ASKACTION = 'Trigger related action'
|
||||
REF_NO = 'No object.'
|
||||
|
|
|
@ -9,6 +9,7 @@ table { font-size: 100%; border-spacing: 0px; border-collapse:collapse;}
|
|||
form { margin: 0; padding: 0;}
|
||||
p { margin: 0;}
|
||||
acronym {cursor: help;}
|
||||
input { font: 92% Helvetica,Arial,sans-serif }
|
||||
input[type=image] { border: 0; background: none; }
|
||||
input[type=checkbox] { border: 0; background: none; cursor: pointer;}
|
||||
input[type=radio] { border: 0; background: none; cursor: pointer;}
|
||||
|
@ -44,6 +45,8 @@ img {border: 0}
|
|||
border-top: 1px solid #5F7983; border-bottom: 1px solid #5F7983; }
|
||||
.login { margin-top: 2px; margin-bottom: 2px; color: white;}
|
||||
.buttons { margin-left: 4px;}
|
||||
.fakeButton { border: 1px solid #D7DEE4; background-color: #fde8e0;
|
||||
padding: 0px 8px 2px; font: italic 92% Helvetica,Arial,sans-serif}
|
||||
.message { color: #fd9c03; position: absolute; top: -55px; left: 100px;
|
||||
width: 700px; border: 1px black dashed; padding: 2px 6px;
|
||||
background-color: #f4f5f6}
|
||||
|
|
|
@ -307,7 +307,7 @@ function triggerTransition(transitionId, msg) {
|
|||
theForm.submit();
|
||||
}
|
||||
else { // Ask the user to confirm.
|
||||
askConfirm('form', 'triggerTransitionForm', msg);
|
||||
askConfirm('form', 'triggerTransitionForm', msg, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,13 +409,17 @@ function closePopup(popupId) {
|
|||
}
|
||||
|
||||
// Function triggered when an action needs to be confirmed by the user
|
||||
function askConfirm(actionType, action, msg) {
|
||||
function askConfirm(actionType, action, msg, showComment) {
|
||||
/* Store the actionType (send a form, call an URL or call a script) and the
|
||||
related action, and shows the confirm popup. If the user confirms, we
|
||||
will perform the action. */
|
||||
will perform the action. If p_showComment is true, an input field allowing
|
||||
to enter a comment will be shown in the popup. */
|
||||
var confirmForm = document.getElementById('confirmActionForm');
|
||||
confirmForm.actionType.value = actionType;
|
||||
confirmForm.action.value = action;
|
||||
var commentArea = document.getElementById('commentArea');
|
||||
if (showComment) commentArea.style.display = "block";
|
||||
else commentArea.style.display = "none";
|
||||
openPopup("confirmActionPopup", msg);
|
||||
}
|
||||
|
||||
|
@ -427,8 +431,14 @@ function doConfirm() {
|
|||
var actionType = confirmForm.actionType.value;
|
||||
var action = confirmForm.action.value;
|
||||
if (actionType == 'form') {
|
||||
// We must submit the form whose id is in "action"
|
||||
document.getElementById(action).submit();
|
||||
/* Submit the form whose id is in "action", and transmmit him the comment
|
||||
from the popup when relevant */
|
||||
var theForm = document.getElementById(action);
|
||||
if ((confirmForm.comment.style.display != 'none') &&
|
||||
(confirmForm.comment.value)) {
|
||||
theForm.comment.value = confirmForm.comment.value;
|
||||
}
|
||||
theForm.submit();
|
||||
}
|
||||
else if (actionType == 'url') {
|
||||
// We must go to the URL defined in "action"
|
||||
|
|
|
@ -88,8 +88,9 @@
|
|||
<td tal:define="actorid python:event.get('actor');" tal:content="actorid"/>
|
||||
<td tal:content="event/time"/>
|
||||
<td tal:condition="not: isDataChange">
|
||||
<tal:comment condition="rhComments" tal:content="structure rhComments"/>
|
||||
<span tal:condition="not: rhComments">No comment.</span>
|
||||
<tal:c condition="rhComments"
|
||||
content="structure python: contextObj.formatText(rhComments)"/>
|
||||
<span tal:condition="not: rhComments">-</span>
|
||||
</td>
|
||||
<td tal:condition="isDataChange">
|
||||
<tal:comment replace="nothing">
|
||||
|
@ -152,21 +153,16 @@
|
|||
<input type="hidden" name="workflow_action"/>
|
||||
<table>
|
||||
<tr valign="middle">
|
||||
<tal:comment replace="nothing">Input field allowing to enter a comment before triggering a transition</tal:comment>
|
||||
<td tal:define="showCommentsField python:tool.getAttr('showWorkflowCommentFieldFor'+contextObj.meta_type)"
|
||||
align="right" tal:condition="showCommentsField">
|
||||
<span tal:content="python: tool.translate('workflow_comment')" class="discreet"></span>
|
||||
<input type="text" id="comment" name="comment" size="30"/>
|
||||
</td>
|
||||
|
||||
<tal:comment replace="nothing">Input field for storing comment</tal:comment>
|
||||
<textarea id="comment" name="comment" cols="30" rows="3" style="display:none"></textarea>
|
||||
<tal:comment replace="nothing">Buttons for triggering transitions</tal:comment>
|
||||
<td align="right" tal:repeat="transition transitions">
|
||||
<tal:comment replace="nothing">Real button</tal:comment>
|
||||
<input type="button" class="appyButton" tal:condition="transition/may_trigger"
|
||||
<input type="button" tal:condition="transition/may_trigger"
|
||||
tal:attributes="value transition/title;
|
||||
onClick python: 'triggerTransition(\'%s\',\'%s\')' % (transition['name'],transition['confirm']);"/>
|
||||
<tal:comment replace="nothing">Fake button, explaining why the transition can't be triggered</tal:comment>
|
||||
<div class="appyButton fakeButton" tal:condition="not: transition/may_trigger">
|
||||
<div class="fakeButton" tal:condition="not: transition/may_trigger">
|
||||
<acronym tal:content="transition/title"
|
||||
tal:attributes="title transition/reason"></acronym>
|
||||
</div>
|
||||
|
|
|
@ -74,6 +74,12 @@
|
|||
<p id="appyConfirmText"></p>
|
||||
<input type="hidden" name="actionType"/>
|
||||
<input type="hidden" name="action"/>
|
||||
<div id="commentArea" align="left"><br/>
|
||||
<span tal:content="python: tool.translate('workflow_comment')" class="discreet"></span>
|
||||
<textarea name="comment" cols="30" rows="3"></textarea>
|
||||
<br/>
|
||||
</div>
|
||||
<br/>
|
||||
<input type="button" onClick="doConfirm()"
|
||||
tal:attributes="value python:_('yes')"/>
|
||||
<input type="button" value="No" onClick="closePopup('confirmActionPopup')"
|
||||
|
|
|
@ -95,10 +95,6 @@ class ToolWrapper(AbstractWrapper):
|
|||
Stores the boolean field indicating if we must show workflow-
|
||||
related information for p_klass or not.
|
||||
|
||||
"showWorkflowCommentField"
|
||||
Stores the boolean field indicating if we must show the field
|
||||
allowing to enter a comment every time a transition is triggered.
|
||||
|
||||
"showAllStatesInPhase"
|
||||
Stores the boolean field indicating if we must show all states
|
||||
linked to the current phase or not. If this field is False, we
|
||||
|
@ -133,4 +129,29 @@ class ToolWrapper(AbstractWrapper):
|
|||
expression="ctx['nb'] += int(obj.o.refreshSecurity())")
|
||||
msg = 'Security refresh: %d object(s) updated.' % context['nb']
|
||||
self.log(msg)
|
||||
|
||||
def refreshCatalog(self, startObject=None):
|
||||
'''Reindex all Appy objects. For some unknown reason, method
|
||||
catalog.refreshCatalog is not able to recatalog Appy objects.'''
|
||||
if not startObject:
|
||||
# This is a global refresh. Clear the catallog completely, and then
|
||||
# reindex all Appy-managed objects, ie those in folders "config"
|
||||
# and "data".
|
||||
# First, clear the catalog.
|
||||
app = self.o.getParentNode()
|
||||
app.catalog._catalog.clear()
|
||||
app.config.reindex()
|
||||
nb = 1
|
||||
for obj in app.config.objectValues():
|
||||
nb += self.refreshCatalog(startObject=obj)
|
||||
# Then, refresh objects in the "data" folder.
|
||||
for obj in app.data.objectValues():
|
||||
nb += self.refreshCatalog(startObject=obj)
|
||||
print '%d object(s) were reindexed.' % nb
|
||||
else:
|
||||
startObject.reindex()
|
||||
nb = 1
|
||||
for obj in startObject.objectValues():
|
||||
nb += self.refreshCatalog(startObject=obj)
|
||||
return nb
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -129,6 +129,7 @@ class ZopeUserPatches:
|
|||
'''Returns the global roles that this user (or any of its groups)
|
||||
possesses.'''
|
||||
res = list(self.roles)
|
||||
if 'Anonymous' not in res: res.append('Authenticated')
|
||||
# Add group global roles
|
||||
if not hasattr(aq_base(self), 'groups'): return res
|
||||
for roles in self.groups.itervalues():
|
||||
|
|
|
@ -375,10 +375,10 @@ class Cortexer:
|
|||
|
||||
Once the "cortex.admin" folder and its content has been generated, in
|
||||
order to push the app definition into Cortex, go in the folder where
|
||||
"cortex.admin" lies and type (command-line tool "cortex-client" must
|
||||
"cortex.admin" lies and type (command-line tool "cortex" must
|
||||
be installed):
|
||||
|
||||
cortex-client sync push --api http://<cortex-host-ip>/api
|
||||
cortex sync push --api http://<cortex-host-ip>/api
|
||||
'''
|
||||
def __init__(self, app, pythonVersions=('2.6',)):
|
||||
self.appName = os.path.basename(app)
|
||||
|
|
Loading…
Reference in a new issue