Skip to content

Commit 2b4c367

Browse files
committed
add: better API to allow projects to generate their own diff-tables
1 parent 2228f54 commit 2b4c367

File tree

1 file changed

+113
-95
lines changed

1 file changed

+113
-95
lines changed

basxconnect/core/layouts/editperson/common/history_tab.py

+113-95
Original file line numberDiff line numberDiff line change
@@ -26,116 +26,134 @@ def pairwise(iterable):
2626
C = layout.grid.Col
2727

2828

29-
def history_tab():
30-
"""
31-
new_record, old_record = p.history.all()
32-
delta = new_record.diff_against(old_record)
33-
for change in delta.changes:
34-
print("{} changed from {} to {}".format(change.field, change.old, change.new))
35-
"""
29+
def changes(c):
30+
if c["row"][0] is not None and c["row"][1] is not None:
31+
return list(c["row"][0].diff_against(c["row"][1]).changes)
32+
return ()
33+
34+
35+
def haschanges(a, b):
36+
return a is not None and b is not None and len(a.diff_against(b).changes) > 0
37+
38+
39+
def fieldname(c, model):
40+
try:
41+
return model._meta.get_field(c["change"].field).verbose_name
42+
except FieldDoesNotExist:
43+
return c["change"].field.replace("_", " ").capitalize()
3644

37-
def changes(c):
38-
if c["row"][1] is not None:
39-
return list(c["row"][0].diff_against(c["row"][1]).changes)
40-
return ()
4145

42-
def haschanges(a, b):
43-
return b is not None and len(a.diff_against(b).changes) > 0
46+
def newfieldvalue(c, model):
47+
try:
48+
field = model._meta.get_field(c["change"].field)
49+
if isinstance(field, RelatedField):
50+
try:
51+
return field.related_model.objects.get(id=int(c["change"].new))
52+
except field.related_model.DoesNotExist:
53+
return hg.SPAN(_("<Value has been deleted>"), style="color: red")
54+
except FieldDoesNotExist:
55+
pass
56+
return c["change"].new
4457

58+
59+
def oldfieldvalue(c, model):
60+
try:
61+
field = model._meta.get_field(c["change"].field)
62+
if isinstance(field, RelatedField):
63+
ret = field.related_model.objects.filter(id=int(c["change"].old)).first()
64+
return ret or hg.SPAN(_("<Value has been deleted>"), style="color: red")
65+
except FieldDoesNotExist:
66+
pass
67+
return c["change"].old
68+
69+
70+
def diff_table(model, historylist, showObjectLabel=None):
4571
def historyentries(c):
4672
return (
4773
(i, j)
48-
for i, j in pairwise(chain(c["object"].history.all(), [None]))
74+
for i, j in pairwise(chain(historylist(c), [None]))
4975
if haschanges(i, j)
5076
)
5177

52-
def fieldname(c):
53-
try:
54-
return c["object"]._meta.get_field(c["change"].field).verbose_name
55-
except FieldDoesNotExist:
56-
return c["change"].field.replace("_", " ").capitalize()
57-
58-
def newfieldvalue(c):
59-
try:
60-
field = c["object"]._meta.get_field(c["change"].field)
61-
if isinstance(field, RelatedField):
62-
try:
63-
return field.related_model.objects.get(id=int(c["change"].new))
64-
except field.related_model.DoesNotExist:
65-
return hg.SPAN(_("<Value has been deleted>"), style="color: red")
66-
except FieldDoesNotExist:
67-
pass
68-
return c["change"].new
69-
70-
def oldfieldvalue(c):
71-
try:
72-
field = c["object"]._meta.get_field(c["change"].field)
73-
if isinstance(field, RelatedField):
74-
ret = field.related_model.objects.filter(
75-
id=int(c["change"].old)
76-
).first()
77-
return ret or hg.SPAN(_("<Value has been deleted>"), style="color: red")
78-
except FieldDoesNotExist:
79-
pass
80-
return c["change"].old
78+
return layout.components.datatable.DataTable(
79+
row_iterator=hg.F(historyentries),
80+
columns=[
81+
layout.components.datatable.DataTableColumn(
82+
_("Date"),
83+
layout.localize(layout.localtime(hg.C("row")[0].history_date).date()),
84+
),
85+
layout.components.datatable.DataTableColumn(
86+
_("Time"),
87+
layout.localize(layout.localtime(hg.C("row")[0].history_date).time()),
88+
),
89+
layout.components.datatable.DataTableColumn(
90+
_("User"),
91+
hg.C("row")[0].history_user,
92+
),
93+
*(
94+
[
95+
layout.components.datatable.DataTableColumn(
96+
_("Object"),
97+
hg.F(lambda c: showObjectLabel(c["row"][0].instance)),
98+
)
99+
]
100+
if showObjectLabel is not None
101+
else []
102+
),
103+
layout.components.datatable.DataTableColumn(
104+
_("Changes"),
105+
hg.UL(
106+
hg.Iterator(
107+
hg.F(changes),
108+
"change",
109+
hg.LI(
110+
hg.SPAN(
111+
hg.F(lambda c: fieldname(c, model(c))),
112+
style="font-weight: 600",
113+
),
114+
": ",
115+
hg.SPAN(
116+
hg.If(
117+
hg.C("change").old,
118+
hg.F(lambda c: oldfieldvalue(c, model(c))),
119+
settings.HTML_NONE,
120+
),
121+
style="text-decoration: line-through;",
122+
),
123+
" -> ",
124+
hg.SPAN(
125+
hg.If(
126+
hg.C("change").new,
127+
hg.F(lambda c: newfieldvalue(c, model(c))),
128+
settings.HTML_NONE,
129+
)
130+
),
131+
),
132+
),
133+
),
134+
),
135+
],
136+
)
137+
138+
139+
def history_tab():
140+
"""
141+
new_record, old_record = p.history.all()
142+
delta = new_record.diff_against(old_record)
143+
for change in delta.changes:
144+
print("{} changed from {} to {}".format(change.field, change.old, change.new))
145+
"""
146+
147+
def historyentries(c):
148+
return c["object"].history.all()
81149

82150
return layout.tabs.Tab(
83151
_("History"),
84152
utils.grid_inside_tab(
85153
R(
86154
utils.tiling_col(
87-
layout.components.datatable.DataTable(
88-
row_iterator=hg.F(historyentries),
89-
columns=[
90-
layout.components.datatable.DataTableColumn(
91-
_("Date"),
92-
layout.localize(
93-
layout.localtime(hg.C("row")[0].history_date).date()
94-
),
95-
),
96-
layout.components.datatable.DataTableColumn(
97-
_("Time"),
98-
layout.localize(
99-
layout.localtime(hg.C("row")[0].history_date).time()
100-
),
101-
),
102-
layout.components.datatable.DataTableColumn(
103-
_("User"),
104-
hg.C("row")[0].history_user,
105-
),
106-
layout.components.datatable.DataTableColumn(
107-
_("Changes"),
108-
hg.UL(
109-
hg.Iterator(
110-
hg.F(changes),
111-
"change",
112-
hg.LI(
113-
hg.SPAN(
114-
hg.F(fieldname),
115-
style="font-weight: 600",
116-
),
117-
": ",
118-
hg.SPAN(
119-
hg.If(
120-
hg.C("change").old,
121-
hg.F(oldfieldvalue),
122-
settings.HTML_NONE,
123-
),
124-
style="text-decoration: line-through;",
125-
),
126-
" -> ",
127-
hg.SPAN(
128-
hg.If(
129-
hg.C("change").new,
130-
hg.F(newfieldvalue),
131-
settings.HTML_NONE,
132-
)
133-
),
134-
),
135-
),
136-
),
137-
),
138-
],
155+
diff_table(
156+
lambda c: type(c["object"]), historyentries
139157
).with_toolbar(_("Changes"))
140158
)
141159
),

0 commit comments

Comments
 (0)