Projet

Général

Profil

0001-forms-recompute-prefills-on-live-changes-51330.patch

Frédéric Péters, 04 mars 2021 08:31

Télécharger (11,8 ko)

Voir les différences:

Subject: [PATCH 1/2] forms: recompute prefills on live changes (#51330)

 tests/backoffice_pages/test_submission.py | 41 ++++++++++++++++++---
 tests/form_pages/test_all.py              | 44 +++++++++++++++++++++--
 wcs/formdef.py                            |  2 +-
 wcs/forms/common.py                       | 23 ++++++++----
 wcs/forms/root.py                         |  8 +++--
 wcs/qommon/static/js/qommon.admin.js      |  4 +++
 wcs/qommon/static/js/qommon.forms.js      | 10 +++++-
 7 files changed, 114 insertions(+), 18 deletions(-)
tests/backoffice_pages/test_submission.py
1569 1569
    assert resp.form['f3'].value == random_user.email
1570 1570
    assert resp.form['f4'].value == random_user.email
1571 1571

  
1572
    live_url = resp.html.find('form').attrs['data-live-url']
1573
    live_resp = app.post(live_url, params=resp.form.submit_fields())
1574
    assert live_resp.json['result']['4']['content'] == random_user.email
1575

  
1576 1572
    resp.form['f4'] = 'altered value'  # alter value
1577 1573

  
1578 1574
    resp = resp.form.submit('submit')  # -> validation page
......
1580 1576
    assert 'altered value' not in resp
1581 1577

  
1582 1578

  
1579
def test_backoffice_submission_user_selection_then_live_prefill(pub):
1580
    user = create_user(pub)
1581

  
1582
    for i in range(10):
1583
        random_user = pub.user_class()
1584
        random_user.name = 'random user %s' % i
1585
        random_user.email = 'test%s@invalid' % i
1586
        random_user.store()
1587

  
1588
    FormDef.wipe()
1589
    formdef = FormDef()
1590
    formdef.name = 'form title'
1591
    formdef.fields = [
1592
        fields.PageField(id='0', label='1st page', type='page'),
1593
        fields.StringField(
1594
            id='3',
1595
            label='Field on 2nd page',
1596
            type='string',
1597
            varname='plop',
1598
            prefill={'type': 'user', 'value': 'email'},
1599
        ),
1600
    ]
1601
    formdef.backoffice_submission_roles = user.roles[:]
1602
    formdef.workflow_roles = {'_receiver': 1}
1603
    formdef.store()
1604

  
1605
    app = login(get_app(pub))
1606
    url = '/backoffice/submission/%s/' % formdef.url_name
1607
    resp = app.get(url)
1608

  
1609
    live_url = resp.html.find('form').attrs['data-live-url']
1610
    assert resp.pyquery('.submit-user-selection')
1611
    resp.form['user_id'] = str(random_user.id)  # happens via javascript
1612
    live_resp = app.post(live_url + '?modified_field_id=user', params=resp.form.submit_fields())
1613
    assert live_resp.json == {'result': {'3': {'visible': True, 'content': 'test9@invalid'}}}
1614

  
1615

  
1583 1616
def test_backoffice_submission_sidebar_lateral_block(pub):
1584 1617
    user = create_user(pub)
1585 1618

  
tests/form_pages/test_all.py
2936 2936

  
2937 2937
    resp = app.get('/test/')
2938 2938
    assert resp.form['f0'].value == ''
2939
    assert 'widget-prefilled' not in resp.text
2939
    # still marked with a css class, in case of live changes.
2940
    assert 'widget-prefilled' in resp.text
2940 2941

  
2941 2942

  
2942 2943
def test_form_page_session_var_prefill(pub):
......
7436 7437
    assert live_resp.json['result']['7']['content'] == '<p>bla bar bla</p>'
7437 7438

  
7438 7439

  
7440
def test_field_live_string_prefill(pub, http_requests):
7441
    FormDef.wipe()
7442
    formdef = FormDef()
7443
    formdef.name = 'Foo'
7444
    formdef.fields = [
7445
        fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
7446
        fields.StringField(
7447
            type='string',
7448
            id='2',
7449
            label='Bar2',
7450
            size='40',
7451
            required=True,
7452
            varname='bar2',
7453
            prefill={'type': 'string', 'value': '{{form_var_bar|default:""}}'},
7454
        ),
7455
    ]
7456
    formdef.store()
7457
    formdef.data_class().wipe()
7458

  
7459
    app = get_app(pub)
7460
    resp = app.get('/foo/')
7461
    assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
7462
    assert resp.pyquery('#var_bar2.widget-prefilled')  # second field is marked as prefilled
7463
    assert resp.form['f2'].value == ''
7464
    resp.form['f1'] = 'hello'
7465
    live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
7466
    assert live_resp.json['result']['2'] == {'visible': True, 'content': 'hello'}
7467

  
7468
    resp.form['f2'] = 'other'  # manually changed -> widget-prefilled class will be removed
7469
    resp.form['f1'] = 'xxx'
7470
    live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
7471
    assert live_resp.json['result']['2'] == {'visible': True}
7472

  
7473
    # check it's not possible to declare user change from frontoffice
7474
    live_resp = app.post('/foo/live?modified_field_id=user', params=resp.form.submit_fields(), status=403)
7475

  
7476

  
7439 7477
def test_form_edit_and_backoffice_field_change(pub):
7440 7478
    create_user(pub)
7441 7479

  
......
8394 8432
    assert 'f1' in resp.form.fields
8395 8433
    assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
8396 8434
    resp.form['f1'] = 'hello'
8397
    live_resp = app.post('/foo/live', params=resp.form.submit_fields())
8435
    live_resp = app.post('/foo/live?prefilled_2=on', params=resp.form.submit_fields())
8398 8436
    assert live_resp.json['result']['2']['content'] == 'bla hello bla'
8399 8437
    resp.form['f1'] = 'toto'
8400
    live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
8438
    live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
8401 8439
    assert live_resp.json['result']['2']['content'] == 'bla toto bla'
8402 8440

  
8403 8441

  
wcs/formdef.py
741 741
                    if not varname in live_condition_fields:
742 742
                        live_condition_fields[varname] = []
743 743
                    live_condition_fields[varname].append(field)
744
            if field.prefill and field.prefill.get('locked') and field.prefill.get('type') == 'string':
744
            if field.prefill and field.prefill.get('type') == 'string':
745 745
                for varname in field.get_referenced_varnames(
746 746
                    formdef=self, value=field.prefill.get('value', '')
747 747
                ):
wcs/forms/common.py
706 706
            for field in displayed_fields:
707 707
                if field.key == 'item' and field.display_mode == 'list' and field.varname:
708 708
                    modified_field_varnames.add(field.varname)
709
        elif get_request().form.get('modified_field_id') == 'user' and get_request().is_in_frontoffice():
710
            # not allowed in frontoffice.
711
            raise errors.AccessForbiddenError()
712
        elif get_request().form.get('modified_field_id') == 'user':
713
            # user selection in sidebar
714
            formdata.user_id = get_request().form.get('user_id')
709 715
        elif get_request().form.get('modified_field_id'):
710 716
            for field in displayed_fields:
711 717
                if field.id == get_request().form.get('modified_field_id'):
......
737 743
                continue
738 744
            if widget.field.key == 'comment':
739 745
                result[widget.field.id]['content'] = widget.content
740
            elif (
741
                widget.field.prefill
742
                and widget.field.prefill.get('locked')
743
                and widget.field.prefill.get('type') == 'string'
744
            ):
745
                value, locked = widget.field.get_prefill_value()
746
                result[widget.field.id]['content'] = value
746
            elif widget.field.prefill and widget.field.prefill.get('type') == 'string':
747
                update_prefill = bool('prefilled_%s' % widget.field.id in get_request().form)
748
                if update_prefill:
749
                    value, locked = widget.field.get_prefill_value()
750
                    result[widget.field.id]['content'] = value
751
            elif widget.field.prefill and widget.field.prefill.get('type') == 'user':
752
                update_prefill = bool(get_request().form.get('modified_field_id') == 'user')
753
                if update_prefill:
754
                    value, locked = widget.field.get_prefill_value(user=formdata.user)
755
                    result[widget.field.id]['content'] = value
747 756

  
748 757
        return json.dumps({'result': result})
749 758

  
wcs/forms/root.py
416 416
                    # turn off prefilling from geolocation attributes if
417 417
                    # the form is filled from the backoffice
418 418
                    v = None
419
                if v:
420
                    prefilled = True
419
                else:
420
                    if v:
421
                        prefilled = True
422
                    # always mark widget as prefilled, even for empty content,
423
                    # this will add a widget-prefilled CSS class that will be
424
                    # used for live prefill changes.
421 425
                    widget.prefilled = True
422 426

  
423 427
            if not prefilled and widget:
wcs/qommon/static/js/qommon.admin.js
163 163
      $('div.submit-user-selection select').select2(select2_options);
164 164
      $('div.submit-user-selection').show().find('select').on('change', function() {
165 165
        $('input[type=hidden][name=user_id]').val($(this).val());
166
        $('form[data-live-url]').trigger(
167
            'wcs:change',
168
            {modified_field: 'user', selected_user_id: $(this).val()}
169
        );
166 170
      });
167 171
    }
168 172

  
wcs/qommon/static/js/qommon.forms.js
291 291
    if (data && data.modified_field) {
292 292
      new_data += '&modified_field_id=' + data.modified_field;
293 293
    }
294
    $('.widget-prefilled').each(function(idx, elem) {
295
      new_data += '&prefilled_' + $(elem).data('field-id') + '=true';
296
    });
294 297
    var live_url = $(this).data('live-url');
295 298
    live_evaluation = $.ajax({
296 299
      type: 'POST',
......
355 358
              $widget.html(value.content);
356 359
            } else {
357 360
              // replace text input value
358
              $widget.find('input, textarea').val(value.content);
361
              if ($widget.is('.widget-prefilled') || $widget.is('.widget-readonly') || data.modified_field == 'user') {
362
                $widget.find('input, textarea').val(value.content);
363
              }
359 364
            }
360 365
          }
361 366
          if (value.source_url) {
......
375 380
    });
376 381
  }
377 382
  $('form div[data-live-source]').parents('form').trigger('wcs:change', {modified_field: 'init'});
383
  $('div.widget-prefilled').on('change input paste', function(ev) {
384
    $(this).removeClass('widget-prefilled');
385
  });
378 386

  
379 387
  /* searchable select */
380 388
  $('select[data-autocomplete]').each(function(i, elem) {
381
-