[views] Update jqtree code, copied back from cubicweb-saem_ref
authorDenis Laxalde <denis.laxalde@logilab.fr>
Fri, 14 Oct 2016 13:03:06 +0200
changeset 1923 c3f377955898
parent 1909 f060b5932206
child 1924 891700ba269e
[views] Update jqtree code, copied back from cubicweb-saem_ref Just keep ITreeBase instead of ITree and added a compatibility method `iterparents` to IContainedToITreeBase adapter to minimize changes in views/jqtree.py. Motions in tree are not handled yet. Related to #15047080.
data/cubes.jqtree.css
data/cubes.jqtree.js
entities/itree.py
views/jqtree.py
views/sedatree.py
--- a/data/cubes.jqtree.css	Wed Oct 19 15:51:07 2016 +0200
+++ b/data/cubes.jqtree.css	Fri Oct 14 13:03:06 2016 +0200
@@ -1,3 +1,14 @@
-.selected {
-  font-weight: bold;
+/* add span/a to override default rules */
+
+ul.jqtree-tree span.jqtree-title {
+  margin-left: 0;
 }
+
+ul.jqtree-tree i.glyphicon {
+  font-size: 80%;
+  color: #777;
+}
+
+ul.jqtree-tree a.jqtree-toggler.jqtree-toggler-left {
+  margin-right: 0.1em;
+}
\ No newline at end of file
--- a/data/cubes.jqtree.js	Wed Oct 19 15:51:07 2016 +0200
+++ b/data/cubes.jqtree.js	Fri Oct 14 13:03:06 2016 +0200
@@ -1,4 +1,4 @@
-// copyright 2015-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+// copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 // contact http://www.logilab.fr -- mailto:contact@logilab.fr
 //
 // This program is free software: you can redistribute it and/or modify it under
@@ -14,17 +14,29 @@
 // You should have received a copy of the GNU Lesser General Public License along
 // with this program. If not, see <http://www.gnu.org/licenses/>.
 
-cw_jqtree = {
-    sedaTree: function(domid, msg) {
+
+jqtree = {
+    jqTree: function(domid, dragAndDrop) {
         var $tree = cw.jqNode(domid);
         // tree display and basic controls.
         $tree.tree({
-            dragAndDrop: false,
+            dragAndDrop: dragAndDrop,
             autoOpen: 0,  // only open level-0
             selectable: false,
             autoEscape: false,
             closedIcon: $('<i class="glyphicon glyphicon-expand"></i>'),
             openedIcon: $('<i class="glyphicon glyphicon-collapse-down"></i>'),
+            onCanMove: function(node) {
+                return node.maybeChild;
+            },
+            onCanMoveTo: function(moved_node, target_node, position) {
+                if ( target_node.id === undefined ) {
+                    return false;
+                }
+                else {
+                    return target_node.maybeParentOf.indexOf(moved_node.type) !== -1;
+                }
+            },
             onCreateLi: function(node, $li) {
                 var selectedId = $tree.tree('getTree').children[0].selected;
                 if ( selectedId !== null && node.id === selectedId ) {
@@ -47,5 +59,15 @@
                 }
             }
         );
+        $tree.bind(
+            'tree.move',
+            function(event) {
+                event.preventDefault();
+                // do the move first, and then POST back.
+                event.move_info.do_move();
+                asyncRemoteExec('jqtree_reparent', event.move_info.moved_node.id,
+                                event.move_info.target_node.id);
+            }
+        );
     }
 };
--- a/entities/itree.py	Wed Oct 19 15:51:07 2016 +0200
+++ b/entities/itree.py	Fri Oct 14 13:03:06 2016 +0200
@@ -69,6 +69,8 @@
                 curr = curr.cw_adapt_to('ITreeBase')
         return _uptoroot(self)
 
+    iterparents = iterancestors  # Compat. with CubicWeb's ITree.
+
 
 class ITreeBaseArchiveUnitAdapter(IContainedToITreeBase):
     """Adapt ArchiveUnit entities to ITreeBase."""
--- a/views/jqtree.py	Wed Oct 19 15:51:07 2016 +0200
+++ b/views/jqtree.py	Fri Oct 14 13:03:06 2016 +0200
@@ -19,19 +19,52 @@
 from functools import wraps
 
 from cubicweb import tags, uilib
-from cubicweb.view import EntityView, View
+from cubicweb.view import EntityAdapter, EntityView, View
 from cubicweb.predicates import adaptable, match_form_params
-from cubicweb.web.views import json
+from cubicweb.web.views import ajaxcontroller, json
+
+
+@ajaxcontroller.ajaxfunc(output_type='json')
+def jqtree_reparent(self, child_eid, parent_eid):
+    child = self._cw.entity_from_eid(child_eid)
+    adapted = child.cw_adapt_to('IJQTree')
+    if adapted is not None:
+        return adapted.reparent(parent_eid)
 
 
-def json_entity(entity, on_demand=False):
-    """Return the minimal JSON dict of an entity."""
-    label = entity.view('jqtree.label')
-    data = {'label': label,
-            'id': entity.eid}
-    if on_demand:
-        data['load_on_demand'] = True
-    return data
+class IJQTreeAdapter(EntityAdapter):
+    """Adapt an entity into a JQTree node."""
+    __abstract__ = True
+    __regid__ = 'IJQTree'
+
+    def maybe_parent_of(self):
+        """Return a list of entity type which `entity` may be parent of."""
+        return []
+
+    def maybe_child(self):
+        """Return True if entity may be child of another (i.e. may be
+        reparented).
+        """
+        return False
+
+    def reparent(self, peid):
+        """Set entity as child of entity with `peid`."""
+        raise NotImplementedError
+
+    def json(self, on_demand=False):
+        """Return a JSON dict of an entity."""
+        entity = self.entity
+        label = entity.view('jqtree.label')
+        data = {
+            'label': label,
+            'id': entity.eid,
+            'type': entity.cw_etype,
+            'maybeChild': self.maybe_child(),
+            'maybeParentOf': self.maybe_parent_of(),
+        }
+        if on_demand:
+            data['load_on_demand'] = True
+        return data
 
 
 def itree_adaptable(func):
@@ -56,7 +89,9 @@
     for child in entity.cw_adapt_to('ITreeBase').iterchildren():
         ctree = child.cw_adapt_to('ITreeBase')
         on_demand = ctree and not ctree.is_leaf()
-        yield json_entity(child, on_demand=on_demand)
+        ichild = child.cw_adapt_to('IJQTree')
+        if ichild is not None:
+            yield ichild.json(on_demand=on_demand)
 
 
 @itree_adaptable
@@ -69,9 +104,12 @@
     # initialize data for "previous" parent when walking up the tree.
     previous, previous_children = None, []
     data = None
-    for parent in entity.cw_adapt_to('ITreeBase').iterancestors():
+    for parent in entity.cw_adapt_to('ITreeBase').iterparents():
         # parent has to be strictly evaluated
-        data = json_entity(parent, on_demand=False)
+        iparent = parent.cw_adapt_to('IJQTree')
+        if iparent is None:
+            continue
+        data = iparent.json(on_demand=False)
         data['children'] = []
         # fetch JSON for children of this parent, setting the previous
         # parent we're coming from as strict (load_on_demand=False).
@@ -101,7 +139,10 @@
         if not data:
             # if empty, just return the current entity JSON tree (with
             # children) as the entity is probably the root.
-            data = json_entity(entity, on_demand=False)
+            adapted = entity.cw_adapt_to('IJQTree')
+            if adapted is None:
+                return
+            data = adapted.json(on_demand=False)
             children = list(json_entity_children(entity))
             if children:
                 data['children'] = children
@@ -141,9 +182,12 @@
     __select__ = adaptable('ITreeBase')
 
     def entity_call(self, entity, **kwargs):
+        # TODO move jqTree js to its own file.
         self._cw.add_js(('cubes.jqtree.js', 'tree.jquery.js'))
-        self._cw.add_css(('cubes.jqtree.css', 'jqtree.css'))
+        self._cw.add_css(('jqtree.css'))
         divid = 'jqtree' + str(entity.eid)
         data_url = entity.absolute_url(vid='jqtree.json')
         self.w(tags.div(id=divid, **{'data-url': data_url}))
-        self._cw.add_onload(uilib.js.cw_jqtree.sedaTree(divid))
+        mayupdate = entity.e_schema.has_perm(
+            self._cw, 'update', eid=entity.eid)
+        self._cw.add_onload(uilib.js.jqtree.jqTree(divid, mayupdate))
--- a/views/sedatree.py	Wed Oct 19 15:51:07 2016 +0200
+++ b/views/sedatree.py	Fri Oct 14 13:03:06 2016 +0200
@@ -29,4 +29,5 @@
     title = _('SEDA profile tree')
 
     def render_body(self, w):
+        self._cw.add_css('cubes.jqtree.css')
         self.entity.view('jqtree.treeview', w=w)