web/views/editforms.py
author sylvain.thenault@logilab.fr
Tue, 07 Apr 2009 19:55:10 +0200
branchtls-sprint
changeset 1276 f213008fad2c
parent 1234 4d5ff6a3d539
child 1277 2eeef019e186
permissions -rw-r--r--
catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     1
"""Set of HTML automatic forms to create, delete, copy or edit a single entity
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     2
or a list of entities of the same type
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     3
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     4
:organization: Logilab
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     5
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     6
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     7
"""
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
     9
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    10
from copy import copy
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    11
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    12
from simplejson import dumps
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    13
1183
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
    14
from logilab.common.decorators import iclassmethod
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    15
from logilab.mtconverter import html_escape
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    16
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    17
from cubicweb import typed_eid
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    18
from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    19
                                specified_etype_implements, yes)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    20
from cubicweb.rtags import RelationTags
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    21
from cubicweb.utils import make_uid
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1091
diff changeset
    22
from cubicweb.view import EntityView
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    23
from cubicweb.common import tags
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    24
from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, formwidgets
1276
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
    25
from cubicweb.web.form import (FieldNotFound, CompositeForm, EntityFieldsForm,
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
    26
                               FormMixIn)
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1091
diff changeset
    27
from cubicweb.web.formfields import guess_field
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    28
from cubicweb.web.formrenderers import (FormRenderer, EntityFormRenderer,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    29
                                        EntityCompositeFormRenderer,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    30
                                        EntityInlinedFormRenderer)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    31
_ = unicode
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    32
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    33
def relation_id(eid, rtype, role, reid):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    34
    """return an identifier for a relation between two entities"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    35
    if role == 'subject':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    36
        return u'%s:%s:%s' % (eid, rtype, reid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    37
    return u'%s:%s:%s' % (reid, rtype, eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    38
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    39
def toggable_relation_link(eid, nodeid, label='x'):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    40
    """return javascript snippet to delete/undelete a relation between two
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    41
    entities
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    42
    """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    43
    js = u"javascript: togglePendingDelete('%s', %s);" % (nodeid, html_escape(dumps(eid)))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    44
    return u'[<a class="handle" href="%s" id="handle%s">%s</a>]' % (js, nodeid, label)
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    45
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    46
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    47
class DeleteConfForm(EntityView):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    48
    """form used to confirm deletion of some entities"""
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    49
    id = 'deleteconf'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    50
    title = _('delete')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    51
    domid = 'deleteconf'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    52
    onsubmit = None
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    53
    # don't use navigation, all entities asked to be deleted should be displayed
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    54
    # else we will only delete the displayed page
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    55
    need_navigation = False
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    56
    
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    57
    def call(self):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    58
        """ask for confirmation before real deletion"""
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    59
        req, w = self.req, self.w
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    60
        _ = req._
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    61
        w(u'<script type="text/javascript">updateMessage(\'%s\');</script>\n'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    62
          % _('this action is not reversible!'))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    63
        # XXX above message should have style of a warning
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    64
        w(u'<h4>%s</h4>\n' % _('Do you want to delete the following element(s) ?'))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    65
        form = CompositeForm(req, domid='deleteconf', action=self.build_url('edit'),
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    66
                                  onsubmit=self.onsubmit, copy_nav_params=True)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    67
        # XXX tabindex
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    68
        form.buttons.append(form.button_delete(label=stdmsgs.YES))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    69
        form.buttons.append(form.button_cancel(label=stdmsgs.NO))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    70
        done = set()
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    71
        w(u'<ul>\n')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    72
        for entity in self.rset.entities():
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    73
            if entity.eid in done:
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    74
                continue
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    75
            done.add(entity.eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    76
            subform = EntityFieldsForm(req, entity=entity, set_error_url=False)
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    77
            form.form_add_subform(subform)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    78
            # don't use outofcontext view or any other that may contain inline edition form
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    79
            w(u'<li>%s</li>' % tags.a(entity.view('textoutofcontext'),
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    80
                                      href=entity.absolute_url()))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    81
        w(u'</ul>\n')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    82
        w(form.form_render())
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    83
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    84
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    85
class ClickAndEditForm(FormMixIn, EntityView):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    86
    """form used to permit ajax edition of an attribute of an entity in a view
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    87
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    88
    (double-click on the field to see an appropriate edition widget)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    89
    """
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    90
    id = 'reledit'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    91
    __select__ = non_final_entity() & match_kwargs('rtype')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    92
    
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    93
    # FIXME editableField class could be toggleable from userprefs
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    94
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    95
    onsubmit = ("return inlineValidateForm('%(divid)s-form', '%(rtype)s', "
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    96
                "'%(eid)s', '%(divid)s', %(reload)s);")
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    97
    ondblclick = "showInlineEditionForm(%(eid)s, '%(rtype)s', '%(divid)s')"
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    98
    
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
    99
    def cell_call(self, row, col, rtype=None, role='subject', reload=False):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   100
        """display field to edit entity's `rtype` relation on double-click"""
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   101
        entity = self.entity(row, col)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   102
        if getattr(entity, rtype) is None:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   103
            value = self.req._('not specified')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   104
        else:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   105
            value = entity.printable_value(rtype)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   106
        if not entity.has_perm('update'):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   107
            self.w(value)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   108
            return
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   109
        self.req.add_js( ('cubicweb.ajax.js',) )
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   110
        eid = entity.eid
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   111
        edit_key = make_uid('%s-%s' % (rtype, eid))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   112
        divid = 'd%s' % edit_key
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   113
        reload = dumps(reload)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   114
        # XXX tab index
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   115
        buttons = [tags.input(klass="validateButton", type="submit",
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   116
                              name="__action_apply",
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   117
                              value=self.req._(stdmsgs.BUTTON_OK),
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   118
                              tabindex=self.req.next_tabindex()),
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   119
                   tags.input(klass="validateButton", type="button",
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   120
                              value=self.req._(stdmsgs.BUTTON_CANCEL),
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   121
                              onclick="cancelInlineEdit(%s,\'%s\',\'%s\')" % (eid, rtype, divid),
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   122
                              tabindex=self.req.next_tabindex())]
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   123
        form = self.vreg.select_object('forms', 'edition', self.req, self.rset,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   124
                                       row=row, col=col, buttons=buttons,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   125
                                       domid='%s-form' % divid, action='#',
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   126
                                       cssstyle='display: none',
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   127
                                       onsubmit=self.onsubmit % locals())
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   128
        renderer = FormRenderer(display_label=False, display_help=False,
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   129
                                display_fields=(rtype,), button_bar_class='buttonbar')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   130
        self.w(tags.div(value, klass='editableField', id=divid,
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   131
                        ondblclick=self.ondblclick % locals()))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   132
        self.w(form.form_render(renderer=renderer))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   133
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   134
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   135
class AutomaticEntityForm(EntityFieldsForm):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   136
    """base automatic form to edit any entity
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   137
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   138
    Designed to be flly generated from schema but highly configurable through:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   139
    * rtags (rcategories, rwidgets, inlined, rpermissions)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   140
    * various standard form parameters
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   141
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   142
    You can also easily customise it by adding/removing fields in
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   143
    AutomaticEntityForm instances.
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   144
    """
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   145
    id = 'edition'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   146
    
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   147
    needs_js = EntityFieldsForm.needs_js + ('cubicweb.ajax.js',)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   148
    cwtarget = 'eformframe'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   149
    cssclass = 'entityForm'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   150
    copy_nav_params = True
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   151
    attrcategories = ('primary', 'secondary')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   152
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   153
    # relations'category (eg primary/secondary/generic/metadata/generated)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   154
    rcategories = RelationTags()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   155
    # use primary and not generated for eid since it has to be an hidden
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   156
    rcategories.set_rtag('primary', 'eid', 'subject')
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   157
    rcategories.set_rtag('metadata', 'creation_date', 'subject')
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   158
    rcategories.set_rtag('metadata', 'modification_date', 'subject')
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   159
    rcategories.set_rtag('generated', 'has_text', 'subject')
1151
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   160
    rcategories.set_rtag('metadata', 'owned_by', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   161
    rcategories.set_rtag('metadata', 'created_by', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   162
    rcategories.set_rtag('generated', 'is', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   163
    rcategories.set_rtag('generated', 'is', 'object')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   164
    rcategories.set_rtag('generated', 'is_instance_of', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   165
    rcategories.set_rtag('generated', 'is_instance_of', 'object')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   166
    rcategories.set_rtag('generated', 'identity', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   167
    rcategories.set_rtag('generated', 'identity', 'object')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   168
    rcategories.set_rtag('generated', 'require_permission', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   169
    rcategories.set_rtag('primary', 'in_state', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   170
    rcategories.set_rtag('generated', 'wf_info_for', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   171
    rcategories.set_rtag('generated', 'wf_info_for', 'subject')
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   172
    rcategories.set_rtag('secondary', 'description', 'subject')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   173
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   174
    # relations'widget (eg one of available class name in cubicweb.web.formwidgets)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   175
    rwidgets = RelationTags()
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   176
    # inlined view flag for non final relations: when True for an entry, the
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   177
    # entity(ies) at the other end of the relation will be editable from the
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   178
    # form of the edited entity
1151
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   179
    rinlined = RelationTags()
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   180
    # set of tags of the form <action>_on_new on relations. <action> is a
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   181
    # schema action (add/update/delete/read), and when such a tag is found
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   182
    # permissions checking is by-passed and supposed to be ok
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   183
    rpermissions_overrides = RelationTags(use_set=True)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   184
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   185
    @classmethod
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   186
    def registered(cls, registry):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   187
        """build class using descriptor at registration time"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   188
        super(AutomaticEntityForm, cls).registered(registry)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   189
        cls.init_rtags_category()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   190
        return cls
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   191
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   192
    @classmethod
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   193
    def init_rtags_category(cls):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   194
        """set default category tags for relations where it's not yet defined in
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   195
        the category relation tags
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   196
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   197
        for eschema in cls.schema.entities():
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   198
            for rschema, tschemas, role in eschema.relation_definitions(True):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   199
                for tschema in tschemas:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   200
                    if role == 'subject':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   201
                        X, Y = eschema, tschema
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   202
                        card = rschema.rproperty(X, Y, 'cardinality')[0]
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   203
                        composed = rschema.rproperty(X, Y, 'composite') == 'object'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   204
                    else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   205
                        X, Y = tschema, eschema
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   206
                        card = rschema.rproperty(X, Y, 'cardinality')[1]
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   207
                        composed = rschema.rproperty(X, Y, 'composite') == 'subject'
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   208
                    if not cls.rcategories.rtag(rschema, role, X, Y):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   209
                        if card in '1+':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   210
                            if not rschema.is_final() and composed:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   211
                                category = 'generated'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   212
                            else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   213
                                category = 'primary'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   214
                        elif rschema.is_final():
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   215
                            category = 'secondary'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   216
                        else: 
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   217
                            category = 'generic'
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   218
                        cls.rcategories.set_rtag(category, rschema, role, X, Y)
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   219
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   220
    @classmethod
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   221
    def erelations_by_category(cls, entity, categories=None, permission=None):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   222
        """return a list of (relation schema, target schemas, role) matching
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   223
        categories and permission
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   224
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   225
        if categories is not None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   226
            if not isinstance(categories, (list, tuple, set, frozenset)):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   227
                categories = (categories,)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   228
            if not isinstance(categories, (set, frozenset)):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   229
                categories = frozenset(categories)
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   230
        eschema  = entity.e_schema
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   231
        rtags = cls.rcategories
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   232
        permsoverrides = cls.rpermissions_overrides
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   233
        if entity.has_eid():
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   234
            eid = entity.eid
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   235
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   236
            eid = None
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   237
        for rschema, targetschemas, role in eschema.relation_definitions(True):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   238
            if rschema in ('identity', 'has_text'):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   239
                continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   240
            # check category first, potentially lower cost than checking
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   241
            # permission which may imply rql queries
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   242
            if categories is not None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   243
                targetschemas = [tschema for tschema in targetschemas
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   244
                                 if rtags.etype_rtag(eschema, rschema, role, tschema) in categories]
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   245
                if not targetschemas:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   246
                    continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   247
            if permission is not None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   248
                # tag allowing to hijack the permission machinery when
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   249
                # permission is not verifiable until the entity is actually
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   250
                # created...
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   251
                if eid is None and '%s_on_new' % permission in permsoverrides.etype_rtags(eschema, rschema, role):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   252
                    yield (rschema, targetschemas, role)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   253
                    continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   254
                if rschema.is_final():
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   255
                    if not rschema.has_perm(entity.req, permission, eid):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   256
                        continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   257
                elif role == 'subject':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   258
                    if not ((eid is None and rschema.has_local_role(permission)) or
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   259
                            rschema.has_perm(entity.req, permission, fromeid=eid)):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   260
                        continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   261
                    # on relation with cardinality 1 or ?, we need delete perm as well
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   262
                    # if the relation is already set
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   263
                    if (permission == 'add'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   264
                        and rschema.cardinality(eschema, targetschemas[0], role) in '1?'
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   265
                        and eid and entity.related(rschema.type, role)
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   266
                        and not rschema.has_perm(entity.req, 'delete', fromeid=eid,
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   267
                                                 toeid=entity.related(rschema.type, role)[0][0])):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   268
                        continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   269
                elif role == 'object':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   270
                    if not ((eid is None and rschema.has_local_role(permission)) or
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   271
                            rschema.has_perm(entity.req, permission, toeid=eid)):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   272
                        continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   273
                    # on relation with cardinality 1 or ?, we need delete perm as well
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   274
                    # if the relation is already set
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   275
                    if (permission == 'add'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   276
                        and rschema.cardinality(targetschemas[0], eschema, role) in '1?'
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   277
                        and eid and entity.related(rschema.type, role)
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   278
                        and not rschema.has_perm(entity.req, 'delete', toeid=eid,
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1151
diff changeset
   279
                                                 fromeid=entity.related(rschema.type, role)[0][0])):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   280
                        continue
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   281
            yield (rschema, targetschemas, role)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   282
    
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   283
    @classmethod
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   284
    def esrelations_by_category(cls, entity, categories=None, permission=None):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   285
        """filter out result of relations_by_category(categories, permission) by
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   286
        removing final relations
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   287
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   288
        return a sorted list of (relation's label, relation'schema, role) 
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   289
        """
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   290
        result = []
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   291
        for rschema, ttypes, role in cls.erelations_by_category(
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   292
            entity, categories, permission):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   293
            if rschema.is_final():
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   294
                continue
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   295
            result.append((rschema.display_name(entity.req, role), rschema, role))
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   296
        return sorted(result)
1183
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   297
    
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   298
    @iclassmethod
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   299
    def field_by_name(cls_or_self, name, role='subject', eclass=None):
1276
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
   300
        """return field with the given name and role. If field is not explicitly
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
   301
        defined for the form but `eclass` is specified, guess_field will be
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
   302
        called.
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
   303
        """
1183
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   304
        try:
1234
sylvain.thenault@logilab.fr
parents: 1183
diff changeset
   305
            return super(AutomaticEntityForm, cls_or_self).field_by_name(name, role)
1276
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
   306
        except FieldNotFound: # XXX should raise more explicit exception
1183
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   307
            if eclass is None:
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   308
                raise
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   309
            field = guess_field(eclass, cls_or_self.schema.rschema(name), role,
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   310
                                eidparam=True)
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   311
            if field is None:
62afd820d3ae field_by_name now takes a "role" argument, override it in AutomaticForm to call guess field if necessary
sylvain.thenault@logilab.fr
parents: 1179
diff changeset
   312
                raise
1276
f213008fad2c catch FieldNotFound instead of Exception in field_by_name, return the field if guessable
sylvain.thenault@logilab.fr
parents: 1234
diff changeset
   313
            return field
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   314
    
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   315
    def __init__(self, *args, **kwargs):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   316
        super(AutomaticEntityForm, self).__init__(*args, **kwargs)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   317
        if self.edited_entity.has_eid():
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   318
            self.edited_entity.complete()
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   319
        for rschema, role in self.editable_attributes():
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   320
            wdgname = self.rwidgets.etype_rtag(self.edited_entity.id, rschema,
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   321
                                               role)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   322
            if wdgname:
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   323
                widget = getattr(formwidgets, wdgname)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   324
                field = guess_field(self.edited_entity.__class__, rschema, role,
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   325
                                    eidparam=True, widget=widget)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   326
            else:
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   327
                field = guess_field(self.edited_entity.__class__, rschema, role,
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   328
                                    eidparam=True)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   329
            if field is not None:
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   330
                self.fields.append(field)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   331
    
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   332
    def relations_by_category(self, categories=None, permission=None):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   333
        """return a list of (relation schema, target schemas, role) matching
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   334
        given category(ies) and permission
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   335
        """
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   336
        return self.erelations_by_category(self.edited_entity, categories,
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   337
                                           permission)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   338
    
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   339
    def srelations_by_category(self, categories=None, permission=None):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   340
        """filter out result of relations_by_category(categories, permission) by
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   341
        removing final relations
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   342
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   343
        return a sorted list of (relation's label, relation'schema, role) 
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   344
        """
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   345
        return self.esrelations_by_category(self.edited_entity, categories,
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   346
                                           permission)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   347
        
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   348
    def action(self):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   349
        """return the form's action attribute. Default to validateform if not
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   350
        explicitly overriden.
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   351
        """
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   352
        try:
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   353
            return self._action
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   354
        except AttributeError:
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   355
            return self.build_url('validateform')
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   356
        
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   357
    def set_action(self, value):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   358
        """override default action"""
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   359
        self._action = value
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   360
        
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   361
    action = property(action, set_action)
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   362
    
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   363
    def form_buttons(self):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   364
        """return the form's buttons (as string)"""
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   365
        return [self.button_ok(tabindex=self.req.next_tabindex()),
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   366
                self.button_apply(tabindex=self.req.next_tabindex()),
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   367
                self.button_cancel(tabindex=self.req.next_tabindex())]
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   368
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   369
    def editable_attributes(self):
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   370
        """return a list of (relation schema, role) to edit for the entity"""
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   371
        return [(rschema, x) for rschema, _, x in self.relations_by_category(
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   372
            self.attrcategories, 'add') if rschema != 'eid']
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   373
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   374
    def relations_table(self):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   375
        """yiels 3-tuples (rtype, target, related_list)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   376
        where <related_list> itself a list of :
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   377
          - node_id (will be the entity element's DOM id)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   378
          - appropriate javascript's togglePendingDelete() function call
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   379
          - status 'pendingdelete' or ''
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   380
          - oneline view of related entity
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   381
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   382
        entity = self.edited_entity
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   383
        pending_deletes = self.req.get_pending_deletes(entity.eid)
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   384
        for label, rschema, role in self.srelations_by_category('generic', 'add'):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   385
            relatedrset = entity.related(rschema, role, limit=self.limit)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   386
            if rschema.has_perm(self.req, 'delete'):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   387
                toggable_rel_link_func = toggable_relation_link
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   388
            else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   389
                toggable_rel_link_func = lambda x, y, z: u''
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   390
            related = []
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   391
            for row in xrange(relatedrset.rowcount):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   392
                nodeid = relation_id(entity.eid, rschema, role,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   393
                                     relatedrset[row][0])
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   394
                if nodeid in pending_deletes:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   395
                    status = u'pendingDelete'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   396
                    label = '+'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   397
                else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   398
                    status = u''
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   399
                    label = 'x'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   400
                dellink = toggable_rel_link_func(entity.eid, nodeid, label)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   401
                eview = self.view('oneline', relatedrset, row=row)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   402
                related.append((nodeid, dellink, status, eview))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   403
            yield (rschema, role, related)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   404
            
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   405
    def restore_pending_inserts(self, cell=False):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   406
        """used to restore edition page as it was before clicking on
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   407
        'search for <some entity type>'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   408
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   409
        eid = self.edited_entity.eid
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   410
        cell = cell and "div_insert_" or "tr"
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   411
        pending_inserts = set(self.req.get_pending_inserts(eid))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   412
        for pendingid in pending_inserts:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   413
            eidfrom, rtype, eidto = pendingid.split(':')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   414
            if typed_eid(eidfrom) == eid: # subject
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   415
                label = display_name(self.req, rtype, 'subject')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   416
                reid = eidto
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   417
            else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   418
                label = display_name(self.req, rtype, 'object')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   419
                reid = eidfrom
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   420
            jscall = "javascript: cancelPendingInsert('%s', '%s', null, %s);" \
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   421
                     % (pendingid, cell, eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   422
            rset = self.req.eid_rset(reid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   423
            eview = self.view('text', rset, row=0)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   424
            # XXX find a clean way to handle baskets
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   425
            if rset.description[0][0] == 'Basket':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   426
                eview = '%s (%s)' % (eview, display_name(self.req, 'Basket'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   427
            yield rtype, pendingid, jscall, label, reid, eview
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   428
            
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   429
    # should_* method extracted to allow overriding
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   430
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   431
    def should_inline_relation_form(self, rschema, targettype, role):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   432
        """return true if the given relation with entity has role and a
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   433
        targettype target should be inlined
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   434
        """
1179
70825477c6ce fix *relations_by_categories + rtags api/key mess
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   435
        return self.rinlined.etype_rtag(self.edited_entity.id, rschema, role, targettype)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   436
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   437
    def should_display_inline_creation_form(self, rschema, existant, card):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   438
        """return true if a creation form should be inlined
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   439
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   440
        by default true if there is no related entity and we need at least one
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   441
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   442
        return not existant and card in '1+'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   443
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   444
    def should_display_add_new_relation_link(self, rschema, existant, card):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   445
        """return true if we should add a link to add a new creation form
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   446
        (through ajax call)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   447
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   448
        by default true if there is no related entity or if the relation has
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   449
        multiple cardinality
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   450
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   451
        return not existant or card in '+*'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   452
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   453
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   454
class EditionFormView(EntityView):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   455
    """display primary entity edition form"""    
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   456
    id = 'edition'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   457
    # add yes() so it takes precedence over deprecated views in baseforms,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   458
    # though not baseforms based customized view
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   459
    __select__ = one_line_rset() & non_final_entity() & yes()
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   460
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   461
    title = _('edition')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   462
    controller = 'edit'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   463
    
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   464
    def cell_call(self, row, col, **kwargs):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   465
        entity = self.complete_entity(row, col)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   466
        self.render_form(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   467
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   468
    def render_form(self, entity):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   469
        """fetch and render the form"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   470
        self.form_title(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   471
        form = self.vreg.select_object('forms', 'edition', self.req, self.rset,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   472
                                       row=self.row, col=self.col, entity=entity,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   473
                                       domid=self.id, submitmsg=self.submited_message())
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   474
        self.init_form(form, entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   475
        self.w(form.form_render(renderer=EntityFormRenderer(), formvid=u'edition'))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   476
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   477
    def init_form(self, form, entity):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   478
        """customize your form before rendering here"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   479
        form.form_add_hidden(u'__maineid', entity.eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   480
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   481
    def form_title(self, entity):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   482
        """the form view title"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   483
        ptitle = self.req._(self.title)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   484
        self.w(u'<div class="formTitle"><span>%s %s</span></div>' % (
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   485
            entity.dc_type(), ptitle and '(%s)' % ptitle))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   486
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   487
    def submited_message(self):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   488
        """return the message that will be displayed on successful edition"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   489
        return self.req._('entity edited')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   490
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   491
        
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   492
class CreationFormView(EditionFormView):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   493
    """display primary entity creation form"""    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   494
    id = 'creation'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   495
    __select__ = specified_etype_implements('Any') & yes()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   496
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   497
    title = _('creation')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   498
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   499
    def call(self, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   500
        """creation view for an entity"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   501
        etype = kwargs.pop('etype', self.req.form.get('etype'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   502
        try:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   503
            entity = self.vreg.etype_class(etype)(self.req, None, None)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   504
        except:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   505
            self.w(self.req._('no such entity type %s') % etype)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   506
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   507
            self.initialize_varmaker()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   508
            entity.eid = self.varmaker.next()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   509
            self.render_form(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   510
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   511
    def form_title(self, entity):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   512
        """the form view title"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   513
        if '__linkto' in self.req.form:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   514
            if isinstance(self.req.form['__linkto'], list):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   515
                # XXX which one should be considered (case: add a ticket to a
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   516
                # version in jpl)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   517
                rtype, linkto_eid, role = self.req.form['__linkto'][0].split(':')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   518
            else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   519
                rtype, linkto_eid, role = self.req.form['__linkto'].split(':')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   520
            linkto_rset = self.req.eid_rset(linkto_eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   521
            linkto_type = linkto_rset.description[0][0]
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   522
            if role == 'subject':
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   523
                title = self.req.__('creating %s (%s %s %s %%(linkto)s)' % (
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   524
                    entity.e_schema, entity.e_schema, rtype, linkto_type))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   525
            else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   526
                title = self.req.__('creating %s (%s %%(linkto)s %s %s)' % (
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   527
                    entity.e_schema, linkto_type, rtype, entity.e_schema))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   528
            msg = title % {'linkto' : self.view('incontext', linkto_rset)}
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   529
            self.w(u'<div class="formTitle notransform"><span>%s</span></div>' % msg)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   530
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   531
            super(CreationFormView, self).form_title(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   532
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   533
    def url(self):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   534
        """return the url associated with this view"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   535
        return self.create_url(self.req.form.get('etype'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   536
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   537
    def submited_message(self):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   538
        """return the message that will be displayed on successful edition"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   539
        return self.req._('entity created')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   540
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   541
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   542
class CopyFormView(EditionFormView):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   543
    """display primary entity creation form initialized with values from another
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   544
    entity
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   545
    """    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   546
    id = 'copy'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   547
    def render_form(self, entity):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   548
        """fetch and render the form"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   549
        # make a copy of entity to avoid altering the entity in the
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   550
        # request's cache. 
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   551
        self.newentity = copy(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   552
        self.copying = self.newentity.eid
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   553
        self.newentity.eid = None
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   554
        self.w(u'<script type="text/javascript">updateMessage("%s");</script>\n'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   555
               % self.req._('Please note that this is only a shallow copy'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   556
        super(CopyFormView, self).render_form(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   557
        del self.newentity
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   558
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   559
    def init_form(self, form, entity):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   560
        """customize your form before rendering here"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   561
        super(CopyFormView, self).init_form(form, entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   562
        if entity.eid == self.newentity.eid:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   563
            form.form_add_hidden('__cloned_eid', self.copying, eidparam=True)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   564
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   565
    def submited_message(self):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   566
        """return the message that will be displayed on successful edition"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   567
        return self.req._('entity copied')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   568
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   569
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   570
class TableEditForm(CompositeForm):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   571
    id = 'muledit'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   572
    onsubmit = "return validateForm('entityForm', null);"
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   573
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   574
    def __init__(self, *args, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   575
        super(TableEditForm, self).__init__(*args, **kwargs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   576
        for row in xrange(len(self.rset)):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   577
            form = self.vreg.select_object('forms', 'edition', self.req, self.rset,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   578
                                           row=row, domid=self.id,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   579
                                           attrcategories=('primary',),
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   580
                                           set_error_url=False)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   581
            # XXX rely on the MultipleEntityFormRenderer to put the eid input
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   582
            form.remove_field(form.field_by_name('eid'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   583
            self.form_add_subform(form)
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents:
diff changeset
   584
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   585
    def form_buttons(self):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   586
        """return the form's buttons (as string)"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   587
        okt = self.req._('validate modifications on selected items').capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   588
        resett = self.req._('revert changes').capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   589
        return [self.button_ok(title=okt), self.button_reset(title=resett)]
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   590
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   591
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   592
class TableEditFormView(EntityView):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   593
    id = 'muledit'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   594
    __select__ = EntityView.__select__ & yes()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   595
    title = _('multiple edit')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   596
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   597
    def call(self, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   598
        """a view to edit multiple entities of the same type the first column
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   599
        should be the eid
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   600
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   601
        #self.form_title(entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   602
        form = self.vreg.select_object('forms', self.id, self.req, self.rset,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   603
                                       domid=self.id)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   604
        self.w(form.form_render(renderer=EntityCompositeFormRenderer()))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   605
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   606
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   607
class InlineEntityEditionFormView(EntityView):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   608
    id = 'inline-edition'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   609
    __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   610
    removejs = "removeInlinedEntity('%s', '%s', '%s')"
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   611
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   612
    def call(self, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   613
        """redefine default call() method to avoid automatic
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   614
        insertions of <div class="section"> between each row of
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   615
        the resultset
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   616
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   617
        rset = self.rset
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   618
        for i in xrange(len(rset)):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   619
            self.wview(self.id, rset, row=i, **kwargs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   620
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   621
    def cell_call(self, row, col, peid, rtype, role='subject', **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   622
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   623
        :param peid: the parent entity's eid hosting the inline form
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   624
        :param rtype: the relation bridging `etype` and `peid`
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   625
        :param role: the role played by the `peid` in the relation
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   626
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   627
        entity = self.entity(row, col)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   628
        divonclick = "restoreInlinedEntity('%s', '%s', '%s')" % (peid, rtype,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   629
                                                                 entity.eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   630
        self.render_form(entity, peid, rtype, role, divonclick=divonclick)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   631
        
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   632
    def render_form(self, entity, peid, rtype, role, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   633
        """fetch and render the form"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   634
        rschema = self.schema.rschema(rtype)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   635
        divid = '%s-%s-%s' % (peid, rtype, entity.eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   636
        title = rschema.display_name(self.req, role)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   637
        form = self.vreg.select_object('forms', 'edition', self.req,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   638
                                       entity=entity)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   639
        removejs = self.removejs % (peid, rtype,entity.eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   640
        if self.keep_entity(entity, peid, rtype):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   641
            if entity.has_eid():
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   642
                rval = entity.eid
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   643
            else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   644
                rval = INTERNAL_FIELD_VALUE
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   645
            form.form_add_hidden('edit%s-%s:%s' % (role[0], rtype, peid), rval)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   646
        form.form_add_hidden(name='%s:%s' % (rtype, peid), value=entity.eid,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   647
                             id='rel-%s-%s-%s'  % (peid, rtype, entity.eid))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   648
        self.w(form.form_render(renderer=EntityInlinedFormRenderer(), divid=divid,
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   649
                                title=title, removejs=removejs,**kwargs))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   650
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   651
    def keep_entity(self, entity, peid, rtype):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   652
        if not entity.has_eid():
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   653
            return True
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   654
        # are we regenerating form because of a validation error ?
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   655
        erroneous_post = self.req.data.get('formvalues')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   656
        if erroneous_post:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   657
            cdvalues = self.req.list_form_param('%s:%s' % (rtype, peid),
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   658
                                                erroneous_post)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   659
            if unicode(entity.eid) not in cdvalues:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   660
                return False
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   661
        return True
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   662
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   663
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   664
class InlineEntityCreationFormView(InlineEntityEditionFormView):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   665
    id = 'inline-creation'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   666
    __select__ = (match_kwargs('peid', 'rtype')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   667
                  & specified_etype_implements('Any'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   668
    
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   669
    def call(self, etype, peid, rtype, role='subject', **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   670
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   671
        :param etype: the entity type being created in the inline form
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   672
        :param peid: the parent entity's eid hosting the inline form
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   673
        :param rtype: the relation bridging `etype` and `peid`
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   674
        :param role: the role played by the `peid` in the relation
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   675
        """
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   676
        try:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   677
            entity = self.vreg.etype_class(etype)(self.req, None, None)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   678
        except:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   679
            self.w(self.req._('no such entity type %s') % etype)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   680
            return
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   681
        self.initialize_varmaker()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   682
        entity.eid = self.varmaker.next()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
   683
        self.render_form(entity, peid, rtype, role)