[gen] Improved performance of the Ref field and added an icon for dissociating referred objects.

This commit is contained in:
Gaetan Delannay 2012-10-08 10:08:54 +02:00
parent 872b77208b
commit 9954edf71a
9 changed files with 71 additions and 19 deletions

View file

@ -1757,11 +1757,11 @@ class Ref(Type):
def __init__(self, klass=None, attribute=None, validator=None,
multiplicity=(0,1), index=None, default=None, optional=False,
editDefault=False, add=False, addConfirm=False, noForm=False,
link=True, unlink=False, back=None, show=True, page='main',
group=None, layouts=None, showHeaders=False, shownInfo=(),
select=None, maxPerPage=30, move=0, indexed=False,
searchable=False, specificReadPermission=False,
editDefault=False, add=False, addConfirm=False, delete=None,
noForm=False, link=True, unlink=None, back=None, show=True,
page='main', group=None, layouts=None, showHeaders=False,
shownInfo=(), select=None, maxPerPage=30, move=0,
indexed=False, searchable=False, specificReadPermission=False,
specificWritePermission=False, width=None, height=5,
maxChars=None, colspan=1, master=None, masterValue=None,
focus=False, historized=False, mapping=None, label=None,
@ -1773,6 +1773,12 @@ class Ref(Type):
self.add = add
# When the user adds a new object, must a confirmation popup be shown?
self.addConfirm = addConfirm
# May the user delete objects via this Ref?
self.delete = delete
if delete == None:
# By default, one may delete objects via a Ref for which one can
# add objects.
self.delete = bool(self.add)
# If noForm is True, when clicking to create an object through this ref,
# the object will be created automatically, and no creation form will
# be presented to the user.
@ -1781,6 +1787,10 @@ class Ref(Type):
self.link = link
# May the user unlink existing objects?
self.unlink = unlink
if unlink == None:
# By default, one may unlink objects via a Ref for which one can
# link objects.
self.unlink = bool(self.link)
self.back = None
if back:
# It is a forward reference

View file

@ -448,8 +448,11 @@ class ZopeGenerator(Generator):
msg('no_elem_selected', '', msg.NO_SELECTION),
msg('object_edit', '', msg.EDIT),
msg('object_delete', '', msg.DELETE),
msg('object_unlink', '', msg.UNLINK),
msg('delete_confirm', '', msg.DELETE_CONFIRM),
msg('unlink_confirm', '', msg.UNLINK_CONFIRM),
msg('delete_done', '', msg.DELETE_DONE),
msg('unlink_done', '', msg.UNLINK_DONE),
msg('goto_first', '', msg.GOTO_FIRST),
msg('goto_previous', '', msg.GOTO_PREVIOUS),
msg('goto_next', '', msg.GOTO_NEXT),

View file

@ -16,7 +16,7 @@ except ImportError:
_noroles = []
# Errors -----------------------------------------------------------------------
jsMessages = ('no_elem_selected', 'delete_confirm')
jsMessages = ('no_elem_selected', 'delete_confirm', 'unlink_confirm')
# ------------------------------------------------------------------------------
class ToolMixin(BaseMixin):

View file

@ -106,6 +106,7 @@ class BaseMixin:
self.getParentNode().manage_delObjects([self.id])
def onDelete(self):
'''Called when an object deletion is triggered from the ui.'''
rq = self.REQUEST
self.delete()
if self.getUrl(rq['HTTP_REFERER'],mode='raw') ==self.getUrl(mode='raw'):
@ -117,6 +118,18 @@ class BaseMixin:
self.say(self.translate('delete_done'))
self.goto(urlBack)
def onUnlink(self):
'''Called when an object unlinking is triggered from the ui.'''
rq = self.REQUEST
tool = self.getTool()
sourceObject = tool.getObject(rq['sourceUid'])
targetObject = tool.getObject(rq['targetUid'])
field = sourceObject.getAppyType(rq['fieldName'])
field.unlinkObject(sourceObject, targetObject)
urlBack = self.getUrl(rq['HTTP_REFERER'])
self.say(self.translate('unlink_done'))
self.goto(urlBack)
def onCreate(self):
'''This method is called when a user wants to create a root object in
the "data" folder or an object through a reference field. A temporary
@ -1006,7 +1019,7 @@ class BaseMixin:
return True
def mayDelete(self):
'''May the currently logged user delete this object?.'''
'''May the currently logged user delete this object?'''
res = self.allows('Delete objects')
if not res: return
# An additional, user-defined condition, may refine the base permission.
@ -1014,9 +1027,10 @@ class BaseMixin:
if hasattr(appyObj, 'mayDelete'): return appyObj.mayDelete()
return True
def mayEdit(self):
'''May the currently logged user edit this object?.'''
res = self.allows('Modify portal content')
def mayEdit(self, permission='Modify portal content'):
'''May the currently logged user edit this object? p_perm can be a
field-specific permission.'''
res = self.allows(permission)
if not res: return
# An additional, user-defined condition, may refine the base permission.
appyObj = self.appy()

View file

@ -94,8 +94,11 @@ class PoMessage:
NO_SELECTION = 'You must select at least one element.'
EDIT = 'Edit'
DELETE = 'Delete'
UNLINK = 'Unlink'
DELETE_CONFIRM = 'Are you sure you want to delete this element?'
UNLINK_CONFIRM = 'Are you sure you want to unlink this element?'
DELETE_DONE = 'The element has been deleted.'
UNLINK_DONE = 'The element has been unlinked.'
GOTO_FIRST = 'Go to top'
GOTO_PREVIOUS = 'Go to previous'
GOTO_NEXT = 'Go to next'

View file

@ -318,6 +318,14 @@ function onDeleteObject(objectUid) {
askConfirm('form', 'deleteForm', delete_confirm);
}
function onUnlinkObject(sourceUid, fieldName, targetUid) {
f = document.getElementById('unlinkForm');
f.sourceUid.value = sourceUid;
f.fieldName.value = fieldName;
f.targetUid.value = targetUid;
askConfirm('form', 'unlinkForm', unlink_confirm);
}
function createCookie(name, value, days) {
if (days) {
var date = new Date();

View file

@ -18,6 +18,13 @@
<input type="hidden" name="action" value="Delete"/>
<input type="hidden" name="objectUid"/>
</form>
<tal:comment replace="nothing">Global form for unlinking an object</tal:comment>
<form id="unlinkForm" method="post" action="do">
<input type="hidden" name="action" value="Unlink"/>
<input type="hidden" name="sourceUid"/>
<input type="hidden" name="fieldName"/>
<input type="hidden" name="targetUid"/>
</form>
<tal:comment replace="nothing">Global form for generating a document from a pod template</tal:comment>
<form name="podTemplateForm" method="post"
tal:attributes="action python: tool.absolute_url() + '/generateDocument'">

BIN
gen/ui/unlink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View file

@ -19,10 +19,11 @@
<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="noStyle">
<table class="noStyle"
tal:define="isBack appyType/isBack">
<tr>
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
<td tal:condition="python: not appyType['isBack'] and (len(objs)&gt;1) and changeOrder and context.allows('Modify portal content')">
<td tal:condition="python: not isBack and (len(objs)&gt;1) and changeOrder and canWrite">
<tal:moveRef define="objectIndex python: contextObj.getAppyRefIndex(fieldName, obj);
ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'ChangeRefOrder\', {\'refObjectUid\':\'%s\', \'move\':\'**v**\'}' % (startNumber, obj.UID()))">
<tal:comment replace="nothing">Move up</tal:comment>
@ -39,22 +40,28 @@
style="cursor:pointer"/>
</tal:moveRef>
</td>
<tal:comment replace="nothing">Edit the element</tal:comment>
<td tal:condition="python: not appyType['noForm'] and obj.mayEdit()">
<tal:comment replace="nothing">Edit</tal:comment>
<td tal:condition="python: not appyType['noForm'] and obj.mayEdit() and appyType['delete']">
<a tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);"
tal:attributes="href python: obj.getUrl(mode='edit', page='main', nav=navInfo)">
<img tal:attributes="src string: $appUrl/ui/edit.gif;
title python: _('object_edit')"/>
</a>
</td>
<tal:comment replace="nothing">Delete the element</tal:comment>
<td>
<tal:comment replace="nothing">Delete</tal:comment>
<td tal:condition="python: not isBack and appyType['delete'] and canWrite and obj.mayDelete()">
<img style="cursor:pointer"
tal:condition="python: not appyType['isBack'] and obj.mayDelete()"
tal:attributes="src string: $appUrl/ui/delete.png;
onClick python:'onDeleteObject(\'%s\')' % obj.UID();
title python: _('object_delete')"/>
</td>
<tal:comment replace="nothing">Unlink</tal:comment>
<td tal:condition="python: not isBack and appyType['unlink'] and canWrite">
<img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/unlink.png;
onClick python:'onUnlinkObject(\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), appyType['name'], obj.UID());
title python: _('object_unlink')"/>
</td>
</tr>
</table>
</metal:objectActions>