[PATCH 2 of 4 compound] Rework default cloning UI features

Sylvain Thenault sylvain.thenault at logilab.fr
Wed Mar 1 10:56:53 CET 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1488349780 -3600
#      Wed Mar 01 07:29:40 2017 +0100
# Node ID eddc207dda229ac1323f7885b4b1b57b93fcc988
# Parent  4d02c64534c7e907f0464b0c87733391a483af7b
Rework default cloning UI features

* make CloneAction abstract, we don't want it to appear auto-magically for every
  IClonable entities,

* backport NoWarningCopyFormView from saem_ref,

* extract part of CloneAction.url into linkto_clone_url_params function and test
  it,

* enhance translation,

* more docstrings / comments.

diff --git a/i18n/fr.po b/i18n/fr.po
--- a/i18n/fr.po
+++ b/i18n/fr.po
@@ -6,10 +6,10 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: pygettext.py 1.5\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
 msgid "clone"
-msgstr "cloner"
+msgstr "dupliquer"
 
 #, python-format
 msgid "clone of entity #%d created"
-msgstr "un clone de l'entité #%d a été crée"
+msgstr "une copie de l'entité #%d a été créée"
diff --git a/test/data/entities.py b/test/data/entities.py
--- a/test/data/entities.py
+++ b/test/data/entities.py
@@ -1,9 +1,10 @@
-from cubicweb.predicates import has_related_entities
+from cubicweb.predicates import has_related_entities, is_instance
 
 from cubes.compound.entities import (IClonableAdapter, IContained, IContainer,
                                      structure_def)
+from cubes.compound.views import CloneAction
 
 
 def agent_structure_def(schema):
     return structure_def(schema, 'Agent').items()
 
@@ -20,10 +21,14 @@ class AgentInGroupIClonableAdapter(IClon
                   & has_related_entities('member', role='object'))
     rtype = 'clone_of'
     follow_relations = [('member', 'object')]
 
 
+class AgentCloneAction(CloneAction):
+    __select__ = CloneAction.__select__ & is_instance('Agent')
+
+
 def registration_callback(vreg):
     vreg.register_all(globals().values(), __name__)
     vreg.register(IContainer.build_class('Agent'))
     for etype, parent_relations in agent_structure_def(vreg.schema):
         IContained.register_class(vreg, etype, parent_relations)
diff --git a/test/test_compound.py b/test/test_compound.py
--- a/test/test_compound.py
+++ b/test/test_compound.py
@@ -369,10 +369,11 @@ class CloneTC(CubicWebTC):
             entity = req.create_entity('Agent', name=u'bob')
             req.cnx.commit()
             action = self.vreg['actions'].select('copy', req,
                                                  rset=entity.as_rset())
             self.assertIsInstance(action, CloneAction)
+            self.assertIn('clone_of', action.url())
 
     @staticmethod
     def _clone_setup(cnx):
         """Setup a graph of entities to be cloned."""
         agent = cnx.create_entity('Agent', name=u'bob')
diff --git a/views.py b/views.py
--- a/views.py
+++ b/views.py
@@ -13,36 +13,69 @@
 #
 # 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/>.
 """cubicweb-compound views/forms/actions/components for web ui"""
 
+from copy import copy
+
 from cubicweb import _, neg_role
 from cubicweb.web import Redirect
-from cubicweb.predicates import (one_line_rset, adaptable, has_permission,
-                                 match_form_params)
+from cubicweb.predicates import adaptable, has_permission, match_form_params, one_line_rset
 from cubicweb.web.controller import Controller
-from cubicweb.web.views import actions, ibreadcrumbs
+from cubicweb.web.views import actions, editforms, ibreadcrumbs
 
 from cubes.compound.entities import copy_entity
 
 
+def linkto_clone_url_params(entity):
+    iclone = entity.cw_adapt_to('IClonable')
+    linkto = '%s:%s:%s' % (iclone.rtype, entity.eid, neg_role(iclone.role))
+    return {'__linkto': linkto}
+
+
 class CloneAction(actions.CopyAction):
-    """Just a copy action (copy is handled by edit controller below) named 'clone'."""
-    __select__ = (actions.CopyAction.__select__ & one_line_rset() &
-                  adaptable('IClonable') & has_permission('add'))
+    """Abstract clone action of ICloneable entities.
+
+    Simply inherit from it with a specific selector if you want to activate it.
+    The action will link to the copy form with shallow copy message disabled and
+    linkto information to rely on the clone hook for the actual cloning.
+    """
+    __abstract__ = True
+    __select__ = (actions.CopyAction.__select__ & one_line_rset()
+                  & has_permission('add')
+                  & adaptable('IClonable'))
+    category = 'mainactions'
     title = _('clone')
 
     def url(self):
         entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
-        iclone = entity.cw_adapt_to('IClonable')
-        linkto = '%s:%s:%s' % (iclone.rtype, entity.eid, neg_role(iclone.role))
-        return entity.absolute_url(vid='copy', __linkto=linkto)
+        return entity.absolute_url(vid='copy', **linkto_clone_url_params(entity))
 
 
+# In any case IClonable entities want default copy disabled since it wont handle
+# composite relations by default.
 actions.CopyAction.__select__ &= ~adaptable('IClonable')
 
 
+class NoWarningCopyFormView(editforms.CopyFormView):
+    """Display primary entity creation form initialized with values from another
+    entity, but avoiding cubicweb default 'this is only a shallow copy' message.
+    """
+    __select__ = editforms.CopyFormView.__select__ & adaptable('ICloneable')
+
+    def render_form(self, entity):
+        """fetch and render the form"""
+        # make a copy of entity to avoid altering the entity in the
+        # request's cache.
+        entity.complete()
+        self.newentity = copy(entity)
+        self.copying = entity
+        self.newentity.eid = self._cw.varmaker.next()
+        super(editforms.CopyFormView, self).render_form(self.newentity)
+        del self.newentity
+
+
 class CloneController(Controller):
     """Controller handling cloning of the original entity (with `eid` passed
     in form parameters). Redirects to the cloned entity primary view.
     """
     __regid__ = 'compound.clone'


More information about the saem-devel mailing list