merge
authorFlorent <florent@secondweb.fr>
Thu, 30 Jul 2009 22:36:01 +0200
changeset 2581 2833df289165
parent 2580 6e9453fd11ef (current diff)
parent 2578 b717ebef04d8 (diff)
child 2582 504ac00ff33b
merge
--- a/misc/migration/bootstrapmigration_repository.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/misc/migration/bootstrapmigration_repository.py	Thu Jul 30 22:36:01 2009 +0200
@@ -29,6 +29,7 @@
     isession.commit()
     repo.hm.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '')
     repo.hm.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
+    session.set_shared_data('do-not-insert-cwuri', False)
 
 if applcubicwebversion < (3, 2, 2) and cubicwebversion >= (3, 2, 1):
     from base64 import b64encode
--- a/sobjects/notification.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/sobjects/notification.py	Thu Jul 30 22:36:01 2009 +0200
@@ -62,7 +62,7 @@
 class RenderAndSendNotificationView(PreCommitOperation):
     """delay rendering of notification view until precommit"""
     def precommit_event(self):
-        if self.view.rset[0][0] in self.session.transaction_data.get('pendingeids', ()):
+        if self.view.rset and self.view.rset[0][0] in self.session.transaction_data.get('pendingeids', ()):
             return # entity added and deleted in the same transaction
         self.view.render_and_send(**getattr(self, 'viewargs', {}))
 
@@ -133,6 +133,8 @@
     * set a content attribute to define the content of the email (unless you
       override call)
     """
+    # XXX refactor this class to work with len(rset) > 1
+
     msgid_timestamp = True
 
     def recipients(self):
@@ -141,7 +143,7 @@
         return finder.recipients()
 
     def subject(self):
-        entity = self.entity(0, 0)
+        entity = self.entity(self.row or 0, self.col or 0)
         subject = self.req._(self.message)
         etype = entity.dc_type()
         eid = entity.eid
@@ -154,7 +156,7 @@
         return self.req.actual_session().user.login
 
     def context(self, **kwargs):
-        entity = self.entity(0, 0)
+        entity = self.entity(self.row or 0, self.col or 0)
         for key, val in kwargs.iteritems():
             if val and isinstance(val, unicode) and val.strip():
                kwargs[key] = self.req._(val)
@@ -184,15 +186,19 @@
                  DeprecationWarning, stacklevel=1)
             lang = self.vreg.property_value('ui.language')
             recipients = zip(recipients, repeat(lang))
-        entity = self.entity(0, 0)
-        # if the view is using timestamp in message ids, no way to reference
-        # previous email
-        if not self.msgid_timestamp:
-            refs = [self.construct_message_id(eid)
-                    for eid in entity.notification_references(self)]
+        if self.rset is not None:
+            entity = self.entity(self.row or 0, self.col or 0)
+            # if the view is using timestamp in message ids, no way to reference
+            # previous email
+            if not self.msgid_timestamp:
+                refs = [self.construct_message_id(eid)
+                        for eid in entity.notification_references(self)]
+            else:
+                refs = ()
+            msgid = self.construct_message_id(entity.eid)
         else:
             refs = ()
-        msgid = self.construct_message_id(entity.eid)
+            msgid = None
         userdata = self.req.user_data()
         origlang = self.req.lang
         for emailaddr, lang in recipients:
@@ -278,7 +284,7 @@
 """
 
     def context(self, **kwargs):
-        entity = self.entity(0, 0)
+        entity = self.entity(self.row or 0, self.col or 0)
         content = entity.printable_value(self.content_attr, format='text/plain')
         if content:
             contentformat = getattr(entity, self.content_attr + '_format', 'text/rest')
@@ -286,7 +292,7 @@
         return super(ContentAddedView, self).context(content=content, **kwargs)
 
     def subject(self):
-        entity = self.entity(0, 0)
+        entity = self.entity(self.row or 0, self.col or 0)
         return  u'%s #%s (%s)' % (self.req.__('New %s' % entity.e_schema),
                                   entity.eid, self.user_login())
 
--- a/web/formfields.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/web/formfields.py	Thu Jul 30 22:36:01 2009 +0200
@@ -480,7 +480,7 @@
 
     def subfields(self, form):
         return self.fields
-    
+
     def actual_fields(self, form):
         return [self] + list(self.fields)
 
--- a/web/views/editforms.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/web/views/editforms.py	Thu Jul 30 22:36:01 2009 +0200
@@ -43,7 +43,31 @@
         js, nodeid, label)
 
 
-class DeleteConfForm(FormViewMixIn, EntityView):
+class DeleteConfForm(forms.CompositeForm):
+    id = 'deleteconf'
+    __select__ = non_final_entity()
+
+    domid = 'deleteconf'
+    copy_nav_params = True
+    form_buttons = [Button(stdmsgs.YES, cwaction='delete'),
+                    Button(stdmsgs.NO, cwaction='cancel')]
+    @property
+    def action(self):
+        return self.build_url('edit')
+
+    def __init__(self, *args, **kwargs):
+        super(DeleteConfForm, self).__init__(*args, **kwargs)
+        done = set()
+        for entity in self.rset.entities():
+            if entity.eid in done:
+                continue
+            done.add(entity.eid)
+            subform = self.vreg.select('forms', 'base', self.req, entity=entity,
+                                       mainform=False)
+            self.form_add_subform(subform)
+
+
+class DeleteConfFormView(FormViewMixIn, EntityView):
     """form used to confirm deletion of some entities"""
     id = 'deleteconf'
     title = _('delete')
@@ -59,20 +83,10 @@
           % _('this action is not reversible!'))
         # XXX above message should have style of a warning
         w(u'<h4>%s</h4>\n' % _('Do you want to delete the following element(s) ?'))
-        form = self.vreg.select('forms', 'composite', req, domid='deleteconf',
-                                copy_nav_params=True,
-                                action=self.build_url('edit'), onsubmit=onsubmit,
-                                form_buttons=[Button(stdmsgs.YES, cwaction='delete'),
-                                              Button(stdmsgs.NO, cwaction='cancel')])
-        done = set()
+        form = self.vreg.select('forms', self.id, req, rset=self.rset,
+                                onsubmit=onsubmit)
         w(u'<ul>\n')
         for entity in self.rset.entities():
-            if entity.eid in done:
-                continue
-            done.add(entity.eid)
-            subform = self.vreg.select('forms', 'base', req, entity=entity,
-                                       mainform=False)
-            form.form_add_subform(subform)
             # don't use outofcontext view or any other that may contain inline edition form
             w(u'<li>%s</li>' % tags.a(entity.view('textoutofcontext'),
                                       href=entity.absolute_url()))
--- a/web/views/formrenderers.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/web/views/formrenderers.py	Thu Jul 30 22:36:01 2009 +0200
@@ -193,7 +193,16 @@
         byfieldset = {}
         for field in fields:
             byfieldset.setdefault(field.fieldset, []).append(field)
-        for fieldset, fields in byfieldset.iteritems():
+        if form.fieldsets_in_order:
+            fieldsets = form.fieldsets_in_order
+        else:
+            fieldsets = byfieldset.keys()
+        for fieldset in fieldsets:
+            try:
+                fields = byfieldset.pop(fieldset)
+            except KeyError:
+                self.warning('no such fieldset: %s (%s)', fieldset, form)
+                continue
             w(u'<fieldset class="%s">' % (fieldset or u'default'))
             if fieldset:
                 w(u'<legend>%s</legend>' % self.req._(fieldset))
@@ -213,6 +222,8 @@
                     w(self.render_help(form, field))
                 w(u'</td></tr>')
             w(u'</table></fieldset>')
+        if byfieldset:
+            self.warning('unused fieldsets: %s', ', '.join(byfieldset))
 
     def render_buttons(self, w, form):
         if not form.form_buttons:
@@ -295,22 +306,29 @@
     """specific renderer for multiple entities edition form (muledit)"""
     id = 'composite'
 
+    _main_display_fields = None
+
     def render_fields(self, w, form, values):
         if not form.is_subform:
             w(u'<table class="listing">')
         super(EntityCompositeFormRenderer, self).render_fields(w, form, values)
         if not form.is_subform:
             w(u'</table>')
+            if self._main_display_fields:
+                super(EntityCompositeFormRenderer, self)._render_fields(
+                    self._main_display_fields, w, form)
 
     def _render_fields(self, fields, w, form):
         if form.is_subform:
             entity = form.edited_entity
             values = form.form_previous_values
             qeid = eid_param('eid', entity.eid)
-            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % xml_escape(dumps(entity.eid))
+            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % \
+                         xml_escape(dumps(entity.eid))
             w(u'<tr class="%s">' % (entity.row % 2 and u'even' or u'odd'))
             # XXX turn this into a widget used on the eid field
-            w(u'<td>%s</td>' % checkbox('eid', entity.eid, checked=qeid in values))
+            w(u'<td>%s</td>' % checkbox('eid', entity.eid,
+                                        checked=qeid in values))
             for field in fields:
                 error = form.form_field_error(field)
                 if error:
@@ -318,22 +336,29 @@
                     w(error)
                 else:
                     w(u'<td>')
-                if isinstance(field.widget, (fwdgs.Select, fwdgs.CheckBox, fwdgs.Radio)):
+                if isinstance(field.widget, (fwdgs.Select, fwdgs.CheckBox,
+                                             fwdgs.Radio)):
                     field.widget.attrs['onchange'] = cbsetstate
                 elif isinstance(field.widget, fwdgs.Input):
                     field.widget.attrs['onkeypress'] = cbsetstate
+                # XXX else
                 w(u'<div>%s</div>' % field.render(form, self))
-                w(u'</td>')
+                w(u'</td></tr>')
         else:
-            # main form, display table headers
-            w(u'<tr class="header">')
-            w(u'<th align="left">%s</th>'
-              % tags.input(type='checkbox', title=self.req._('toggle check boxes'),
-                           onclick="setCheckboxesState('eid', this.checked)"))
-            for field in self.forms[0].fields:
-                if self.display_field(form, field) and field.is_visible():
+            self._main_display_fields = fields
+            subfields = [field for field in form.forms[0].fields
+                         if self.display_field(form, field)
+                         and field.is_visible()]
+            if subfields:
+                # main form, display table headers
+                w(u'<tr class="header">')
+                w(u'<th align="left">%s</th>' %
+                  tags.input(type='checkbox',
+                             title=self.req._('toggle check boxes'),
+                             onclick="setCheckboxesState('eid', this.checked)"))
+                for field in subfields:
                     w(u'<th>%s</th>' % self.req._(field.label))
-        w(u'</tr>')
+                w(u'</tr>')
 
 
 class EntityFormRenderer(EntityBaseFormRenderer):
--- a/web/views/forms.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/web/views/forms.py	Thu Jul 30 22:36:01 2009 +0200
@@ -20,16 +20,49 @@
 
 
 class FieldsForm(form.Form):
+    """base class for fields based forms.
+
+    The following attributes may be either set on subclasses or given on
+    form selection to customize the generated form:
+
+    * `needs_js`: sequence of javascript files that should be added to handle
+      this form (through `req.add_js`)
+
+    * `needs_css`: sequence of css files that should be added to handle this
+      form (through `req.add_css`)
+
+    * `domid`: value for the "id" attribute of the <form> tag
+
+    * `action`: value for the "action" attribute of the <form> tag
+
+    * `onsubmit`: value for the "onsubmit" attribute of the <form> tag
+
+    * `cssclass`: value for the "class" attribute of the <form> tag
+
+    * `cssstyle`: value for the "style" attribute of the <form> tag
+
+    * `cwtarget`: value for the "cubicweb:target" attribute of the <form> tag
+
+    * `redirect_path`: relative to redirect to after submitting the form
+
+    * `copy_nav_params`: flag telling if navigation paramenters should be copied
+      back in hidden input
+
+    * `form_buttons`:  form buttons sequence (button widgets instances)
+
+    * `form_renderer_id`: id of the form renderer to use to render the form
+
+    * `fieldsets_in_order`: fieldset name sequence, to control order
+    """
     id = 'base'
 
     is_subform = False
+    internal_fields = ('__errorurl',) + NAV_FORM_PARAMETERS
 
-    # attributes overrideable through __init__
-    internal_fields = ('__errorurl',) + NAV_FORM_PARAMETERS
+    # attributes overrideable by subclasses or through __init__
     needs_js = ('cubicweb.ajax.js', 'cubicweb.edition.js',)
     needs_css = ('cubicweb.form.css',)
     domid = 'form'
-    title = None
     action = None
     onsubmit = "return freezeFormButtons('%(domid)s');"
     cssclass = None
@@ -37,8 +70,9 @@
     cwtarget = None
     redirect_path = None
     copy_nav_params = False
-    form_buttons = None # form buttons (button widgets instances)
+    form_buttons = None
     form_renderer_id = 'default'
+    fieldsets_in_order = None
 
     def __init__(self, req, rset=None, row=None, col=None,
                  submitmsg=None, mainform=True,
--- a/web/views/magicsearch.py	Thu Jul 30 22:33:46 2009 +0200
+++ b/web/views/magicsearch.py	Thu Jul 30 22:36:01 2009 +0200
@@ -170,10 +170,7 @@
     """
     priority = 2
     def preprocess_query(self, uquery, req):
-        try:
-            rqlst = parse(uquery, print_errors=False)
-        except (RQLSyntaxError, BadRQLQuery), err:
-            return uquery,
+        rqlst = parse(uquery, print_errors=False)
         schema = self.vreg.schema
         # rql syntax tree will be modified in place if necessary
         translate_rql_tree(rqlst, trmap(self.config, schema, req.lang), schema)
@@ -204,7 +201,7 @@
             elif len(words) == 3:
                 args = self._three_words_query(*words)
             else:
-                args = self._multiple_words_query(words)
+                raise
         return args
 
     def _get_entity_type(self, word):
@@ -291,11 +288,6 @@
                                   self._complete_rql(word3, etype, searchattr=rtype))
         return rql, {'text': word3}
 
-    def _multiple_words_query(self, words):
-        """specific process for more than 3 words query"""
-        return ' '.join(words),
-
-
     def _expand_shortcut(self, etype, rtype, searchstr):
         """Expands shortcut queries on a non final relation to use has_text or
         the main attribute (according to possible entity type) if '%' is used in the