[PATCH 1 of 3 saem_ref v3] Make ConceptSchemes and Concepts adaptable to IJQTree

Frank Bessou frank.bessou at logilab.fr
Fri Sep 28 16:33:04 CEST 2018


# HG changeset patch
# User Frank Bessou <frank.bessou at logilab.fr>
# Date 1538037542 -7200
#      Thu Sep 27 10:39:02 2018 +0200
# Node ID 72e97e0e43537623076c7d8c6b24a98a68f7724c
# Parent  cb6995e6a650a6e408511fb08228390597f8319f
# Available At http://hg.logilab.org/review/cubes/saem_ref
#              hg pull http://hg.logilab.org/review/cubes/saem_ref -r 72e97e0e4353
Make ConceptSchemes and Concepts adaptable to IJQTree

We implement needed adapters so that a ConceptScheme can be rendered as
a JQTree: IJQTreeAdapter and ITreeBaseAdapter.

Since Concept is already adaptable to IContained we make it adaptable
to ITreeBase by extending the IContainedToITreeBase adapter.

We have to provide js callback to JQTree adapters which tells if it is
possible the move the Concept to a given node. Since a Concept can
always be moved we make this callback return always true.

We use a currently unrelease version of cubicweb-seda to avoid having a
"seda profile tree" contextual component displayed on the concept scheme
page.

diff --git a/cubicweb_saem_ref/data/cubes.saem_ref.js b/cubicweb_saem_ref/data/cubes.saem_ref.js
--- a/cubicweb_saem_ref/data/cubes.saem_ref.js
+++ b/cubicweb_saem_ref/data/cubes.saem_ref.js
@@ -156,6 +156,10 @@ saem = {
             $('#' + refresh_view + eid).loadxhtml(
                 AJAX_BASE_URL, ajaxFuncArgs('view', {eid: eid, vid: refresh_view}));
         });
+    },
+
+    canMoveTo : function(moved_node, target_node, position){
+        return true;
     }
 
 };
diff --git a/cubicweb_saem_ref/views/skos.py b/cubicweb_saem_ref/views/skos.py
--- a/cubicweb_saem_ref/views/skos.py
+++ b/cubicweb_saem_ref/views/skos.py
@@ -19,9 +19,13 @@
 from cubicweb import tags, _
 from cubicweb.view import AnyRsetView
 from cubicweb.predicates import is_instance
+from cubicweb.uilib import js
+from cubicweb.view import EntityAdapter
 from cubicweb.web import formwidgets as fw
 from cubicweb.web.views import baseviews, treeview, uicfg
 
+from cubicweb_seda.entities.itree import IContainedToITreeBase
+import cubicweb_seda.views.jqtree as jqtree
 from cubicweb_skos import views as skos
 
 from . import ImportEntityComponent
@@ -114,6 +118,60 @@ class ConceptPopoverView(AnyRsetView):
         self.w(tags.a(title, href='javascript:$.noop();', id=str(entity.eid), **data))
 
 
+class ConceptSchemeJQTreeAdapter(jqtree.IJQTreeAdapter):
+    __select__ = jqtree.IJQTreeAdapter.__select__ & is_instance('ConceptScheme')
+    js_can_move_to = js.saem.canMoveTo
+
+    def maybe_parent_of(self):
+        return ['Concept']
+
+    def maybe_moved(self):
+        return False
+
+
+class ConceptJQTreeAdapter(jqtree.IJQTreeAdapter):
+    __select__ = jqtree.IJQTreeAdapter.__select__ & is_instance('Concept')
+    js_can_move_to = js.saem.canMoveTo
+
+    def maybe_parent_of(self):
+        return ['Concept']
+
+    def maybe_moved(self):
+        return True
+
+    def reparent(self, peid, index):
+        parent = self._cw.entity_from_eid(peid)
+        if parent == self.entity.in_scheme[0]:
+            self.entity.cw_set(broader_concept=None)
+            return
+        self.entity.cw_set(broader_concept=[parent])
+
+
+class ConceptSchemeITreeBaseAdapter(EntityAdapter):
+    __regid__ = 'ITreeBase'
+    __select__ = is_instance('ConceptScheme')
+
+    def iterparents(self):
+        return iter([])
+
+    def iterchildren(self):
+        for concept in self.entity.reverse_in_scheme:
+            # Do not treat children of other concepts as children of this concept scheme
+            if not concept.broader_concept:
+                yield concept
+
+    def is_leaf(self):
+        """Returns True if the entity does not have any children."""
+        return not self.entity.reverse_in_scheme
+
+
+class ConceptITreeBaseAdapter(IContainedToITreeBase):
+    __regid__ = 'ITreeBase'
+    __select__ = is_instance('Concept')
+
+    _children_relations = [('broader_concept', 'object')]
+
+
 def registration_callback(vreg):
     vreg.register_all(globals().values(), __name__)
     from cubicweb_skos.views import ImportConceptSchemeAction
diff --git a/dev-requirements.txt b/dev-requirements.txt
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -2,3 +2,5 @@ mock
 psycopg2
 pytest
 webtest
+http://hg.logilab.org/master/cubes/seda/archive/default.tar.bz2#egg=cubicweb-seda
+
diff --git a/test/unittest_entities_skos.py b/test/unittest_entities_skos.py
--- a/test/unittest_entities_skos.py
+++ b/test/unittest_entities_skos.py
@@ -56,6 +56,35 @@ class ConceptSchemeTC(CubicWebTC):
             self.assertEqual(set(c1label.cw_attr_cache), set(['kind', 'label', 'language_code']))
 
 
+class ConceptSchemeITreeBaseAdapterTC(CubicWebTC):
+
+    configcls = PostgresApptestConfiguration
+
+    def test_iter_children_does_not_list_nested_concepts(self):
+        with self.admin_access.cnx() as cnx:
+            scheme = cnx.create_entity('ConceptScheme', ark_naa=testutils.naa(cnx))
+            c1 = scheme.add_concept(u'child1')
+            c2 = scheme.add_concept(u'child2')
+            c3 = c2.add_concept(u'child2child')
+            cnx.commit()
+            children = scheme.cw_adapt_to('ITreeBase').iterchildren()
+            self.assertIn(c1, children)
+            self.assertIn(c2, children)
+            self.assertNotIn(c3, children)
+
+    def test_is_leaf_when_contains_no_concepts(self):
+        with self.admin_access.cnx() as cnx:
+            scheme = cnx.create_entity('ConceptScheme', ark_naa=testutils.naa(cnx))
+            cnx.commit()
+            self.assertTrue(scheme.cw_adapt_to('ITreeBase').is_leaf())
+
+            scheme.add_concept(u'child')
+            cnx.commit()
+
+            scheme.clear_all_caches()
+            self.assertFalse(scheme.cw_adapt_to('ITreeBase').is_leaf())
+
+
 if __name__ == '__main__':
     import unittest
     unittest.main()



More information about the saem-devel mailing list