Projet

Général

Profil

0002-backoffice-add-tracing-information-to-inspect-page-5.patch

Frédéric Péters, 14 juin 2021 16:01

Télécharger (8,91 ko)

Voir les différences:

Subject: [PATCH 2/2] backoffice: add tracing information to inspect page
 (#54497)

 tests/backoffice_pages/test_all.py   | 24 ++++++++++
 wcs/backoffice/management.py         | 69 +++++++++++++++++++++++++++-
 wcs/qommon/static/css/dc2/admin.scss | 18 ++++++++
 wcs/workflows.py                     | 29 +++++++++++-
 4 files changed, 138 insertions(+), 2 deletions(-)
tests/backoffice_pages/test_all.py
5022 5022
    )
5023 5023

  
5024 5024

  
5025
def test_inspect_page_actions_traces(pub):
5026
    create_environment(pub)
5027
    create_user(pub, is_admin=True)
5028

  
5029
    formdef = FormDef.get_by_urlname('form-title')
5030

  
5031
    formdef.data_class().wipe()
5032
    formdata = formdef.data_class()()
5033
    formdata.data = {}
5034
    formdata.just_created()
5035
    formdata.perform_workflow()
5036
    formdata.store()
5037

  
5038
    resp = login(get_app(pub)).get(formdata.get_url(backoffice=True), status=200)
5039
    resp = resp.click('Data Inspector')
5040
    assert '<h2>Actions Tracing</h2>' in resp
5041
    assert [x.text for x in resp.pyquery('#inspect-timeline strong')] == ['Just Submitted', 'New']
5042
    assert [x.text for x in resp.pyquery('#inspect-timeline a.tracing-link') if x.text] == [
5043
        'Email',
5044
        'Email',
5045
        'Automatic Jump',
5046
    ]
5047

  
5048

  
5025 5049
def test_workflow_jump_previous(pub):
5026 5050
    user = create_user(pub)
5027 5051
    create_environment(pub)
wcs/backoffice/management.py
42 42
from wcs.forms.common import FormStatusPage
43 43
from wcs.roles import logged_users_role
44 44
from wcs.variables import LazyFieldVar
45
from wcs.workflows import WorkflowStatusItem, template_on_formdata
45
from wcs.workflows import ActionsTracingEvolutionPart, WorkflowStatusItem, item_classes, template_on_formdata
46 46

  
47 47
from ..qommon import _, emails, errors, ezt, force_str, get_cfg, get_logger, misc, ngettext, ods, sms
48 48
from ..qommon.admin.emails import EmailsDirectory
......
3427 3427
            r += htmltext('</ul>')
3428 3428
            r += htmltext('</div>')
3429 3429

  
3430
        has_tracing = False
3431
        for evolution in self.filled.evolution or []:
3432
            if evolution.parts and any(isinstance(x, ActionsTracingEvolutionPart) for x in evolution.parts):
3433
                has_tracing = True
3434
                break
3435

  
3436
        if has_tracing:
3437
            action_classes = {x.key: x.description for x in item_classes}
3438
            r += htmltext('<div id="inspect-timeline" class="section">')
3439
            r += htmltext('<h2>%s</h2></li>\n') % _('Actions Tracing')
3440
            r += htmltext('<ul class="form-inspector biglist">')
3441
            wf_status = None
3442
            status_admin_base_url = '#'
3443
            for evolution in self.filled.evolution:
3444
                if evolution.status and evolution.status != wf_status:
3445
                    for part in evolution.parts or []:
3446
                        if isinstance(part, ActionsTracingEvolutionPart):
3447
                            if part.actions:
3448
                                r += (
3449
                                    htmltext('<li><span class="event">%s</span></li>')
3450
                                    % part.get_event_label()
3451
                                )
3452
                                break
3453
                    try:
3454
                        status = self.filled.formdef.workflow.get_status(evolution.status)
3455
                        status_label = status.name
3456
                        status_admin_base_url = status.get_admin_url()
3457
                    except KeyError:
3458
                        status_label = _('Unavailable status (%s)') % evolution.status
3459
                        status_admin_base_url = '#missing'
3460
                    r += htmltext(
3461
                        '<li><span class="datetime">%s</span> '
3462
                        '<a class="tracing-link" href="%s"><strong>%s</strong></a></li>'
3463
                    ) % (
3464
                        time.strftime('%Y-%m-%d %H:%M:%S', evolution.time) if evolution.time else '-',
3465
                        status_admin_base_url,
3466
                        status_label,
3467
                    )
3468
                if evolution.status:
3469
                    wf_status = evolution.status
3470
                first_part = True
3471
                for part in evolution.parts or []:
3472
                    if isinstance(part, ActionsTracingEvolutionPart):
3473
                        if not first_part and part.actions:
3474
                            r += htmltext('<li><span class="event">%s</span></li>') % part.get_event_label()
3475
                        first_part = False
3476
                        for action_ts, action_key, action_id in part.actions:
3477
                            action_label = action_classes.get(action_key, action_key)
3478
                            try:
3479
                                url = '%sitems/%s/' % (
3480
                                    part.get_base_url(self.filled.formdef.workflow, wf_status),
3481
                                    action_id,
3482
                                )
3483
                            except KeyError:
3484
                                url = '#missing-%s' % action_id
3485
                            r += htmltext(
3486
                                '<li><span class="datetime">%s</span> '
3487
                                '<a class="tracing-link" href="%s">%s</a></li>'
3488
                            ) % (
3489
                                action_ts.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3],
3490
                                url,
3491
                                action_label,
3492
                            )
3493

  
3494
            r += htmltext('</ul>')
3495
            r += htmltext('</div>')
3496

  
3430 3497
        # markers stack
3431 3498
        if '_markers_stack' in (self.filled.workflow_data or {}):
3432 3499
            r += htmltext('<div id="inspect-markers" class="section">')
wcs/qommon/static/css/dc2/admin.scss
1662 1662
	font-size: 100%;
1663 1663
}
1664 1664

  
1665
ul.form-inspector li span.datetime {
1666
	padding: 0 1ex;
1667
}
1668

  
1669
ul.form-inspector li a.tracing-link {
1670
	display: inline;
1671
	padding: 0;
1672
	&:hover {
1673
		background: transparent;
1674
		text-decoration: underline;
1675
	}
1676
}
1677

  
1665 1678
ul.form-inspector li span.status {
1666 1679
	padding: 0 1ex;
1667 1680
}
1668 1681

  
1682
ul.form-inspector span.event {
1683
	padding: 0 1ex;
1684
	font-style: italic;
1685
}
1686

  
1669 1687
ul.form-inspector li div.value {
1670 1688
	display: block;
1671 1689
	padding: 0 0 0 1em;
wcs/workflows.py
80 80
            continue
81 81
        if not item.check_condition(formdata):
82 82
            continue
83
        performed_actions.append((datetime.datetime.now(), item.id))
83
        performed_actions.append((datetime.datetime.now(), item.key, item.id))
84 84
        try:
85 85
            url = item.perform(formdata) or url
86 86
        except AbortActionException as e:
......
340 340
            self.event_args = None
341 341
        self.actions = actions
342 342

  
343
    def get_event_label(self):
344
        return {
345
            'api-created': _('Created (by API)'),
346
            'api-post-edit-action': _('Actions after edit action (by APIà'),
347
            'api-trigger': _('API Trigger'),
348
            'backoffice-created': _('Created (backoffice submission)'),
349
            'continuation': _('Continuation'),
350
            'csv-import-created': _('Created (by CSV import)'),
351
            'edit-action': _('Actions after edit action'),
352
            'frontoffice-created': _('Created (frontoffice submission)'),
353
            'global-action-button': _('Click on a global action button'),
354
            'global-action': _('Global action'),
355
            'global-action-timeout': _('Global action timeout'),
356
            'timeout-jump': _('Timeout jump'),
357
            'workflow-created': _('Created (by workflow action)'),
358
            'workflow-form-submit': _('Action in workflow form'),
359
        }.get(self.event, self.event)
360

  
361
    def is_global_event(self):
362
        return bool(self.event and self.event.startswith('global-'))
363

  
364
    def get_base_url(self, workflow, status_id):
365
        if self.is_global_event():
366
            return '%sglobal-actions/%s/' % (workflow.get_admin_url(), self.event_args[0])
367
        status = workflow.get_status(status_id)
368
        return status.get_admin_url()
369

  
343 370

  
344 371
class DuplicateGlobalActionNameError(Exception):
345 372
    pass
346
-