Projet

Général

Profil

0001-forms-add-post-conditions-to-page-fields-8962.patch

Frédéric Péters, 20 janvier 2016 18:43

Télécharger (8,57 ko)

Voir les différences:

Subject: [PATCH] forms: add post-conditions to page fields (#8962)

 wcs/fields.py      | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
 wcs/forms/root.py  | 27 +++++++++++++++++++++++++--
 wcs/qommon/form.py | 24 +++++++++++++++++++++---
 3 files changed, 92 insertions(+), 13 deletions(-)
wcs/fields.py
1257 1257
register_field_class(ItemsField)
1258 1258

  
1259 1259

  
1260

  
1261
class PostConditionsRowWidget(CompositeWidget):
1262
    def __init__(self, name, value=None, **kwargs):
1263
        CompositeWidget.__init__(self, name, value, **kwargs)
1264
        if not value:
1265
            value = {}
1266
        self.add(StringWidget, name='condition', title=_('Condition'),
1267
                value=value.get('condition'), size=50)
1268
        self.add(StringWidget, name='error_message', title=_('Error Message'),
1269
                value=value.get('error_message'), size=50)
1270

  
1271
    def _parse(self, request):
1272
        if self.get('condition') or self.get('error_message'):
1273
            self.value = {
1274
                'condition': self.get('condition'),
1275
                'error_message': self.get('error_message')
1276
            }
1277
        else:
1278
            self.value = None
1279

  
1280

  
1281
class PostConditionsTableWidget(WidgetListAsTable):
1282
    readonly = False
1283
    def __init__(self, name, **kwargs):
1284
        super(PostConditionsTableWidget, self).__init__(name,
1285
                element_type=PostConditionsRowWidget, **kwargs)
1286

  
1287

  
1260 1288
class PageField(Field):
1261 1289
    key = 'page'
1262 1290
    description = N_('New Page')
1263 1291

  
1264 1292
    condition = None
1293
    post_conditions = None
1265 1294

  
1266 1295
    def fill_admin_form(self, form):
1267 1296
        form.add(StringWidget, 'label', title = _('Label'), value = self.label,
1268 1297
                required = True, size = 50)
1269 1298
        form.add(StringWidget, 'condition', title = _('Condition'), value = self.condition,
1270 1299
                required = False, size = 50)
1300
        form.add(PostConditionsTableWidget, 'post_conditions',
1301
                title=_('Post Conditions'),
1302
                value=self.post_conditions,
1303
                advanced=not(self.post_conditions))
1271 1304

  
1272 1305
    def get_admin_attributes(self):
1273
        return Field.get_admin_attributes(self) + ['condition']
1306
        return Field.get_admin_attributes(self) + ['condition', 'post_conditions']
1274 1307

  
1275 1308
    def add_to_view_form(self, *args):
1276 1309
        pass
1277 1310

  
1278
    def is_visible(self, dict, formdef):
1279
        if dict is None:
1280
            return True
1281

  
1282
        if not self.condition:
1311
    def evaluate_condition(self, dict, formdef, condition):
1312
        if not condition:
1283 1313
            return True
1284 1314

  
1285 1315
        # create variables with values currently being evaluated, not yet
......
1301 1331
        data = get_publisher().substitutions.get_context_variables()
1302 1332

  
1303 1333
        try:
1304
            if eval(self.condition, get_publisher().get_global_eval_dict(), data):
1334
            if eval(condition, get_publisher().get_global_eval_dict(), data):
1305 1335
                return True
1306 1336
        except Exception, e:
1307 1337
            get_logger().warn('failed to evaluate condition "%s" (%r)' % (self.condition, e))
1308
            return True
1338
            raise RuntimeError()
1309 1339

  
1310 1340
        return False
1311 1341

  
1342
    def is_visible(self, dict, formdef):
1343
        if dict is None:
1344
            return True
1345
        try:
1346
            return self.evaluate_condition(dict, formdef, self.condition)
1347
        except RuntimeError:
1348
            return True
1349

  
1312 1350
register_field_class(PageField)
1313 1351

  
1314 1352

  
wcs/forms/root.py
330 330

  
331 331
        return self.page(0)
332 332

  
333
    def page(self, page_no, page_change=True, log_detail=None):
333
    def page(self, page_no, page_change=True, log_detail=None, page_error_messages=None):
334 334
        r = TemplateIO(html=True)
335 335
        displayed_fields = []
336 336

  
......
345 345
            self.feed_current_data(magictoken)
346 346

  
347 347
        form = self.formdef.create_form(page_no, displayed_fields)
348
        if page_error_messages:
349
            form.add_global_errors(page_error_messages)
348 350
        if getattr(session, 'ajax_form_token', None):
349 351
            form.add_hidden('_ajax_form_token', session.ajax_form_token)
350 352
        if get_request().is_in_backoffice():
......
661 663
                filled = self.save_draft(form_data, page_no)
662 664
                return redirect(filled.get_url().rstrip('/'))
663 665

  
666
            page_error_messages = []
667
            if form.get_submit() == 'submit':
668
                pages = [x for x in self.formdef.fields if x.type == 'page']
669
                try:
670
                    page = pages[page_no]
671
                    post_conditions = page.post_conditions or []
672
                except IndexError:
673
                    post_conditions = []
674
                form_data = session.get_by_magictoken(magictoken, {})
675
                for i, post_condition in enumerate(post_conditions):
676
                    condition = post_condition.get('condition')
677
                    error_message = post_condition.get('error_message')
678
                    try:
679
                        if not page.evaluate_condition(form_data, self.formdef, condition):
680
                            form.add(HiddenErrorWidget, 'post_condition%d' % i)
681
                            form.set_error('post_condition%d' % i, 'error')
682
                            page_error_messages.append(error_message)
683
                    except RuntimeError:
684
                        pass
685

  
664 686
            # form.get_submit() returns the name of the clicked button, and
665 687
            # it will return True if the form has been submitted, but not
666 688
            # by clicking on a submit widget; for example if an "add row"
......
671 693
                    # page hidden field had an error in its submission), in
672 694
                    # that case we just fall back to the first page.
673 695
                    page_no = 0
674
                return self.page(page_no, page_change=False)
696
                return self.page(page_no, page_change=False,
697
                        page_error_messages=page_error_messages)
675 698

  
676 699
            form_data = session.get_by_magictoken(magictoken, {})
677 700
            data = self.formdef.get_data(form)
wcs/qommon/form.py
261 261
        if kwargs.get('advanced_label'):
262 262
            self.advanced_label = kwargs.pop('advanced_label')
263 263
        QuixoteForm.__init__(self, *args, **kwargs)
264
        self.global_error_messages = None
264 265

  
265 266
    def keep_referer(self):
266 267
        self.add(HiddenWidget, '__keep_referer',
......
297 298
            l.append(self.captcha)
298 299
        return l
299 300

  
301
    def add_global_errors(self, error_messages):
302
        self.global_error_messages = error_messages
303

  
300 304
    def _get_default_action(self):
301 305
        if get_request().get_header('x-popup') == 'true':
302 306
            # do not leave action empty for popups, as they get embedded into
......
331 335
        return htmltext('<div class="infonotice">%s</div>' % _(self.info))
332 336

  
333 337
    def _render_error_notice(self):
334
        return htmltext('<div class="errornotice">%s</div>' % _(
335
                    QuixoteForm._render_error_notice(self)))
338
        errors = []
339
        if self.has_errors():
340
            errors.append(_(QuixoteForm._render_error_notice(self)))
341
        if self.global_error_messages:
342
            errors.extend(self.global_error_messages)
343
        t = TemplateIO(html=True)
344
        t += htmltext('<div class="errornotice">')
345
        for error in errors:
346
            t += htmltext('<p>%s</p>') % error
347
        t += htmltext('</div>')
348
        return t.getvalue()
336 349

  
337 350
    def _render_body(self):
338 351
        r = TemplateIO(html=True)
339
        if self.has_errors():
352
        if self.has_errors() or self.global_error_messages:
340 353
            r += self._render_error_notice()
341 354
        if self.info:
342 355
            r += self._render_info_notice()
......
2086 2099
    def _parse(self, request):
2087 2100
        CompositeWidget._parse(self, request)
2088 2101
        self.value = self.get('latlng')
2102

  
2103

  
2104
class HiddenErrorWidget(HiddenWidget):
2105
    def set_error(self, error):
2106
        Widget.set_error(self, error)
2089
-