Projet

Général

Profil

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

Lauréline Guérin, 27 juin 2022 08:31

Télécharger (29,8 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                   | 128 ++++++++--
 wcs/qommon/static/css/dc2/admin.scss          |  17 +-
 .../wcs/backoffice/block-inspect.html         |   2 +-
 .../wcs/backoffice/formdef-inspect.html       |   4 +-
 .../wcs/backoffice/snapshots_compare.html     |  34 ++-
 .../wcs/backoffice/workflow-inspect.html      |  60 ++---
 12 files changed, 355 insertions(+), 137 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
152 152
    assert [int(f.id) for f in snapshot6.instance.fields] == list(range(0, 12))
153 153

  
154 154

  
155
def test_snapshot_diff(pub):
155
def test_snapshot_instance(pub):
156
    formdef = FormDef()
157
    formdef.name = 'testform'
158
    formdef.fields = []
159
    formdef.store()
160

  
161
    carddef = CardDef()
162
    carddef.name = 'testcard'
163
    carddef.fields = []
164
    carddef.store()
165

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

  
170
    carddef.name = 'testcard2'
171
    carddef.store()
172

  
173
    for i in range(10):
174
        formdef.name = 'testform %s' % i
175
        formdef.store()
176

  
177
    assert pub.snapshot_class.count() == 11
178

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

  
186
    snapshots = pub.snapshot_class.select_object_history(carddef)
187
    assert len(snapshots) == 1
188

  
189

  
190
def test_snapshot_user(pub):
191
    user = pub.user_class()
192
    user.name = 'User Name'
193
    user.email = 'foo@localhost'
194
    user.store()
195

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

  
203
    snapshot.user_id = user.id
204
    snapshot.store()
205
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
206
    assert str(snapshot.user) == 'User Name'
207

  
208
    snapshot.user_id = 'nope'
209
    snapshot.store()
210
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
211
    assert str(snapshot.user) == 'unknown user'
212

  
213

  
214
def test_form_snapshot_diff(pub):
156 215
    create_superuser(pub)
157 216
    create_role(pub)
158 217

  
......
190 249
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot3.id, snapshot3.id) in resp
191 250
    assert resp.text.count('diff_sub') == 1
192 251
    assert resp.text.count('diff_add') == 24
252
    resp = resp.click('Compare inspect')
253
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot1.id, snapshot1.id) in resp
254
    assert 'Snapshot <a href="%s/view/">%s</a>' % (snapshot3.id, snapshot3.id) in resp
255
    assert 'http://example.net/backoffice/forms/%s/fields/1/' % formdef.id in resp
256
    assert 'http://example.net/backoffice/forms/%s/fields/2/' % formdef.id in resp
193 257

  
194 258
    resp = app.get(
195 259
        '/backoffice/forms/%s/history/compare?version1=%s&version2=%s'
......
223 287
    assert resp.text.count('diff_sub') == 11
224 288
    assert resp.text.count('diff_add') == 0
225 289

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

  
242

  
243
def test_snapshot_instance(pub):
244
    formdef = FormDef()
245
    formdef.name = 'testform'
246
    formdef.fields = []
247
    formdef.store()
248

  
249
    carddef = CardDef()
250
    carddef.name = 'testcard'
251
    carddef.fields = []
252
    carddef.store()
253

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

  
258
    carddef.name = 'testcard2'
259
    carddef.store()
260

  
261
    for i in range(10):
262
        formdef.name = 'testform %s' % i
263
        formdef.store()
264

  
265
    assert pub.snapshot_class.count() == 11
266

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

  
274
    snapshots = pub.snapshot_class.select_object_history(carddef)
275
    assert len(snapshots) == 1
276

  
277

  
278
def test_snapshot_user(pub):
279
    user = pub.user_class()
280
    user.name = 'User Name'
281
    user.email = 'foo@localhost'
282
    user.store()
283

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

  
291
    snapshot.user_id = user.id
292
    snapshot.store()
293
    snapshot = pub.snapshot_class.select_object_history(carddef)[0]
294
    assert str(snapshot.user) == 'User Name'
295

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

  
301 307

  
302 308
def test_form_snapshot_comments(pub):
......
588 594
    assert 'Can not display snapshot (Unknown referenced objects [Unknown field types: foobar])' in resp
589 595

  
590 596

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

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

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

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

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

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

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

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

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

  
660

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

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

  
1007 1095

  
1008 1096
def test_mail_template_snapshot_browse(pub):
1009 1097
    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
650 650
        except KeyError:
651 651
            raise TraversalError()
652 652
        self.formdefui = self.formdef_ui_class(self.formdef)
653
        get_response().breadcrumb.append((component + '/', self.formdef.name))
653
        if component:
654
            get_response().breadcrumb.append((component + '/', self.formdef.name))
654 655
        self.fields = self.fields_directory_class(self.formdef)
655 656
        self.fields.html_top = self.html_top
656 657
        self.role = WorkflowRoleDirectory(self.formdef)
......
1753 1754
    def inspect(self):
1754 1755
        self.html_top(self.formdef.name)
1755 1756
        get_response().breadcrumb.append(('inspect', _('Inspector')))
1757
        return self.render_inspect()
1758

  
1759
    def render_inspect(self):
1756 1760
        context = {'formdef': self.formdef, 'view': self}
1757 1761
        if self.formdef.workflow.variables_formdef:
1758 1762
            context['workflow_options'] = {}
wcs/admin/workflows.py
1586 1586
        self.criticality_levels_dir = CriticalityLevelsDirectory(self.workflow)
1587 1587
        self.logged_errors_dir = LoggedErrorsDirectory(parent_dir=self, workflow_id=self.workflow.id)
1588 1588
        self.snapshots_dir = SnapshotsDirectory(self.workflow)
1589
        get_response().breadcrumb.append((component + '/', self.workflow.name))
1589
        if component:
1590
            get_response().breadcrumb.append((component + '/', self.workflow.name))
1590 1591

  
1591 1592
    def html_top(self, title):
1592 1593
        return html_top('workflows', title)
......
1679 1680
    def inspect(self):
1680 1681
        self.html_top(self.workflow.name)
1681 1682
        get_response().breadcrumb.append(('inspect', _('Inspector')))
1683
        return self.render_inspect()
1684

  
1685
    def render_inspect(self):
1682 1686
        context = {'workflow': self.workflow, 'view': self}
1683 1687
        return template.QommonTemplateResponse(
1684 1688
            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 fix_result(panel_diff):
146
            if not panel_diff:
147
                return panel_diff
148
            panel = pq(panel_diff)
149
            # remove "Link" added by htmldiff
150
            for link in panel.find('a'):
151
                d = pq(link)
152
                text = d.html()
153
                new_text = re.sub(r' Link: .*$', '', text)
154
                d.html(new_text)
155
            # remove empty ins and del tags
156
            for elem in panel.find('ins, del'):
157
                d = pq(elem)
158
                if not d.html().strip():
159
                    d.remove()
160
            # prevent auto-closing behaviour of pyquery .html() method
161
            for elem in panel.find('span, ul, div'):
162
                d = pq(elem)
163
                if not d.html():
164
                    d.html(' ')
165
            return panel.html()
166

  
167
        inspect1 = backoffice_class(component=None, instance=snapshot1.instance).render_inspect()
168
        inspect1 = template.render(inspect1.templates, inspect1.context)
169
        d1 = pq(str(inspect1))
170
        inspect2 = backoffice_class(component=None, instance=snapshot2.instance).render_inspect()
171
        inspect2 = template.render(inspect2.templates, inspect2.context)
172
        d2 = pq(str(inspect2))
173
        panels_attrs = [tab.attrib for tab in d1('[role="tabpanel"]')]
174
        panels1 = [pq(tab).html().strip('\n') for tab in d1('[role="tabpanel"]')]
175
        panels2 = [pq(tab).html().strip('\n') for tab in d2('[role="tabpanel"]')]
176

  
177
        # build tab list (merge version 1 and version2)
178
        tabs1 = d1.find('[role="tab"]')
179
        tabs2 = d2.find('[role="tab"]')
180
        tabs_order = [t.get('id') for t in panels_attrs]
181
        tabs = {}
182
        for tab in tabs1 + tabs2:
183
            tab_id = pq(tab).attr('aria-controls')
184
            tabs[tab_id] = pq(tab).outer_html()
185
        tabs = [tabs[k] for k in tabs_order if k in tabs]
186

  
187
        # build diff of each panel
188
        panels_diff = list(map(htmldiff, panels1, panels2))
189
        panels_diff = [fix_result(t) for t in panels_diff]
190

  
191
        return {
192
            'fromdesc': self.snapshot_desc(snapshot1),
193
            'todesc': self.snapshot_desc(snapshot2),
194
            'tabs': tabs,
195
            'panels': zip(panels_attrs, panels_diff),
196
            'tab_class_names': d1('.pk-tabs').attr('class'),
197
        }
116 198

  
117 199
    def snapshots(self):
118 200
        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
}
......
2370 2370
	min-width: 4em;
2371 2371
}
2372 2372

  
2373
.section.diff {
2374
	background: transparent;
2373
div.diff {
2374
	margin: 1em 0;
2375 2375
}
2376 2376

  
2377 2377
table.diff {
......
2392 2392
		 */
2393 2393
		overflow: hidden;
2394 2394
		text-overflow: ellipsis;
2395
		vertical-align: top;
2395 2396
	}
2396 2397
	.diff_header {
2397 2398
		background: #f7f7f7;
......
2414 2415
		background-color: #ffaaaa;
2415 2416
	}
2416 2417
}
2418
ins {
2419
	text-decoration: none;
2420
	background-color: #d4fcbc;
2421
}
2422

  
2423
del {
2424
	text-decoration: line-through;
2425
	background-color: #fbb6c2;
2426
	color: #555;
2427
}
2417 2428

  
2418 2429
#sidebar .operator-and-value-widget {
2419 2430
	.title-and-operator {
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 %}
......
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
-