[gen] Ref field has now global actions like 'unlink many', 'link many' and 'delete many'.

This commit is contained in:
Gaetan Delannay 2014-04-04 16:49:22 +02:00
parent e7c20f8d2b
commit 3621d0da92
12 changed files with 151 additions and 43 deletions

View file

@ -82,10 +82,10 @@ class Phase:
def addPageLinks(self, field, obj):
'''If p_field is a navigable Ref, we must add, within self.pagesInfo,
objects linked to p_obj through this ReF as links.'''
objects linked to p_obj through this Ref as links.'''
if field.page.name in self.hiddenPages: return
infos = []
for ztied in field.getValue(obj, type='zobjects'):
for ztied in field.getValue(obj, appy=False):
infos.append(Object(title=ztied.title, url=ztied.absolute_url()))
self.pagesInfo[field.page.name].links = infos

View file

@ -41,7 +41,7 @@ class Ref(Field):
<x var="includeShownInfo=includeShownInfo|False;
navInfo='ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
field.pageName, loop.tied.nb + 1 + startNumber, totalNumber);
navInfo=not field.isBack and navInfo or '';
navInfo=(not field.isBack and not inPickList) and navInfo or '';
cssClass=tied.o.getCssFor('title')">
<x>::tied.o.getSupTitle(navInfo)</x>
<a var="pageName=field.isBack and field.back.pageName or 'main';
@ -56,16 +56,29 @@ class Ref(Field):
# objects (delete many, unlink many,...)
pxGlobalActions = Px('''
<!-- Insert several objects (if in pick list) -->
<input if="inPickList" type="button" class="button"
<input if="inPickList" var2="action='link'" type="button" class="button"
value=":_('object_link_many')"
onClick=":'onLinkMany(%s)' % q(ajaxHookId)"
onclick=":'onLinkMany(%s,%s)' % (q(action), q(ajaxHookId))"
style=":url('linkMany', bg=True)"/>
<!-- Unlink several objects -->
<input if="not isBack and field.unlink and canWrite and not inPickList"
var2="imgName=linkList and 'unlinkManyUp' or 'unlinkMany';
action='unlink'"
type="button" class="button" value=":_('object_unlink_many')"
onclick=":'onLinkMany(%s,%s)' % (q(action), q(ajaxHookId))"
style=":url(imgName, bg=True)"/>
<!-- Delete several objects -->
<input if="not isBack and field.delete and canWrite"
var2="action='delete'"
type="button" class="button" value=":_('object_delete_many')"
onclick=":'onLinkMany(%s,%s)' % (q(action), q(ajaxHookId))"
style=":url('deleteMany', bg=True)"/>
''')
# This PX displays icons for triggering actions on a given referenced object
# (edit, delete, etc).
pxObjectActions = Px('''
<table class="noStyle" var="isBack=field.isBack">
<table class="noStyle">
<tr>
<!-- Arrows for moving objects up or down -->
<td if="not isBack and (len(objects)&gt;1) and changeOrder and canWrite \
@ -247,6 +260,7 @@ class Ref(Field):
<x var="innerRef=False;
ajaxHookId=ajaxHookId|'%s_%s_poss' % (zobj.id, field.name);
inPickList=True;
isBack=field.isBack;
startNumber=field.getStartNumber('list', req, ajaxHookId);
info=field.getPossibleValues(zobj, startNumber=startNumber, \
someObjects=True, removeLinked=True);
@ -263,7 +277,7 @@ class Ref(Field):
(q(ajaxHookId), q(zobj.absolute_url()), \
q(field.name), q(innerRef));
changeOrder=False;
checkboxes=checkboxes|field.checkboxesEnabled(zobj);
checkboxes=field.checkboxesEnabled(zobj) and (totalNumber &gt; 1);
showSubTitles=showSubTitles|\
req.get('showSubTitles', 'true') == 'true';
subLabel='selectable_objects'">:field.pxViewList</x>''')
@ -310,6 +324,7 @@ class Ref(Field):
linkList=field.link == 'list';
renderAll=req.get('scope') != 'objs';
inPickList=False;
isBack=field.isBack;
startNumber=field.getStartNumber(render, req, ajaxHookId);
info=field.getValue(zobj,startNumber=startNumber,someObjects=True);
objects=info.objects;
@ -327,16 +342,17 @@ class Ref(Field):
(q(ajaxHookId), q(zobj.absolute_url()), \
q(field.name), q(innerRef));
changeOrder=field.changeOrderEnabled(zobj);
checkboxes=field.checkboxesEnabled(zobj);
checkboxesEnabled=field.checkboxesEnabled(zobj);
checkboxes=checkboxesEnabled and (totalNumber &gt; 1);
showSubTitles=req.get('showSubTitles', 'true') == 'true'">
<!-- The definition of "atMostOneRef" above may sound strange: we
shouldn't check the actual number of referenced objects. But for
back references people often forget to specify multiplicities. So
concretely, multiplicities (0,None) are coded as (0,1). -->
<!-- JS tables storing checkbox statuses if checkboxes are enabled -->
<script if="checkboxes and renderAll"
<script if="checkboxesEnabled and renderAll"
type="text/javascript">:field.getCbJsInit(zobj)</script>
<div if="linkList and renderAll"
<div if="linkList and renderAll and canWrite"
var2="ajaxHookId='%s_%s_poss' % (zobj.id, field.name)"
id=":ajaxHookId">:field.pxViewPickList</div>
<x if="render == 'list'"
@ -759,7 +775,6 @@ class Ref(Field):
through this Ref field.'''
# Security check
if not noSecurity: obj.allows(self.writePermission, raiseError=True)
# p_value can be a list of objects
if type(value) in sutils.sequenceTypes:
for v in value: self.linkObject(obj, v, back=back)
@ -964,30 +979,43 @@ class Ref(Field):
def onUiRequest(self, obj, rq):
'''This method is called when an action tied to this Ref field is
triggered from the user interface (link, unlink, link_many,
unlink_many...).'''
unlink_many, delete_many).'''
action = rq['linkAction']
tool = obj.getTool()
if action == 'link':
if not action.endswith('_many'):
# "link" or "unlink"
tied = tool.getObject(rq['targetUid'])
self.linkObject(obj, tied, noSecurity=False)
elif action == 'unlink':
tied = tool.getObject(rq['targetUid'])
self.unlinkObject(obj, tied, noSecurity=False)
elif action == 'link_many':
exec 'self.%sObject(obj, tied, noSecurity=False)' % action
else:
# "link_many", "unlink_many", "delete_many"
uids = rq['targetUid'].strip(',') or ();
if uids: uids = uids.split(',')
unchecked = rq['semantics'] == 'unchecked'
# Browse possible values
for tied in self.getPossibleValues(obj, removeLinked=True):
if action == 'link_many':
# Get possible values (objects)
values = self.getPossibleValues(obj, removeLinked=True)
isObj = True
else:
# Get current values (uids)
values = list(getattr(obj.aq_base, self.name, ()))
isObj = False
mustDelete = action == 'delete_many'
for value in values:
uid = not isObj and value or value.uid
if unchecked:
# Keep only tied objects not among uids.
if tied.uid in uids: continue
# Keep only objects not among uids.
if uid in uids: continue
else:
# Keep only tied objects being in uids.
if tied.uid not in uids: continue
self.linkObject(obj, tied.o, noSecurity=False)
elif action == 'unlink_many':
pass
# Keep only objects being in uids.
if uid not in uids: continue
# (Un-)link or delete this object.
tied = not isObj and tool.getObject(value) or value.o
if mustDelete:
if tied.mayDelete(): tied.delete()
else:
# Link or unlink
exec 'self.%sObject(obj, tied, noSecurity=False)' % \
action.split('_')[0]
urlBack = obj.getUrl(rq['HTTP_REFERER'])
obj.say(obj.translate('action_done'))
tool.goto(urlBack)

View file

@ -191,15 +191,23 @@ msgstr ""
msgid "object_delete"
msgstr ""
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr ""
#. Default: "Remove"
msgid "object_unlink"
msgstr ""
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr ""
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr ""

View file

@ -191,15 +191,23 @@ msgstr "تعديل"
msgid "object_delete"
msgstr ""
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr ""
#. Default: "Remove"
msgid "object_unlink"
msgstr ""
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr ""
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr ""

View file

@ -191,15 +191,23 @@ msgstr "Bearbeiten"
msgid "object_delete"
msgstr "Löschen"
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr ""
#. Default: "Remove"
msgid "object_unlink"
msgstr ""
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr ""
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr ""

View file

@ -192,17 +192,25 @@ msgstr "Edit"
msgid "object_delete"
msgstr "Delete"
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr "Delete selection"
#. Default: "Remove"
msgid "object_unlink"
msgstr "Unlink"
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr "Insert"
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr "Insert selected elements"
msgstr "Insert selection"
#. Default: "(Un)check everything"
msgid "check_uncheck"

View file

@ -191,15 +191,23 @@ msgstr "Editar"
msgid "object_delete"
msgstr "Eliminar"
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr ""
#. Default: "Remove"
msgid "object_unlink"
msgstr ""
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr ""
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr ""

View file

@ -192,15 +192,23 @@ msgstr "Modifier"
msgid "object_delete"
msgstr "Supprimer"
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr "Supprimer la sélection"
#. Default: "Remove"
msgid "object_unlink"
msgstr "Retirer"
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr "Retirer la sélection"
#. Default: "Insert"
msgid "object_link"
msgstr "Insérer"
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr "Insérer la sélection"

View file

@ -191,15 +191,23 @@ msgstr "Modifica"
msgid "object_delete"
msgstr "Elimina"
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr ""
#. Default: "Remove"
msgid "object_unlink"
msgstr ""
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr ""
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr ""

View file

@ -191,15 +191,23 @@ msgstr "Bewerken"
msgid "object_delete"
msgstr "Verwijderen"
#. Default: "Delete selection"
msgid "object_delete_many"
msgstr ""
#. Default: "Remove"
msgid "object_unlink"
msgstr ""
#. Default: "Remove selection"
msgid "object_unlink_many"
msgstr ""
#. Default: "Insert"
msgid "object_link"
msgstr ""
#. Default: "Insert selected elements"
#. Default: "Insert selection"
msgid "object_link_many"
msgstr ""

View file

@ -262,10 +262,26 @@ function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
else hidden.value = 'False';
}
// JS implementation of Python ''.rsplit.
function _rsplit(s, delimiter, limit) {
var elems = s.split(delimiter);
var exc = elems.length - limit;
if (exc <= 0) return elems;
// Merge back first elements to get p_limit elements.
var head = '';
var res = [];
for (var i=0; i < elems.length; i++) {
if (exc > 0) { head += elems[i] + delimiter; exc -= 1 }
else { if (exc == 0) { res.push(head + elems[i]); exc -= 1 }
else res.push(elems[i]) }
}
return res;
}
// (Un)checks a checkbox corresponding to a linked object.
function toggleRefCb(checkbox) {
var name = checkbox.getAttribute('name');
var elems = name.split('_');
var elems = _rsplit(name, '_', 3);
// Get the DOM node corresponding to the Ref field.
var node = document.getElementById(elems[0] + '_' + elems[1]);
// Get the array that stores checkbox statuses.
@ -285,7 +301,7 @@ function toggleRefCb(checkbox) {
// Initialise checkboxes of a Ref field.
function initRefCbs(id) {
var elems = id.split('_');
var elems = _rsplit(id, '_', 3);
// Get the DOM node corresponding to the Ref field.
var node = document.getElementById(elems[0] + '_' + elems[1]);
// Get the array that stores checkbox statuses.
@ -303,7 +319,7 @@ function initRefCbs(id) {
// Toggle all checkboxes of a Ref field.
function toggleAllRefCbs(id) {
var elems = id.split('_');
var elems = _rsplit(id, '_', 3);
// Get the DOM node corresponding to the Ref field.
var node = document.getElementById(elems[0] + '_' + elems[1]);
// Empty the array that stores checkbox statuses.
@ -523,8 +539,8 @@ function onLink(action, sourceUid, fieldName, targetUid) {
f.submit();
}
function onLinkMany(id) {
var elems = id.split('_');
function onLinkMany(action, id) {
var elems = _rsplit(id, '_', 3);
// Get the DOM node corresponding to the Ref field.
var node = document.getElementById(elems[0] + '_' + elems[1]);
// Get the uids of (un-)checked objects.
@ -535,7 +551,7 @@ function onLinkMany(id) {
var semantics = node['_appy_' + elems[2] + '_sem'];
// Fill the form and ask for a confirmation
f = document.getElementById('linkForm');
f.linkAction.value = 'link_many';
f.linkAction.value = action + '_many';
f.sourceUid.value = elems[0];
f.fieldName.value = elems[1];
f.targetUid.value = uids;

View file

@ -823,7 +823,7 @@ class XmlMarshaller:
v = field.getValue(instance)
elif field.type == 'Ref':
fieldType = 'ref'
v = field.getValue(instance, type='zobjects')
v = field.getValue(instance, appy=False)
else:
v = field.getValue(instance)
self.dumpField(res, field.name, v, fieldType=fieldType)