Fix references related view in typed reference context
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 06 Jan 2017 14:20:19 +0100
changeset 2257 2d824356706d
parent 2227 ac4a8c9b5e95
child 2258 9ee61b23011c
Fix references related view in typed reference context Those objects may be used as 'main reference' (ie. archive unit 'ref' to another archive unit or to a data object) or as 'typed reference' (ie. IsVersionOf, IsPartOf, etc) accessible from archive unit's content. Only the former case was handled, this fix the situation for the latter in various places. Related to #16688070.
views/archiveunit.py
views/dataobject.py
views/viewlib.py
--- a/views/archiveunit.py	Fri Jan 06 12:02:49 2017 +0100
+++ b/views/archiveunit.py	Fri Jan 06 14:20:19 2017 +0100
@@ -134,27 +134,6 @@
         parent_archive_unit(entity).view('incontext', w=self.w)
 
 
-class ArchiveUnitRefIdOutOfContextView(baseviews.OutOfContextView):
-    """Custom outofcontext view for proper display of SEDAArchiveUnitRefId from in boxes"""
-    __select__ = is_instance('SEDAArchiveUnitRefId')
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
-        parent = entity.cw_adapt_to('IContained').parent
-        parent.view('incontext', w=self.w)
-
-
-class DataObjectReferenceBusinessValueLinkEntityView(viewlib.BusinessValueLinkEntityView):
-    __select__ = is_instance('SEDADataObjectReference')
-
-    def entity_call(self, entity):
-        do_rset = entity.related('seda_data_object_reference_id', 'subject')
-        if do_rset:
-            do_rset.one().view(self.__regid__, w=self.w)
-        else:
-            super(DataObjectReferenceBusinessValueLinkEntityView, self).entity_call(entity)
-
-
 class ArchiveUnitTabbedPrimaryView(tabs.TabbedPrimaryView):
     __select__ = is_instance('SEDAArchiveUnit')
 
--- a/views/dataobject.py	Fri Jan 06 12:02:49 2017 +0100
+++ b/views/dataobject.py	Fri Jan 06 14:20:19 2017 +0100
@@ -1,4 +1,4 @@
-# copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2016-2017 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
@@ -292,18 +292,6 @@
         self.w(xml_escape(msg))
 
 
-class ObjectReferencepArchiveUnitEntityView(view.EntityView):
-
-    __regid__ = 'seda.object-ref.archive-unit'
-    __select__ = is_instance('SEDADataObjectReference')
-
-    def entity_call(self, entity):
-        au_seq = entity.seda_data_object_reference[0]
-        au_choice = au_seq.reverse_seda_seq_alt_archive_unit_archive_unit_ref_id_management[0]
-        archive_unit = au_choice.reverse_seda_alt_archive_unit_archive_unit_ref_id[0]
-        self._cw.view('listitem', rset=archive_unit.as_rset(), w=self.w)
-
-
 class UnitBusinessValueEntityView(viewlib.BusinessValueEntityView):
 
     __select__ = is_instance('SEDAWidth', 'SEDAHeight', 'SEDADepth', 'SEDAShape',
--- a/views/viewlib.py	Fri Jan 06 12:02:49 2017 +0100
+++ b/views/viewlib.py	Fri Jan 06 14:20:19 2017 +0100
@@ -15,11 +15,12 @@
 # with this program. If not, see <http://www.gnu.org/licenses/>.
 """Library of views use there and there in the interface"""
 
-from cubicweb import tags, _
-from cubicweb.predicates import match_kwargs, is_instance
+from cubicweb import tags, view, _
+from cubicweb.predicates import match_kwargs, is_instance, score_entity
 from cubicweb.view import EntityView
-from cubicweb.web.views import tabs
+from cubicweb.web.views import baseviews, tabs
 
+from cubes.seda.xsd import un_camel_case
 from cubes.seda.xsd2uicfg import FIRST_LEVEL_ETYPES
 from cubes.seda.views import add_subobjects_button
 
@@ -249,3 +250,97 @@
 
     def parent(self, entity):
         return entity
+
+
+# references views #################################################################################
+
+def typed_reference_origin(entity):
+    """Given a typed reference (eg. SEDAIsVersionOf, SEDAReplaces, etc), return a value to display
+    its type and origin (archive unit defining it).
+    """
+    up_to_content_rtype = 'seda_{}'.format(un_camel_case(entity.cw_etype[4:]))
+    content = entity.related(up_to_content_rtype).one()
+    archive_unit = content.cw_adapt_to('ITreeBase').parent()
+    return'{} ({})'.format(archive_unit.view('incontext'), entity.dc_type())
+
+
+class ArchiveUnitRefIdOutOfContextView(baseviews.OutOfContextView):
+    """Custom outofcontext view for proper display of SEDAArchiveUnitRefId from in boxes"""
+    __select__ = is_instance('SEDAArchiveUnitRefId')
+
+    def cell_call(self, row, col):
+        entity = self.cw_rset.get_entity(row, col)
+        parent = entity.cw_adapt_to('IContained').parent
+        if parent.cw_etype == 'SEDAAltArchiveUnitArchiveUnitRefId':
+            parent.view('incontext', w=self.w)
+        else:
+            parent_parent_rtype = 'seda_{}'.format(un_camel_case(parent.cw_etype[4:]))
+            parent_parent = parent.related(parent_parent_rtype, 'object').one()
+            self.w(typed_reference_origin(parent_parent))
+
+
+class ArchiveUnitRefIdBusinessValueLinkEntityView(BusinessValueLinkEntityView):
+    __select__ = is_instance('SEDAArchiveUnitRefId')
+
+    def entity_value(self, entity):
+        if entity.seda_archive_unit_ref_id_to:
+            archiveunit = entity.seda_archive_unit_ref_id_to[0]
+            return archiveunit.view('oneline')
+        return None
+
+
+def is_main_data_object_reference(reference):
+    """Return True if the given SEDADataObjectReference is a 'main' reference from an archive unit
+    to a data object (not a qualified reference, eg IsVersionOf, IsPartOf, Reference, etc.).
+    """
+    parent = reference.seda_data_object_reference[0]
+    return parent.cw_etype == 'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement'
+
+
+class MainDataObjectReferenceBusinessValueLinkEntityView(BusinessValueLinkEntityView):
+    __select__ = (is_instance('SEDADataObjectReference')
+                  & score_entity(lambda x: is_main_data_object_reference(x)))
+
+    def entity_call(self, entity):
+        do_rset = entity.related('seda_data_object_reference_id', 'subject')
+        if do_rset:
+            do_rset.one().view(self.__regid__, w=self.w)
+        else:
+            super(MainDataObjectReferenceBusinessValueLinkEntityView, self).entity_call(entity)
+
+
+class OtherDataObjectReferenceBusinessValueLinkEntityView(BusinessValueLinkEntityView):
+    __select__ = (is_instance('SEDADataObjectReference')
+                  & score_entity(lambda x: not is_main_data_object_reference(x)))
+
+    def entity_value(self, entity):
+        if entity.seda_data_object_reference_id:
+            dataobject = entity.seda_data_object_reference_id[0]
+            return dataobject.view('oneline')
+        return None
+
+
+class ObjectReferencepArchiveUnitEntityView(view.EntityView):
+
+    __regid__ = 'seda.object-ref.archive-unit'
+    __select__ = is_instance('SEDADataObjectReference')
+
+    def entity_call(self, entity):
+        au_seq = entity.seda_data_object_reference[0]
+        if au_seq.cw_etype == 'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement':
+            au_choice = au_seq.reverse_seda_seq_alt_archive_unit_archive_unit_ref_id_management[0]
+            target = au_choice.reverse_seda_alt_archive_unit_archive_unit_ref_id[0]
+        else:
+            rtype = 'seda_{}'.format(un_camel_case(au_seq.cw_etype[4:]))
+            target = au_seq.related(rtype, 'object').one()
+        target.view('listitem', w=self.w)
+
+
+class ReferenceListItemView(view.EntityView):
+    __regid__ = 'listitem'
+    # additional match_kwargs because we don't want to be selected by SubObjectsTab based list
+    __select__ = is_instance('SEDAIsVersionOf', 'SEDAReplaces', 'SEDARequires', 'SEDAIsPartOf',
+                             'SEDAReferences') & ~match_kwargs('tabid')
+
+    def entity_call(self, entity):
+        self.w(typed_reference_origin(entity))