Projet

Général

Profil

0004-backoffice-sorting-on-a-field-of-block-field-46500.patch

Lauréline Guérin, 18 janvier 2022 09:46

Télécharger (6,82 ko)

Voir les différences:

Subject: [PATCH 4/4] backoffice: sorting on a field of block field (#46500)

 tests/backoffice_pages/test_columns.py | 72 ++++++++++++++++++++++++--
 wcs/forms/backoffice.py                | 31 ++++++++++-
 wcs/sql.py                             | 10 +++-
 3 files changed, 105 insertions(+), 8 deletions(-)
tests/backoffice_pages/test_columns.py
471 471
    data_class = formdef.data_class()
472 472
    data_class.wipe()
473 473

  
474
    formdata = data_class()
475
    formdata.data = {
474
    formdata1 = data_class()
475
    formdata1.data = {
476 476
        '8': {
477 477
            'data': [{'123': 'blah', '456': card.id, '456_display': card.default_digest}],
478 478
            'schema': {},  # not important here
479 479
        },
480 480
        '8_display': 'blah',
481 481
    }
482
    formdata.just_created()
483
    formdata.jump_status('new')
484
    formdata.store()
482
    formdata1.just_created()
483
    formdata1.jump_status('new')
484
    formdata1.store()
485 485

  
486 486
    app = login(get_app(pub))
487 487
    resp = app.get('/backoffice/management/form-title/')
......
504 504
    assert resp.text.count('<tr') == 2
505 505
    assert '<td>blah</td>' in resp
506 506
    assert '<td>Foo Bar</td>' in resp
507

  
508
    formdef.fields[0].max_items = 1
509
    formdef.store()
510

  
511
    card2 = carddef.data_class()()
512
    card2.data = {
513
        '1': 'Bar2',
514
        '2': 'Foo2',
515
    }
516
    card2.store()
517

  
518
    formdata2 = data_class()
519
    formdata2.data = {
520
        '8': {
521
            'data': [{'123': 'blah', '456': card2.id, '456_display': card2.default_digest}],
522
            'schema': {},  # not important here
523
        },
524
        '8_display': 'blah',
525
    }
526
    formdata2.just_created()
527
    formdata2.jump_status('new')
528
    formdata2.store()
529

  
530
    formdata3 = data_class()
531
    formdata3.data = {
532
        '8': {
533
            'data': [{'123': 'blah'}],
534
            'schema': {},  # not important here
535
        },
536
        '8_display': 'blah',
537
    }
538
    formdata3.just_created()
539
    formdata3.jump_status('new')
540
    formdata3.store()
541

  
542
    resp = app.get('/backoffice/management/form-title/')
543
    assert [x.text_content() for x in resp.pyquery('#columns-filter label')] == [
544
        'Number',
545
        'Created',
546
        'Last Modified',
547
        'User Label',
548
        'Status',
549
        'Block',
550
        'Block / Test',
551
        'Block / card field',
552
        'Anonymised',
553
    ]
554
    resp.forms['listing-settings']['8-123'].checked = True
555
    resp.forms['listing-settings']['8-456'].checked = True
556
    resp = resp.forms['listing-settings'].submit()
557
    assert '<th data-field-sort-key="f8-123"><span>Block / Test</span></th>' in resp
558
    assert '<th data-field-sort-key="f8-456"><span>Block / card field</span></th>' in resp
559
    assert resp.text.count('<tr') == 4
560

  
561
    # XXX ordering is done on card id, to be fixed with #60742
562
    resp = app.get('/backoffice/management/form-title/?order_by=f8-456')
563
    ids = [int(x.strip('/')) for x in re.findall(r'data-link="(.*?)"', resp.text)]
564
    assert ids == [formdata1.id, formdata2.id, formdata3.id]
565

  
566
    resp = app.get('/backoffice/management/form-title/?order_by=-f8-456')
567
    ids = [int(x.strip('/')) for x in re.findall(r'data-link="(.*?)"', resp.text)]
568
    assert ids == [formdata3.id, formdata2.id, formdata1.id]
wcs/forms/backoffice.py
111 111
                    field_sort_key = 'receipt_time'
112 112
                elif f.id in ('user-label', 'submission_agent'):
113 113
                    field_sort_key = None
114
            elif getattr(f, 'is_related_field', False) or getattr(f, 'block_field', None):
114
            elif getattr(f, 'is_related_field', False):
115
                field_sort_key = None
116
            elif getattr(f, 'block_field', None) and f.block_field.max_items != 1:
117
                # allow sorting on a field of block field if there is one item only
115 118
                field_sort_key = None
116 119
            else:
117 120
                field_sort_key = 'f%s' % f.contextual_id
......
213 216
        if order_by and not hasattr(formdata_class, 'get_sorted_ids'):
214 217
            # get_sorted_ids is only implemented in the SQL backend
215 218
            order_by = None
219

  
220
        def iter_fields(fields, block_field=None):
221
            for field in fields:
222
                field.contextual_id = field.id
223
                if block_field:
224
                    if field.key == 'items':
225
                        # not yet
226
                        continue
227
                    field.block_field = block_field
228
                    field.contextual_id = '%s-%s' % (field.block_field.id, field.id)
229
                yield field
230
                if field.key == 'block':
231
                    yield from iter_fields(field.block.fields, block_field=field)
232
                    continue
233

  
234
        direction = ''
235
        if order_by.startswith('-'):
236
            order_by = order_by[1:]
237
            direction = '-'
238
        for field in iter_fields(self.formdef.get_all_fields()):
239
            if getattr(field, 'block_field', None) and 'f%s' % field.contextual_id == order_by:
240
                # field of block field, sort on the first element
241
                order_by = "f%s->'data'->0->>'%s'" % (field.block_field.id, field.id)
242

  
243
        order_by = '%s%s' % (direction, order_by)
244

  
216 245
        if order_by and not anonymise:
217 246
            ordered_ids = formdata_class.get_sorted_ids(order_by, clause=criterias)
218 247
            item_ids_dict = {x: True for x in item_ids}
wcs/sql.py
1654 1654
        if order_by.startswith('-'):
1655 1655
            order_by = order_by[1:]
1656 1656
            direction = 'DESC'
1657
        order_by = order_by.replace('-', '_')
1657
        if '->' in order_by:
1658
            # sort on field of block field: f42->'data'->0->>'bf13e4d8a8-fb08-4808-b5ae-02d6247949b9'
1659
            parts = order_by.split('->')
1660
            order_by = '%s->%s' % (parts[0].replace('-', '_'), '->'.join(parts[1:]))
1661
        else:
1662
            order_by = order_by.replace('-', '_')
1658 1663

  
1659 1664
        fields = [x[0] for x in cls._table_static_fields] + cls.get_data_fields()
1660
        if order_by not in fields:
1665
        if order_by.split('->')[0] not in fields:
1666
            # for a sort on field of block field, just check the existence of the block field
1661 1667
            return ''
1662 1668

  
1663 1669
        return ' ORDER BY %s %s' % (order_by, direction)
1664
-