Beispiel #1
0
 def _get_removejs(self):
     """
     Don't display the remove link in edition form if the
     cardinality is 1. Handled in InlineEntityCreationFormView for
     creation form.
     """
     entity = self._entity()
     rdef = entity.e_schema.rdef(self.rtype, neg_role(self.role),
                                 self.petype)
     card = rdef.role_cardinality(self.role)
     if card == '1':  # don't display remove link
         return None
     # if cardinality is 1..n (+), dont display link to remove an inlined form for the first form
     # allowing to edit the relation. To detect so:
     #
     # * if parent form (pform) is None, we're generated through an ajax call and so we know this
     #   is not the first form
     #
     # * if parent form is not None, look for previous InlinedFormField in the parent's form
     #   fields
     if card == '+' and self.pform is not None:
         # retrieve all field'views handling this relation and return None if we're the first of
         # them
         first_view = next(
             iter((f.view for f in self.pform.fields
                   if isinstance(f, InlinedFormField) and f.view.rtype ==
                   self.rtype and f.view.role == self.role)))
         if self == first_view:
             return None
     return self.removejs and self.removejs % (self.peid, self.rtype,
                                               entity.eid)
Beispiel #2
0
def _update_entity_rel_cache_add(cnx,
                                 entity,
                                 rtype,
                                 role,
                                 targetentity,
                                 otherside=False):
    rcache = entity.cw_relation_cached(rtype, role)
    if rcache is None:
        rset = ResultSet([[targetentity.eid]],
                         'Any X WHERE X eid %s' % targetentity.eid,
                         description=[[targetentity.cw_etype]])
        rset.req = cnx
        entities = []
    else:
        rset, entities = rcache
        rset = rset.copy()
        entities = list(entities)
        rset.rows.append([targetentity.eid])
        if not isinstance(rset.description, list):  # else description not set
            rset.description = list(rset.description)
        rset.description.append([targetentity.cw_etype])
    if targetentity.cw_rset is None:
        targetentity.cw_rset = rset
        targetentity.cw_row = rset.rowcount
        targetentity.cw_col = 0
    rset.rowcount += 1
    entities.append(targetentity)
    entity._cw_related_cache['%s_%s' % (rtype, role)] = (rset, tuple(entities))
    if not otherside:
        _update_entity_rel_cache_add(cnx, targetentity, rtype, neg_role(role),
                                     entity, True)
Beispiel #3
0
 def __call__(self):
     eid = self.entity.eid
     for rdef, role in self.entity.e_schema.composite_rdef_roles:
         rtype = rdef.rtype.type
         target = getattr(rdef, neg_role(role))
         expr = ('C %s X' % rtype) if role == 'subject' else ('X %s C' %
                                                              rtype)
         self._cw.execute(
             'DELETE %s X WHERE C eid %%(c)s, %s' % (target, expr),
             {'c': eid})
Beispiel #4
0
 def add_hiddens(self, form, entity):
     """to ease overriding (see cubes.vcsfile.views.forms for instance)"""
     iid = 'rel-%s-%s-%s' % (self.peid, self.rtype, entity.eid)
     #  * str(self.rtype) in case it's a schema object
     #  * neged_role() since role is the for parent entity, we want the role
     #    of the inlined entity
     form.add_hidden(name=str(self.rtype),
                     value=self.peid,
                     role=neg_role(self.role),
                     eidparam=True,
                     id=iid)
Beispiel #5
0
 def parent(self):
     if needs_container_parent(self.entity.e_schema):
         parent = self.entity.container_parent
         return parent[0] if parent else None
     try:
         rdef = first_parent_rdef(self.entity.e_schema)
         rtype, role = rdef.rtype.type, neg_role(rdef.composite)
     except StopIteration:
         self.debug('ContainerProtocol.parent stopped on %s', self.entity)
         return None
     parent = self.entity.related(rtype=rtype, role=role, entities=True)
     if parent:
         return parent[0]
Beispiel #6
0
def iterrdefs(eschema, meta=True, final=True, skiprtypes=(), skipetypes=()):
    """ yield all the relation definitions of an entity type """
    for role in ('subject', 'object'):
        rschemas = eschema.subjrels if role == 'subject' else eschema.objrels
        for rschema in rschemas:
            if not meta and rschema.meta:
                continue
            if not final and rschema.final:
                continue
            if rschema in skiprtypes:
                continue
            for rdef in rschema.rdefs.itervalues():
                if getattr(rdef, neg_role(role)) in skipetypes:
                    continue
                if getattr(rdef, role) == eschema:
                    yield rdef
Beispiel #7
0
 def removejs(self):
     entity = self._entity()
     rdef = entity.e_schema.rdef(self.rtype, neg_role(self.role),
                                 self.petype)
     card = rdef.role_cardinality(self.role)
     # when one is adding an inline entity for a relation of a single card,
     # the 'add a new xxx' link disappears. If the user then cancel the addition,
     # we have to make this link appears back. This is done by giving add new link
     # id to removeInlineForm.
     if card == '?':
         divid = "addNew%s%s%s:%s" % (self.etype, self.rtype, self.role,
                                      self.peid)
         return "removeInlineForm('%%s', '%%s', '%s', '%%s', '%s')" % (
             self.role, divid)
     elif card in '+*':
         return "removeInlineForm('%%s', '%%s', '%s', '%%s')" % self.role
Beispiel #8
0
 def _init(self, sschema, rschema, oschema, role):
     if self.get(sschema, rschema, oschema, role) is None:
         rdef = rschema.rdef(sschema, oschema)
         if rschema.final:
             if rschema.meta or sschema.is_metadata(rschema) \
                     or oschema.type in ('Password', 'Bytes'):
                 section = 'hidden'
             else:
                 section = 'attributes'
         else:
             if rdef.role_cardinality(role) in '1+':
                 section = 'attributes'
             elif rdef.composite == neg_role(role):
                 section = 'relations'
             else:
                 section = 'sideboxes'
         self.tag_relation((sschema, rschema, oschema, role), section)
Beispiel #9
0
 def _prepare_form(self, entity, rschema, role, action):
     assert action in ('edit_rtype', 'edit_related', 'add',
                       'delete'), action
     if action == 'edit_rtype':
         return False, entity
     label = True
     if action in ('edit_related', 'delete'):
         edit_entity = entity.related(rschema, role).get_entity(0, 0)
     elif action == 'add':
         add_etype = self._compute_ttypes(rschema, role)[0]
         _new_entity = self._cw.vreg['etypes'].etype_class(add_etype)(
             self._cw)
         _new_entity.eid = next(self._cw.varmaker)
         edit_entity = _new_entity
         # XXX see forms.py ~ 276 and entities.linked_to method
         #     is there another way?
         self._cw.form['__linkto'] = '%s:%s:%s' % (rschema, entity.eid,
                                                   neg_role(role))
     assert edit_entity
     return label, edit_entity
Beispiel #10
0
 def linked_to(self):
     linked_to = {}
     # case where this is an embeded creation form
     try:
         eid = int(self.cw_extra_kwargs['peid'])
     except (KeyError, ValueError):
         # When parent is being created, its eid is not numeric (e.g. 'A')
         # hence ValueError.
         pass
     else:
         ltrtype = self.cw_extra_kwargs['rtype']
         ltrole = neg_role(self.cw_extra_kwargs['role'])
         linked_to[(ltrtype, ltrole)] = [eid]
     # now consider __linkto if the current form is the main form
     try:
         self.field_by_name('__maineid')
     except form.FieldNotFound:
         return linked_to
     for linkto in self._cw.list_form_param('__linkto'):
         ltrtype, eid, ltrole = linkto.split(':')
         linked_to.setdefault((ltrtype, ltrole), []).append(int(eid))
     return linked_to
Beispiel #11
0
    def render(self, form, field, renderer):
        stream = []
        w = stream.append
        req = form._cw
        _ = req._
        __ = _
        entity = form.edited_entity
        eid = entity.eid
        etype = entity.e_schema
        relative_url = '%s' % eid
        w(u'<div class="accordion form-relation" id="accordion_%s">' % eid)
        w_num_rel = 0
        for label, rschema, role in field.relations:
            # FIXME should be a more optimized way to get the name of
            # the target entity.
            targets = rschema.targets(etype, role)

            #----
            #    Agregar ciclo sobre targets
            #----
            for target in targets:
                if req.vreg.schema.eschema(target).has_perm(req, 'read'):
                    if w_num_rel == 0:
                        w(u'<div class="row-fluid">')
                    w_num_rel = w_num_rel + 1

                    linkto = '%s:%s:%s' % (rschema, eid, neg_role(role))
                    link_label = u'%s %s' % (req._('add'), req._(target))
                    lsearch = u'%s %s' % (req._('search'), req._(target))

                    relate_entity = (
                        u'<div class="relate-entity">%(relate_entity)s</div>' %
                        {
                            'relate_entity':
                            entity.view('autocomplete-edition-view',
                                        relation=rschema,
                                        role=role,
                                        etype_search=target,
                                        showname="E")
                        })

                    search_url = (
                        '<a href="?__mode=%(role)s:%(eid)s:%(rschema)s:'
                        '%(target)s&vid=search-associate"'
                        'class="btn btn-micro btn-link">'
                        '%(link_label)s'
                        '</a>' % {
                            'role': role,
                            'rschema': rschema,
                            'eid': eid,
                            'link_label': lsearch,
                            'target': target
                        })

                    add_new = (
                        '<a href="/add/%(target)s?__linkto=%(linkto)s'
                        '&__redirectpath=%(url)s&__redirectvid=edition "'
                        'class="btn btn-micro btn-link">'
                        '%(link_label)s'
                        '</a>' % {
                            'linkto': linkto,
                            'url': relative_url,
                            'link_label': link_label,
                            'target': target
                        })

                    w(
                        u'<div class="span4"><div class="accordion-group">'
                        u'<div class="accordion-heading container-fluid">'
                        u'    <div id="RDR_%(relation_name)s_%(role)s_%(target)s">'
                        u'        <a class="accordion-toggle" data-toggle="collapse" '
                        u'            data-parent="# accordion_%(eid)s" '
                        u'             href="#collapse_%(relation_name)s">'
                        u'             %(label)s'
                        u'        </a>'
                        u'    </div>'  # </div> de id_RDR..
                        u'    <div id="add-relation-combo">%(search)s %(add_new)s</div>'
                        u'</div>'  # </div> de accordion-heading
                        % {
                            'eid': eid,
                            'relation_name': rschema,
                            'target': target,
                            'label': label,
                            'search': search_url,
                            'add_new': add_new,
                            'role': role,
                            'relate-entity': relate_entity
                        })
                    w(u'<div id="collapse_%(relation)s" class="accordion-body collapse in">'
                      u'    <div class="accordion-inner">'
                      u'        <ul class="thumbnails">%(relate-entity)s' % {
                          'relation': rschema,
                          'relate-entity': relate_entity
                      })
                    #----
                    # Reemplazar los widgets desordenados de la vid=edition por tablas tipo any_rset
                    #----
                    if role == "subject":
                        subject_eid = eid
                        target_eid = 'eid-objeto'
                        rql = ('Any X,X WHERE X is %(target)s,Y is %(entity)s,'
                               ' Y %(relate)s X, Y eid %(eid)s ' % {
                                   'relate': rschema,
                                   'target': target,
                                   'entity': etype,
                                   'eid': eid
                               })
                    else:
                        subject_eid = 'eid-objeto'
                        target_eid = eid
                        rql = ('Any X,X WHERE X is %(target)s,Y is %(entity)s,'
                               ' X %(relate)s Y, Y eid %(eid)s' % {
                                   'relate': rschema,
                                   'target': target,
                                   'entity': etype,
                                   'eid': eid
                               })
                    rset = form._cw.execute(rql)
                    #----
                    #    Incluir el activador ([x]) de borrado de relaciones en la tabla preentada.
                    #        + cellvid redf-del-rel para el activador de borrado
                    #        + cellvid pending_del para que las relaciones seleccionadas se marquen  visualmente
                    #----
                    pending_deletes = get_pending_deletes(form._cw, eid)
                    ea_relation = rschema.type
                    param_but = '%s|%s|%s|%s|%s' % ('Y', eid, ea_relation,
                                                    role, str(pending_deletes))

                    kwargs = {
                        'ea_rel_entity': target,
                        'ea_relation': rschema,
                        'role': role,
                        'headers': (' '),
                        'cellvids': {
                            0: 'rdef-del-rel',
                            '_0': param_but
                        },
                        'limit': 10,
                        'rdefkwargs': {},
                        'title': u'no-widget-title',
                    }

                    w(form._cw.view('w-table', rset, 'null', **kwargs))
                    #----
                    w(u'    </div>'  # </div> de accordion-inner
                      u'</div></div>'  # </div> de accordion-body-collapse  -- </div> accordion-group
                      u'</div>')  # </div> de span4

                    if w_num_rel == 3:  # controlar el cambio de row de los widgets
                        w(u'</div>')
                        w_num_rel = 0
        if w_num_rel > 0:
            w(u'</div>')
        w(u'</div>' u'</div>')

        # FIXME try to change this table with a fancy html code.

        pendings = list(field.restore_pending_inserts(form))

        w(u'<table id="relatedEntities">')
        if not pendings:
            w(u'<tr><th>&#160;</th><td>&#160;</td></tr>')
        else:
            for row in pendings:
                # soon to be linked to entities
                w(u'<tr id="tr%s">' % row[1])
                w(u'<th>%s</th>' % row[3])
                w(u'<td>')
                w(u'<a class="handle" title="%s" href="%s">[x]</a>' %
                  (_('cancel this insert'), row[2]))
                w(u'<a id="a%s" class="editionPending" href="%s">%s</a>' %
                  (row[1], row[4], xml_escape(row[5])))
                w(u'</td>')
                w(u'</tr>')
        w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
        w(u'<th class="labelCol">')
        w(u'<select id="relationSelector_%s" tabindex="%s" '
          u'onchange="javascript:showMatchingSelect'
          u'(this.options[this.selectedIndex].value,%s);">' %
          (eid, req.next_tabindex(), xml_escape(json_dumps(eid))))
        w(u'<option value="">%s</option>' % _('select a relation'))
        for i18nrtype, rschema, role in field.relations:
            # more entities to link to
            w(u'<option value="%s_%s">%s</option>' %
              (rschema, role, i18nrtype))
        w(u'</select>')
        w(u'</th>')
        w(u'<td id="unrelatedDivs_%s"></td>' % eid)
        w(u'</tr>')
        w(u'</table>')
        return '\n'.join(stream)
Beispiel #12
0
def guess_field(eschema, rschema, role='subject', req=None, **kwargs):
    """This function return the most adapted field to edit the given relation
    (`rschema`) where the given entity type (`eschema`) is the subject or object
    (`role`).

    The field is initialized according to information found in the schema,
    though any value can be explicitly specified using `kwargs`.
    """
    fieldclass = None
    rdef = eschema.rdef(rschema, role)
    if role == 'subject':
        targetschema = rdef.object
        if rschema.final:
            if rdef.get('internationalizable'):
                kwargs.setdefault('internationalizable', True)
    else:
        targetschema = rdef.subject
    card = rdef.role_cardinality(role)
    composite = getattr(rdef, 'composite', None)
    kwargs['name'] = rschema.type
    kwargs['role'] = role
    kwargs['eidparam'] = True
    # don't mark composite relation as required, we want the composite element
    # to be removed when not linked to its parent
    kwargs.setdefault('required', card in '1+' and composite != neg_role(role))
    if role == 'object':
        kwargs.setdefault('label', (eschema.type, rschema.type + '_object'))
    else:
        kwargs.setdefault('label', (eschema.type, rschema.type))
    kwargs.setdefault('help', rdef.description)
    if rschema.final:
        fieldclass = kwargs.pop('fieldclass', FIELDS[targetschema])
        if issubclass(fieldclass, FileField):
            if req:
                aff_kwargs = req.vreg['uicfg'].select('autoform_field_kwargs',
                                                      req)
            else:
                aff_kwargs = _AFF_KWARGS
            for metadata in KNOWN_METAATTRIBUTES:
                metaschema = eschema.has_metadata(rschema, metadata)
                if metaschema is not None:
                    metakwargs = aff_kwargs.etype_get(eschema, metaschema,
                                                      'subject')
                    kwargs['%s_field' % metadata] = guess_field(eschema,
                                                                metaschema,
                                                                req=req,
                                                                **metakwargs)
        elif issubclass(fieldclass, StringField):
            if eschema.has_metadata(rschema, 'format'):
                # use RichTextField instead of StringField if the attribute has
                # a "format" metadata. But getting information from constraints
                # may be useful anyway...
                for cstr in rdef.constraints:
                    if isinstance(cstr, StaticVocabularyConstraint):
                        raise Exception(
                            'rich text field with static vocabulary')
                return RichTextField(**kwargs)
            # init StringField parameters according to constraints
            for cstr in rdef.constraints:
                if isinstance(cstr, StaticVocabularyConstraint):
                    kwargs.setdefault('choices', cstr.vocabulary)
                    break
            for cstr in rdef.constraints:
                if isinstance(cstr, SizeConstraint) and cstr.max is not None:
                    kwargs['max_length'] = cstr.max
        return fieldclass(**kwargs)
    else:
        fieldclass = kwargs.pop('fieldclass', RelationField)
        return fieldclass.fromcardinality(card, **kwargs)
Beispiel #13
0
 def _compute_ttypes(self, rschema, role):
     dual_role = neg_role(role)
     return getattr(rschema, '%ss' % dual_role)()