'
+ """
+ eid = self.edited_entity.eid
+ cell = cell and "div_insert_" or "tr"
+ pending_inserts = set(self.req.get_pending_inserts(eid))
+ for pendingid in pending_inserts:
+ eidfrom, rtype, eidto = pendingid.split(':')
+ if typed_eid(eidfrom) == eid: # subject
+ label = display_name(self.req, rtype, 'subject')
+ reid = eidto
+ else:
+ label = display_name(self.req, rtype, 'object')
+ reid = eidfrom
+ jscall = "javascript: cancelPendingInsert('%s', '%s', null, %s);" \
+ % (pendingid, cell, eid)
+ rset = self.req.eid_rset(reid)
+ eview = self.view('text', rset, row=0)
+ # XXX find a clean way to handle baskets
+ if rset.description[0][0] == 'Basket':
+ eview = '%s (%s)' % (eview, display_name(self.req, 'Basket'))
+ yield rtype, pendingid, jscall, label, reid, eview
+
+ # should_* method extracted to allow overriding
+
+ def should_inline_relation_form(self, rschema, targettype, role):
+ """return true if the given relation with entity has role and a
+ targettype target should be inlined
+ """
+ return self.inlined.etype_rtag(self.edited_entity.id, role, rschema, targettype)
+
+ def should_display_inline_creation_form(self, rschema, existant, card):
+ """return true if a creation form should be inlined
+
+ by default true if there is no related entity and we need at least one
+ """
+ return not existant and card in '1+'
+
+ def should_display_add_new_relation_link(self, rschema, existant, card):
+ """return true if we should add a link to add a new creation form
+ (through ajax call)
+
+ by default true if there is no related entity or if the relation has
+ multiple cardinality
+ """
+ return not existant or card in '+*'
+
+
+class EditionFormView(EntityView):
+ """display primary entity edition form"""
id = 'edition'
- __select__ = one_line_rset() & non_final_entity()
+ # add yes() so it takes precedence over deprecated views in baseforms,
+ # though not baseforms based customized view
+ __select__ = one_line_rset() & non_final_entity() & yes()
title = _('edition')
controller = 'edit'
- skip_relations = FormMixIn.skip_relations.copy()
-
+
def cell_call(self, row, col, **kwargs):
- self.req.add_js( ('cubicweb.ajax.js',) )
- self.initialize_varmaker()
entity = self.complete_entity(row, col)
+ self.render_form(entity)
+
+ def render_form(self, entity):
+ """fetch and render the form"""
+ self.form_title(entity)
+ form = self.vreg.select_object('forms', 'edition', self.req, self.rset,
+ row=self.row, col=self.col, entity=entity,
+ domid=self.id, submitmsg=self.submited_message())
+ self.init_form(form, entity)
+ self.w(form.form_render(renderer=EntityFormRenderer(), formvid=u'edition'))
- def initialize_varmaker(self):
- varmaker = self.req.get_page_data('rql_varmaker')
- if varmaker is None:
- varmaker = self.req.varmaker
- self.req.set_page_data('rql_varmaker', varmaker)
- self.varmaker = varmaker
+ def init_form(self, form, entity):
+ """customize your form before rendering here"""
+ form.form_add_hidden(u'__maineid', entity.eid)
+
+ def form_title(self, entity):
+ """the form view title"""
+ ptitle = self.req._(self.title)
+ self.w(u'%s %s
' % (
+ entity.dc_type(), ptitle and '(%s)' % ptitle))
+
+ def submited_message(self):
+ """return the message that will be displayed on successful edition"""
+ return self.req._('entity edited')
+
- def edit_form(self, entity, kwargs):
- form = EntityFieldsForm(self.req, entity=entity)
- for rschema, target in self.editable_attributes(entity):
- field = guess_field(entity.__class__, entity.e_schema, rschema, target)
- form.fields.append(field)
- form.buttons.append(form.button_ok())
- form.buttons.append(form.button_apply())
- form.buttons.append(form.button_cancel())
- self.w(form.form_render())
+class CreationFormView(EditionFormView):
+ """display primary entity creation form"""
+ id = 'creation'
+ __select__ = specified_etype_implements('Any') & yes()
+
+ title = _('creation')
+
+ def call(self, **kwargs):
+ """creation view for an entity"""
+ etype = kwargs.pop('etype', self.req.form.get('etype'))
+ try:
+ entity = self.vreg.etype_class(etype)(self.req, None, None)
+ except:
+ self.w(self.req._('no such entity type %s') % etype)
+ else:
+ self.initialize_varmaker()
+ entity.eid = self.varmaker.next()
+ self.render_form(entity)
+
+ def form_title(self, entity):
+ """the form view title"""
+ if '__linkto' in self.req.form:
+ if isinstance(self.req.form['__linkto'], list):
+ # XXX which one should be considered (case: add a ticket to a
+ # version in jpl)
+ rtype, linkto_eid, role = self.req.form['__linkto'][0].split(':')
+ else:
+ rtype, linkto_eid, role = self.req.form['__linkto'].split(':')
+ linkto_rset = self.req.eid_rset(linkto_eid)
+ linkto_type = linkto_rset.description[0][0]
+ if role == 'subject':
+ title = self.req.__('creating %s (%s %s %s %%(linkto)s)' % (
+ entity.e_schema, entity.e_schema, rtype, linkto_type))
+ else:
+ title = self.req.__('creating %s (%s %%(linkto)s %s %s)' % (
+ entity.e_schema, linkto_type, rtype, entity.e_schema))
+ msg = title % {'linkto' : self.view('incontext', linkto_rset)}
+ self.w(u'%s
' % msg)
+ else:
+ super(CreationFormView, self).form_title(entity)
+
+ def url(self):
+ """return the url associated with this view"""
+ return self.create_url(self.req.form.get('etype'))
+
+ def submited_message(self):
+ """return the message that will be displayed on successful edition"""
+ return self.req._('entity created')
+
+
+class CopyFormView(EditionFormView):
+ """display primary entity creation form initialized with values from another
+ entity
+ """
+ id = 'copy'
+ def render_form(self, entity):
+ """fetch and render the form"""
+ # make a copy of entity to avoid altering the entity in the
+ # request's cache.
+ self.newentity = copy(entity)
+ self.copying = self.newentity.eid
+ self.newentity.eid = None
+ self.w(u'\n'
+ % self.req._('Please note that this is only a shallow copy'))
+ super(CopyFormView, self).render_form(entity)
+ del self.newentity
+
+ def init_form(self, form, entity):
+ """customize your form before rendering here"""
+ super(CopyFormView, self).init_form(form, entity)
+ if entity.eid == self.newentity.eid:
+ form.form_add_hidden('__cloned_eid', self.copying, eidparam=True)
+
+ def submited_message(self):
+ """return the message that will be displayed on successful edition"""
+ return self.req._('entity copied')
+
+
+class TableEditForm(CompositeForm):
+ id = 'muledit'
+ onsubmit = "return validateForm('entityForm', null);"
+
+ def __init__(self, *args, **kwargs):
+ super(TableEditForm, self).__init__(*args, **kwargs)
+ for row in xrange(len(self.rset)):
+ form = self.vreg.select_object('forms', 'edition', self.req, self.rset,
+ row=row, domid=self.id,
+ attrcategories=('primary',),
+ set_error_url=False)
+ # XXX rely on the MultipleEntityFormRenderer to put the eid input
+ form.remove_field(form.field_by_name('eid'))
+ self.form_add_subform(form)
- def editable_attributes(self, entity):
- # XXX both (add, delete)
- return [(rschema, x) for rschema, _, x in entity.relations_by_category(('primary', 'secondary'), 'add')
- if rschema != 'eid']
+ def form_buttons(self):
+ """return the form's buttons (as string)"""
+ okt = self.req._('validate modifications on selected items').capitalize()
+ resett = self.req._('revert changes').capitalize()
+ return [self.button_ok(title=okt), self.button_reset(title=resett)]
+
+
+class TableEditFormView(EntityView):
+ id = 'muledit'
+ __select__ = EntityView.__select__ & yes()
+ title = _('multiple edit')
+
+ def call(self, **kwargs):
+ """a view to edit multiple entities of the same type the first column
+ should be the eid
+ """
+ #self.form_title(entity)
+ form = self.vreg.select_object('forms', self.id, self.req, self.rset,
+ domid=self.id)
+ self.w(form.form_render(renderer=EntityCompositeFormRenderer()))
+
+
+class InlineEntityEditionFormView(EntityView):
+ id = 'inline-edition'
+ __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
+ removejs = "removeInlinedEntity('%s', '%s', '%s')"
+
+ def call(self, **kwargs):
+ """redefine default call() method to avoid automatic
+ insertions of between each row of
+ the resultset
+ """
+ rset = self.rset
+ for i in xrange(len(rset)):
+ self.wview(self.id, rset, row=i, **kwargs)
+
+ def cell_call(self, row, col, peid, rtype, role='subject', **kwargs):
+ """
+ :param peid: the parent entity's eid hosting the inline form
+ :param rtype: the relation bridging `etype` and `peid`
+ :param role: the role played by the `peid` in the relation
+ """
+ entity = self.entity(row, col)
+ divonclick = "restoreInlinedEntity('%s', '%s', '%s')" % (peid, rtype,
+ entity.eid)
+ self.render_form(entity, peid, rtype, role, divonclick=divonclick)
+
+ def render_form(self, entity, peid, rtype, role, **kwargs):
+ """fetch and render the form"""
+ rschema = self.schema.rschema(rtype)
+ divid = '%s-%s-%s' % (peid, rtype, entity.eid)
+ title = rschema.display_name(self.req, role)
+ form = self.vreg.select_object('forms', 'edition', self.req,
+ entity=entity)
+ removejs = self.removejs % (peid, rtype,entity.eid)
+ if self.keep_entity(entity, peid, rtype):
+ if entity.has_eid():
+ rval = entity.eid
+ else:
+ rval = INTERNAL_FIELD_VALUE
+ form.form_add_hidden('edit%s-%s:%s' % (role[0], rtype, peid), rval)
+ form.form_add_hidden(name='%s:%s' % (rtype, peid), value=entity.eid,
+ id='rel-%s-%s-%s' % (peid, rtype, entity.eid))
+ self.w(form.form_render(renderer=EntityInlinedFormRenderer(), divid=divid,
+ title=title, removejs=removejs,**kwargs))
+
+ def keep_entity(self, entity, peid, rtype):
+ if not entity.has_eid():
+ return True
+ # are we regenerating form because of a validation error ?
+ erroneous_post = self.req.data.get('formvalues')
+ if erroneous_post:
+ cdvalues = self.req.list_form_param('%s:%s' % (rtype, peid),
+ erroneous_post)
+ if unicode(entity.eid) not in cdvalues:
+ return False
+ return True
+
+
+class InlineEntityCreationFormView(InlineEntityEditionFormView):
+ id = 'inline-creation'
+ __select__ = (match_kwargs('peid', 'rtype')
+ & specified_etype_implements('Any'))
+
+ def call(self, etype, peid, rtype, role='subject', **kwargs):
+ """
+ :param etype: the entity type being created in the inline form
+ :param peid: the parent entity's eid hosting the inline form
+ :param rtype: the relation bridging `etype` and `peid`
+ :param role: the role played by the `peid` in the relation
+ """
+ try:
+ entity = self.vreg.etype_class(etype)(self.req, None, None)
+ except:
+ self.w(self.req._('no such entity type %s') % etype)
+ return
+ self.initialize_varmaker()
+ entity.eid = self.varmaker.next()
+ self.render_form(entity, peid, rtype, role)