Projet

Général

Profil

0001-snapshot-compare-inspect-of-2-versions-66565.patch

Lauréline Guérin, 20 juillet 2022 09:08

Télécharger (31 ko)

Voir les différences:

Subject: [PATCH] snapshot: compare inspect of 2 versions (#66565)

 debian/control                                |   1 +
 setup.py                                      |   2 +
 tests/test_snapshots.py                       | 226 ++++++++++++------
 wcs/admin/blocks.py                           |   6 +-
 wcs/admin/forms.py                            |   6 +-
 wcs/admin/workflows.py                        |   6 +-
 wcs/backoffice/snapshots.py                   | 144 +++++++++--
 wcs/qommon/static/css/dc2/admin.scss          |  31 ++-
 .../wcs/backoffice/block-inspect.html         |   2 +-
 .../wcs/backoffice/formdef-inspect.html       |   6 +-
 .../wcs/backoffice/snapshots_compare.html     |  34 ++-
 .../wcs/backoffice/workflow-inspect.html      |  60 ++---
 12 files changed, 386 insertions(+), 138 deletions(-)
debian/control
24 24
         python3-dnspython,
25 25
         python3-hobo,
26 26
         python3-lasso,
27
         python3-lxml,
27 28
         python3-pil,
28 29
         python3-psycopg2,
29 30
         python3-pyproj,
setup.py
178 178
        'XStatic-Leaflet-GestureHandling',
179 179
        'XStatic-Select2',
180 180
        'pyproj',
181
        'pyquery',
181 182
        'unidecode',
183
        'lxml',
182 184
    ],
183 185
    package_dir={'wcs': 'wcs'},
184 186
    packages=find_packages(),
tests/test_snapshots.py
149 149
    assert [int(f.id) for f in snapshot6.instance.fields] == list(range(0, 12))
150 150

  
151 151

  
152
def test_snapshot_diff(pub):
152
def test_snapshot_instance(pub):
153
    formdef = FormDef()
154
    formdef.name = 'testform'
155
    formdef.fields = []
156
    formdef.store()
157

  
158
    carddef = CardDef()
159
    carddef.name = 'testcard'
160
    carddef.fields = []
161
    carddef.store()
162

  
163
    # remove existing snapshots as they may be duplicated if table_name was
164
    # generated in a different second.
165
    pub.snapshot_class.wipe()
166

  
167
    carddef.name = 'testcard2'
168
    carddef.store()
169

  
170
    for i in range(10):
171
        formdef.name = 'testform %s' % i
172
        formdef.store()
173

  
174
    assert pub.snapshot_class.count() == 11
175

  
176
    snapshots = pub.snapshot_class.select_object_history(formdef)
177
    assert len(snapshots) == 10
178
    for i in range(10):
179
        assert snapshots[i].serialization is None  # not loaded
180
        assert snapshots[i].patch is None  # not loaded
181
        assert pub.snapshot_class.get(snapshots[i].id).instance.name == 'testform %s' % (9 - i)
182

  
183
    snapshots = pub.snapshot_class.select_object_history(carddef)
184
    assert len(snapshots) == 1
185

  
186

  
187
def test_snapshot_user(pub):
188
    user = pub.user_class()
189
    user.name = 'User Name'
190
    user.email = 'foo@localhost'
191
    user.store()
192

  
193
    carddef = CardDef()
194
    carddef.name = 'testcard'
195
    carddef.fields = []
196
    carddef.store()
197
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
198
    assert snapshot.user is None
199

  
200
    snapshot.user_id = user.id
201
    snapshot.store()
202
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
203
    assert str(snapshot.user) == 'User Name'
204

  
205
    snapshot.user_id = 'nope'
206
    snapshot.store()
207
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
208
    assert str(snapshot.user) == 'unknown user'
209

  
210

  
211
def test_form_snapshot_diff(pub):
153 212
    create_superuser(pub)
154 213
    create_role(pub)
155 214

  
......
187 246
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot3.id, snapshot3.id) in resp
188 247
    assert resp.text.count('diff_sub') == 1
189 248
    assert resp.text.count('diff_add') == 24
249
    resp = resp.click('Compare inspect')
250
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot1.id, snapshot1.id) in resp
251
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot3.id, snapshot3.id) in resp
252
    assert 'http://example.net/backoffice/forms/%s/fields/1/' % formdef.id in resp
253
    assert 'http://example.net/backoffice/forms/%s/fields/2/' % formdef.id in resp
190 254

  
191 255
    resp = app.get(
192 256
        '/backoffice/forms/%s/history/compare?version1=%s&version2=%s'
......
220 284
    assert resp.text.count('diff_sub') == 11
221 285
    assert resp.text.count('diff_add') == 0
222 286

  
223
    resp = app.get('/backoffice/forms/%s/history/compare' % (formdef.id), status=404)
224
    resp = app.get(
225
        '/backoffice/forms/%s/history/compare?version1=%s' % (formdef.id, snapshot4.id), status=404
226
    )
227
    resp = app.get(
228
        '/backoffice/forms/%s/history/compare?version2=%s' % (formdef.id, snapshot4.id), status=404
229
    )
230
    resp = app.get(
287
    app.get('/backoffice/forms/%s/history/compare' % (formdef.id), status=404)
288
    app.get('/backoffice/forms/%s/history/compare?version1=%s' % (formdef.id, snapshot4.id), status=404)
289
    app.get('/backoffice/forms/%s/history/compare?version2=%s' % (formdef.id, snapshot4.id), status=404)
290
    app.get(
231 291
        '/backoffice/forms/%s/history/compare?version1=%s&version2=%s' % (formdef.id, snapshot3.id, 0),
232 292
        status=404,
233 293
    )
234
    resp = app.get(
294
    app.get(
235 295
        '/backoffice/forms/%s/history/compare?version1=%s&version2=%s' % (formdef.id, 0, snapshot4.id),
236 296
        status=404,
237 297
    )
238

  
239

  
240
def test_snapshot_instance(pub):
241
    formdef = FormDef()
242
    formdef.name = 'testform'
243
    formdef.fields = []
244
    formdef.store()
245

  
246
    carddef = CardDef()
247
    carddef.name = 'testcard'
248
    carddef.fields = []
249
    carddef.store()
250

  
251
    # remove existing snapshots as they may be duplicated if table_name was
252
    # generated in a different second.
253
    pub.snapshot_class.wipe()
254

  
255
    carddef.name = 'testcard2'
256
    carddef.store()
257

  
258
    for i in range(10):
259
        formdef.name = 'testform %s' % i
260
        formdef.store()
261

  
262
    assert pub.snapshot_class.count() == 11
263

  
264
    snapshots = pub.snapshot_class.select_object_history(formdef)
265
    assert len(snapshots) == 10
266
    for i in range(10):
267
        assert snapshots[i].serialization is None  # not loaded
268
        assert snapshots[i].patch is None  # not loaded
269
        assert pub.snapshot_class.get(snapshots[i].id).instance.name == 'testform %s' % (9 - i)
270

  
271
    snapshots = pub.snapshot_class.select_object_history(carddef)
272
    assert len(snapshots) == 1
273

  
274

  
275
def test_snapshot_user(pub):
276
    user = pub.user_class()
277
    user.name = 'User Name'
278
    user.email = 'foo@localhost'
279
    user.store()
280

  
281
    carddef = CardDef()
282
    carddef.name = 'testcard'
283
    carddef.fields = []
284
    carddef.store()
285
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
286
    assert snapshot.user is None
287

  
288
    snapshot.user_id = user.id
289
    snapshot.store()
290
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
291
    assert str(snapshot.user) == 'User Name'
292

  
293
    snapshot.user_id = 'nope'
294
    snapshot.store()
295
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
296
    assert str(snapshot.user) == 'unknown user'
298
    app.get(
299
        '/backoffice/forms/%s/history/compare?version1=%s&version2=%s&mode=foobar'
300
        % (formdef.id, snapshot1.id, snapshot3.id),
301
        status=404,
302
    )
297 303

  
298 304

  
299 305
def test_form_snapshot_comments(pub):
......
587 593
    assert 'Can not display snapshot (Unknown referenced objects [Unknown field types: foobar])' in resp
588 594

  
589 595

  
596
def test_workflow_snapshot_diff(pub):
597
    create_superuser(pub)
598
    create_role(pub)
599

  
600
    Workflow.wipe()
601
    workflow = Workflow(name='test')
602
    workflow.store()
603
    assert pub.snapshot_class.count() == 1
604
    snapshot1 = pub.snapshot_class.get_latest('workflow', workflow.id)
605

  
606
    workflow.add_status('Status1', 'st1')
607
    workflow.store()
608
    assert pub.snapshot_class.count() == 2
609
    snapshot2 = pub.snapshot_class.get_latest('workflow', workflow.id)
610

  
611
    ac1 = workflow.add_global_action('Action', 'ac1')
612
    trigger = ac1.triggers[0]
613
    assert trigger.key == 'manual'
614
    trigger.roles = ['foobar']
615
    workflow.store()
616
    assert pub.snapshot_class.count() == 3
617
    snapshot3 = pub.snapshot_class.get_latest('workflow', workflow.id)
618

  
619
    workflow.global_actions = []
620
    workflow.store()
621
    assert pub.snapshot_class.count() == 4
622
    snapshot4 = pub.snapshot_class.get_latest('workflow', workflow.id)
623

  
624
    app = login(get_app(pub))
625
    resp = app.get(
626
        '/backoffice/workflows/%s/history/compare?version1=%s&version2=%s&mode=inspect'
627
        % (workflow.id, snapshot1.id, snapshot2.id)
628
    )
629
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot1.id, snapshot1.id) in resp
630
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot2.id, snapshot2.id) in resp
631
    assert 'id="tab-statuses"' in resp
632
    assert 'id="tab-global-actions"' not in resp
633

  
634
    resp = app.get(
635
        '/backoffice/workflows/%s/history/compare?version1=%s&version2=%s&mode=inspect'
636
        % (workflow.id, snapshot2.id, snapshot3.id)
637
    )
638
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot2.id, snapshot2.id) in resp
639
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot3.id, snapshot3.id) in resp
640
    assert 'http://example.net/backoffice/workflows/%s/global-actions/ac1/' % (workflow.id) in resp
641
    assert 'http://example.net/backoffice/workflows/%s/status/st1/' % workflow.id in resp
642
    assert 'id="tab-statuses"' in resp
643
    assert 'id="tab-global-actions"' in resp
644

  
645
    resp = app.get(
646
        '/backoffice/workflows/%s/history/compare?version1=%s&version2=%s&mode=inspect'
647
        % (workflow.id, snapshot3.id, snapshot4.id)
648
    )
649
    assert 'id="tab-statuses"' in resp
650
    assert 'id="tab-global-actions"' in resp
651

  
652
    resp = app.get(
653
        '/backoffice/workflows/%s/history/compare?version1=%s&version2=%s&mode=inspect'
654
        % (workflow.id, snapshot1.id, snapshot4.id)
655
    )
656
    assert 'id="tab-statuses"' in resp
657
    assert 'id="tab-global-actions"' not in resp
658

  
659

  
590 660
def test_workflow_snapshot_browse(pub):
591 661
    create_superuser(pub)
592 662
    create_role(pub)
......
1003 1073
    mail_template2 = MailTemplate.get(resp.location.split('/')[-2])
1004 1074
    assert mail_template2.id == mail_template.id
1005 1075

  
1076
    snapshot1 = pub.snapshot_class.select_object_history(mail_template)[0]
1077
    snapshot2 = pub.snapshot_class.select_object_history(mail_template)[1]
1078
    app.get(
1079
        '/backoffice/workflows/mail-templates/%s/history/compare?version1=%s&version2=%s&mode=xml'
1080
        % (mail_template.id, snapshot1.id, snapshot2.id),
1081
        status=200,
1082
    )
1083
    app.get(
1084
        '/backoffice/workflows/mail-templates/%s/history/compare?version1=%s&version2=%s&mode=inspect'
1085
        % (mail_template.id, snapshot1.id, snapshot2.id),
1086
        status=404,
1087
    )
1088
    app.get(
1089
        '/backoffice/workflows/mail-templates/%s/history/compare?version1=%s&version2=%s&mode=foobar'
1090
        % (mail_template.id, snapshot1.id, snapshot2.id),
1091
        status=404,
1092
    )
1093

  
1006 1094

  
1007 1095
def test_mail_template_snapshot_browse(pub):
1008 1096
    create_superuser(pub)
wcs/admin/blocks.py
58 58
    fields_count_total_hard_limit = 60
59 59

  
60 60
    def __init__(self, section='forms', *args, **kwargs):
61
        if kwargs.pop('component', None):  # snapshot
61
        kwargs.pop('component', None)  # snapshot
62
        if 'instance' in kwargs:
62 63
            kwargs['objectdef'] = kwargs.pop('instance')
63 64
        self.section = section
64 65
        super().__init__(*args, **kwargs)
......
211 212
    def inspect(self):
212 213
        self.html_top(self.objectdef.name)
213 214
        get_response().breadcrumb.append(('inspect', _('Inspector')))
215
        return self.render_inspect()
216

  
217
    def render_inspect(self):
214 218
        context = {'blockdef': self.objectdef, 'view': self}
215 219
        return template.QommonTemplateResponse(
216 220
            templates=['wcs/backoffice/block-inspect.html'], context=context
wcs/admin/forms.py
647 647
        except KeyError:
648 648
            raise TraversalError()
649 649
        self.formdefui = self.formdef_ui_class(self.formdef)
650
        get_response().breadcrumb.append((component + '/', self.formdef.name))
650
        if component:
651
            get_response().breadcrumb.append((component + '/', self.formdef.name))
651 652
        self.fields = self.fields_directory_class(self.formdef)
652 653
        self.fields.html_top = self.html_top
653 654
        self.role = WorkflowRoleDirectory(self.formdef)
......
1647 1648
    def inspect(self):
1648 1649
        self.html_top(self.formdef.name)
1649 1650
        get_response().breadcrumb.append(('inspect', _('Inspector')))
1651
        return self.render_inspect()
1652

  
1653
    def render_inspect(self):
1650 1654
        context = {'formdef': self.formdef, 'view': self}
1651 1655
        if self.formdef.workflow.variables_formdef:
1652 1656
            context['workflow_options'] = {}
wcs/admin/workflows.py
1602 1602
        self.criticality_levels_dir = CriticalityLevelsDirectory(self.workflow)
1603 1603
        self.logged_errors_dir = LoggedErrorsDirectory(parent_dir=self, workflow_id=self.workflow.id)
1604 1604
        self.snapshots_dir = SnapshotsDirectory(self.workflow)
1605
        get_response().breadcrumb.append((component + '/', self.workflow.name))
1605
        if component:
1606
            get_response().breadcrumb.append((component + '/', self.workflow.name))
1606 1607

  
1607 1608
    def html_top(self, title):
1608 1609
        return html_top('workflows', title)
......
1707 1708
    def inspect(self):
1708 1709
        self.html_top(self.workflow.name)
1709 1710
        get_response().breadcrumb.append(('inspect', _('Inspector')))
1711
        return self.render_inspect()
1712

  
1713
    def render_inspect(self):
1710 1714
        context = {'workflow': self.workflow, 'view': self}
1711 1715
        return template.QommonTemplateResponse(
1712 1716
            templates=['wcs/backoffice/workflow-inspect.html'], context=context
wcs/backoffice/snapshots.py
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import difflib
18
import re
18 19

  
19 20
from django.utils.module_loading import import_string
21
from lxml.html.diff import htmldiff  # pylint: disable=no-name-in-module
22
from pyquery import PyQuery as pq
20 23
from quixote import get_publisher, get_request, get_response, get_session, redirect
21 24
from quixote.directory import Directory
22 25
from quixote.html import TemplateIO, htmltext
......
70 73
        get_response().breadcrumb.append(('compare/', _('Compare')))
71 74
        html_top('', _('Compare'))
72 75

  
76
        mode = get_request().form.get('mode') or 'xml'
77

  
73 78
        id1 = get_request().form.get('version1')
74 79
        id2 = get_request().form.get('version2')
75 80
        if not id1 or not id2:
76 81
            raise errors.TraversalError()
82
        if mode not in ['xml', 'inspect']:
83
            raise errors.TraversalError()
77 84

  
78 85
        snapshot1 = get_publisher().snapshot_class.get(id1, ignore_errors=True)
79 86
        snapshot2 = get_publisher().snapshot_class.get(id2, ignore_errors=True)
......
82 89
        if snapshot1.timestamp > snapshot2.timestamp:
83 90
            snapshot1, snapshot2 = snapshot2, snapshot1
84 91

  
85
        def snapshot_desc(snapshot):
86
            label_or_comment = ''
87
            if snapshot.label:
88
                label_or_comment = snapshot.label
89
            elif snapshot.comment:
90
                label_or_comment = snapshot.comment
91
            return '{name} <a href="{pk}/view/">{pk}</a><br />{label_or_comment}<br />({user}{timestamp})'.format(
92
                name=_('Snapshot'),
93
                pk=snapshot.id,
94
                label_or_comment=label_or_comment,
95
                user='%s ' % snapshot.user if snapshot.user_id else '',
96
                timestamp=misc.strftime(misc.datetime_format(), snapshot.timestamp),
97
            )
92
        klass = snapshot1.get_object_class()
93
        backoffice_class = import_string(klass.backoffice_class)
94
        has_inspect = hasattr(backoffice_class, 'render_inspect')
95

  
96
        if mode == 'inspect' and not has_inspect:
97
            raise errors.TraversalError()
98

  
99
        context = getattr(self, 'get_compare_%s_context' % mode)(snapshot1, snapshot2)
100
        context.update(
101
            {
102
                'mode': mode,
103
                'has_inspect': has_inspect,
104
                'snapshot1': snapshot1,
105
                'snapshot2': snapshot2,
106
            }
107
        )
108
        return template.QommonTemplateResponse(
109
            templates=['wcs/backoffice/snapshots_compare.html'],
110
            context=context,
111
        )
112

  
113
    def snapshot_desc(self, snapshot):
114
        label_or_comment = ''
115
        if snapshot.label:
116
            label_or_comment = snapshot.label
117
        elif snapshot.comment:
118
            label_or_comment = snapshot.comment
119
        return '{name} <a href="{pk}/view/">{pk}</a> - {label_or_comment} ({user}{timestamp})'.format(
120
            name=_('Snapshot'),
121
            pk=snapshot.id,
122
            label_or_comment=label_or_comment,
123
            user='%s ' % snapshot.user if snapshot.user_id else '',
124
            timestamp=misc.strftime(misc.datetime_format(), snapshot.timestamp),
125
        )
98 126

  
127
    def get_compare_xml_context(self, snapshot1, snapshot2):
99 128
        serialization1 = snapshot1.get_serialization(indented=True)
100 129
        serialization2 = snapshot2.get_serialization(indented=True)
101 130
        diff_serialization = difflib.HtmlDiff(wrapcolumn=160).make_table(
102 131
            fromlines=serialization1.splitlines(True),
103 132
            tolines=serialization2.splitlines(True),
104
            fromdesc=snapshot_desc(snapshot1),
105
            todesc=snapshot_desc(snapshot2),
106 133
        )
107 134

  
108
        return template.QommonTemplateResponse(
109
            templates=['wcs/backoffice/snapshots_compare.html'],
110
            context={
111
                'snapshot1': snapshot1,
112
                'snapshot2': snapshot2,
113
                'diff_serialization': diff_serialization,
114
            },
115
        )
135
        return {
136
            'fromdesc': self.snapshot_desc(snapshot1),
137
            'todesc': self.snapshot_desc(snapshot2),
138
            'diff_serialization': diff_serialization,
139
        }
140

  
141
    def get_compare_inspect_context(self, snapshot1, snapshot2):
142
        klass = snapshot1.get_object_class()
143
        backoffice_class = import_string(klass.backoffice_class)
144

  
145
        def clean_panel(tab):
146
            panel = pq(tab)
147
            # remove quicknavs
148
            panel.find('.inspect--quicknav').remove()
149
            # remove page & field counters, for formdef
150
            panel.find('.page-field-counters').remove()
151
            # remove status colors
152
            panel.find('.inspect-status--colour').remove()
153
            return panel.html().strip('\n')
154

  
155
        def fix_result(panel_diff):
156
            if not panel_diff:
157
                return panel_diff
158
            panel = pq(panel_diff)
159
            # remove "Link" added by htmldiff
160
            for link in panel.find('a'):
161
                d = pq(link)
162
                text = d.html()
163
                new_text = re.sub(r' Link: .*$', '', text)
164
                d.html(new_text)
165
            # remove empty ins and del tags
166
            for elem in panel.find('ins, del'):
167
                d = pq(elem)
168
                if not d.html().strip():
169
                    d.remove()
170
            # prevent auto-closing behaviour of pyquery .html() method
171
            for elem in panel.find('span, ul, div'):
172
                d = pq(elem)
173
                if not d.html():
174
                    d.html(' ')
175
            # sometimes status section are misplaced by htmldiff, fix it
176
            for elem in panel.find('div.section.status'):
177
                d = pq(elem)
178
                parents = d.parents('div.section.status')
179
                if parents:
180
                    pq(parents[0]).after(d.remove())
181
            return panel.html()
182

  
183
        inspect1 = backoffice_class(component=None, instance=snapshot1.instance).render_inspect()
184
        inspect1 = template.render(inspect1.templates, inspect1.context)
185
        d1 = pq(str(inspect1))
186
        inspect2 = backoffice_class(component=None, instance=snapshot2.instance).render_inspect()
187
        inspect2 = template.render(inspect2.templates, inspect2.context)
188
        d2 = pq(str(inspect2))
189
        panels_attrs = [tab.attrib for tab in d1('[role="tabpanel"]')]
190
        panels1 = [clean_panel(tab) for tab in d1('[role="tabpanel"]')]
191
        panels2 = [clean_panel(tab) for tab in d2('[role="tabpanel"]')]
192

  
193
        # build tab list (merge version 1 and version2)
194
        tabs1 = d1.find('[role="tab"]')
195
        tabs2 = d2.find('[role="tab"]')
196
        tabs_order = [t.get('id') for t in panels_attrs]
197
        tabs = {}
198
        for tab in tabs1 + tabs2:
199
            tab_id = pq(tab).attr('aria-controls')
200
            tabs[tab_id] = pq(tab).outer_html()
201
        tabs = [tabs[k] for k in tabs_order if k in tabs]
202

  
203
        # build diff of each panel
204
        panels_diff = list(map(htmldiff, panels1, panels2))
205
        panels_diff = [fix_result(t) for t in panels_diff]
206

  
207
        return {
208
            'fromdesc': self.snapshot_desc(snapshot1),
209
            'todesc': self.snapshot_desc(snapshot2),
210
            'tabs': tabs,
211
            'panels': zip(panels_attrs, panels_diff),
212
            'tab_class_names': d1('.pk-tabs').attr('class'),
213
        }
116 214

  
117 215
    def snapshots(self):
118 216
        current_date = None
wcs/qommon/static/css/dc2/admin.scss
969 969
	text-align: right;
970 970
}
971 971

  
972
p.last-modification {
972
p.last-modification, p.snapshot-description {
973 973
	font-size: 80%;
974 974
	margin: 0;
975 975
}
......
2374 2374
	min-width: 4em;
2375 2375
}
2376 2376

  
2377
.section.diff {
2378
	background: transparent;
2377
div.diff {
2378
	margin: 1em 0;
2379 2379
}
2380 2380

  
2381 2381
table.diff {
......
2396 2396
		 */
2397 2397
		overflow: hidden;
2398 2398
		text-overflow: ellipsis;
2399
		vertical-align: top;
2399 2400
	}
2400 2401
	.diff_header {
2401 2402
		background: #f7f7f7;
......
2419 2420
	}
2420 2421
}
2421 2422

  
2423
ins {
2424
	text-decoration: none;
2425
	background-color: #d4fcbc;
2426
}
2427

  
2428
del {
2429
	text-decoration: line-through;
2430
	background-color: #fbb6c2;
2431
	color: #555;
2432
}
2433

  
2434
.inspect-tabs h3 {
2435
	del, ins {
2436
		font-weight: bold;
2437
		background-color: transparent;
2438
	}
2439
	del, del a {
2440
		color: #fbb6c2 !important;
2441
	}
2442
	ins, ins a {
2443
		color: #d4fcbc !important;
2444
	}
2445
}
2446

  
2422 2447
#sidebar .operator-and-value-widget {
2423 2448
	.title-and-operator {
2424 2449
		display: flex;
wcs/templates/wcs/backoffice/block-inspect.html
22 22

  
23 23
<div id="inspect-fields" role="tabpanel" tabindex="0" aria-labelledby="tab-fields" hidden>
24 24
{% for field in blockdef.fields %}
25
{% include "wcs/backoffice/includes/inspect-field.html" %}
25
{% include "wcs/backoffice/includes/inspect-field.html" with path=blockdef.get_admin_url %}
26 26
{% endfor %}
27 27
</div>
28 28
</div>
wcs/templates/wcs/backoffice/formdef-inspect.html
29 29
<li><span class="parameter">{% trans "Options" %}{% trans ":" %}</span> {% if not workflow_options %}-{% else %}<ul>
30 30
  {% for label, value in workflow_options.items %}
31 31
  {% if value == '__title__' or value == '__subtitle__' %}<li><strong>{{ label }}</strong></li>
32
  {% elif value == '__comment__' %}<li><{{ label }}</li>
32
  {% elif value == '__comment__' %}<li>{{ label }}</li>
33 33
  {% else %}
34 34
  <li>{{ label }} → {{ value|safe|default:"-" }}</li>
35 35
  {% endif %}
......
73 73
</div>
74 74

  
75 75
<div id="inspect-fields" role="tabpanel" tabindex="0" aria-labelledby="tab-fields" hidden>
76
<div class="pk-information"><p>
76
<div class="pk-information page-field-counters"><p>
77 77
{% blocktrans count page_count=formdef.page_count %}{{ page_count }} page{% plural %}{{ page_count }} pages{% endblocktrans %},
78 78
{% blocktrans count fields_count=formdef.fields|count %}{{ fields_count }} field{% plural %}{{ fields_count }} fields.{% endblocktrans %}
79 79
</p></div>
80 80
{% for field in formdef.fields %}
81
{% include "wcs/backoffice/includes/inspect-field.html" %}
81
{% include "wcs/backoffice/includes/inspect-field.html" with path=formdef.get_admin_url|add:"fields/" %}
82 82
{% endfor %}
83 83
</div>
84 84
</div>
wcs/templates/wcs/backoffice/snapshots_compare.html
1
{% extends "wcs/backoffice/base.html" %}
1 2
{% load i18n %}
2 3

  
3
{% block body %}
4
<div id="appbar">
5
<h2>{% trans "Compare snapshots" %}</h2>
6
</div>
4
{% block appbar-title %}{% trans "Compare snapshots" %}{% if has_inspect %} ({% if mode == 'xml' %}{% trans "XML" %}{% else %}{% trans "Inspect" %}{% endif %}){% endif %}{% endblock %}
5
{% block appbar-actions %}
6
{% if has_inspect %}
7
<a href="?version1={{ snapshot1.id }}&version2={{ snapshot2.id }}&mode=inspect">{% trans "Compare inspect" %}</a>
8
<a href="?version1={{ snapshot1.id }}&version2={{ snapshot2.id }}&mode=xml">{% trans "Compare XML" %}</a>
9
{% endif %}
10
{% endblock %}
7 11

  
8
<div class="section diff">
9
  {{ diff_serialization|safe }}
12
{% block content %}
13
<p class="snapshot-description">{{ fromdesc|safe }} ➔ {{ todesc|safe }}</p>
14
<div class="diff">
15
{% if mode == 'xml' %}
16
    {{ diff_serialization|safe }}
17
{% else %}
18
  <div class="{{ tab_class_names }}">
19
    <div class="pk-tabs--tab-list" role="tablist">
20
      {% for tab in tabs %}{{ tab|safe }}{% endfor %}
21
      {{ tab_list|safe }}
22
    </div>
23
    <div class="pk-tabs--container">
24
      {% for attrs, panel in panels %}
25
        <div{% for k, v in attrs.items %} {{ k }}="{{ v }}"{% endfor %}>
26
          {{ panel|safe }}
27
        </div>
28
      {% endfor %}
29
    </div>
30
  </div>
31
{% endif %}
10 32
</div>
11 33
{% endblock %}
wcs/templates/wcs/backoffice/workflow-inspect.html
24 24
 </div>
25 25
 <div class="pk-tabs--container">
26 26

  
27
 <div id="inspect-functions" role="tabpanel" tabindex="0" aria-labelledby="tab-functions" hidden>
28
<ul>
29
{% for label in workflow.roles.values %}
30
<li>{{ label }}</li>
31
{% endfor %}
32
</ul>
33
</div>
34

  
35
<div id="inspect-variables" role="tabpanel" tabindex="0" aria-labelledby="tab-variables" hidden>
36
{% for field in workflow.variables_formdef.fields %}
37
{% include "wcs/backoffice/includes/inspect-field.html" with path="variables/fields/" %}
38
{% endfor %}
39
</div>
40

  
41
<div id="inspect-fields" role="tabpanel" tabindex="0" aria-labelledby="tab-fields" hidden>
42
{% for field in workflow.backoffice_fields_formdef.fields %}
43
{% include "wcs/backoffice/includes/inspect-field.html" with path="backoffice-fields/fields/" %}
44
{% endfor %}
45
</div>
46

  
47
<div id="inspect-criticality" role="tabpanel" tabindex="0" aria-labelledby="tab-criticality" hidden>
48
<ul>
49
{% for level in workflow.criticality_levels %}<li>{{ level.name }}</li>{% endfor %}
50
</ul>
51
</div>
52

  
53 27
<div id="inspect-statuses" role="tabpanel" tabindex="0" aria-labelledby="tab-statuses">
54 28
<nav class="inspect--quicknav"><span class="inspect--jumpto">{% trans "Jump to:" %}</span><ul class="inspect--quicklinks">
55 29
{% for status in workflow.possible_status %}
......
60 34
{% for status in workflow.possible_status %}
61 35
<div class="section status">
62 36
<h3 id="status-{{ status.id }}"
63
    ><a href="status/{{ status.id }}/" class="inspect-status--link">
37
    ><a href="{{ workflow.get_admin_url }}status/{{ status.id }}/" class="inspect-status--link">
64 38
    <span class="inspect-status--colour" style="background-color: #{{ status.colour|default:"fff" }}"></span>
65 39
    {{ status.name }}</a></h3>
66 40
{% if status.backoffice_info_text %}<div>{{ status.backoffice_info_text|safe }}</div>{% endif %}
67 41
{% for item in status.items %}
68
<h4><a href="status/{{ status.id }}/items/{{ item.id }}/">{{ item.description }}</a></h4>
42
<h4><a href="{{ workflow.get_admin_url }}status/{{ status.id }}/items/{{ item.id }}/">{{ item.description }}</a></h4>
69 43
{{ item.get_parameters_view|safe }}
70 44
{% empty %}
71 45
<p>{% trans "No actions in this status." %}</p>
......
84 58
<div class="expanded-statuses">
85 59
{% for action in workflow.global_actions %}
86 60
<div class="section global-action">
87
<h3><a id="action-{{ action.id }}" href="global-actions/{{ action.id }}/">{{ action.name }}</a></h3>
61
<h3><a id="action-{{ action.id }}" href="{{ workflow.get_admin_url }}global-actions/{{ action.id }}/">{{ action.name }}</a></h3>
88 62
<h4>{% trans "Triggers" %}</h4>
89 63
<ul>{% for trigger in action.triggers %}<li>{{ trigger.render_as_line }}</li>{% endfor %}</ul>
90 64
{% for item in action.items %}
91
<h4><a href="global-actions/{{ action.id }}/items/{{ item.id }}/">{{ item.description }}</a></h4>
65
<h4><a href="{{ workflow.get_admin_url }}global-actions/{{ action.id }}/items/{{ item.id }}/">{{ item.description }}</a></h4>
92 66
{{ item.get_parameters_view|safe }}
93 67
{% endfor %}
94 68
</div>
......
96 70
</div>
97 71
</div>
98 72

  
73
<div id="inspect-functions" role="tabpanel" tabindex="0" aria-labelledby="tab-functions" hidden>
74
<ul>
75
{% for label in workflow.roles.values %}
76
<li>{{ label }}</li>
77
{% endfor %}
78
</ul>
79
</div>
80

  
81
<div id="inspect-variables" role="tabpanel" tabindex="0" aria-labelledby="tab-variables" hidden>
82
{% for field in workflow.variables_formdef.fields %}
83
{% include "wcs/backoffice/includes/inspect-field.html" with path=workflow.get_admin_url|add:"variables/fields/" %}
84
{% endfor %}
85
</div>
86

  
87
<div id="inspect-fields" role="tabpanel" tabindex="0" aria-labelledby="tab-fields" hidden>
88
{% for field in workflow.backoffice_fields_formdef.fields %}
89
{% include "wcs/backoffice/includes/inspect-field.html" with path=workflow.get_admin_url|add:"backoffice-fields/fields/" %}
90
{% endfor %}
91
</div>
92

  
93
<div id="inspect-criticality" role="tabpanel" tabindex="0" aria-labelledby="tab-criticality" hidden>
94
<ul>
95
{% for level in workflow.criticality_levels %}<li>{{ level.name }}</li>{% endfor %}
96
</ul>
97
</div>
98

  
99 99
</div> <!-- pk-tabs-container -->
100 100
 </div> <!-- pk-tabs -->
101 101
{% endblock %}
102
-