lino 25.2.2__py3-none-any.whl → 25.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lino/__init__.py +8 -3
- lino/api/dd.py +11 -35
- lino/api/doctest.py +49 -17
- lino/api/selenium.py +1 -1
- lino/core/actions.py +25 -23
- lino/core/actors.py +52 -23
- lino/core/choicelists.py +10 -8
- lino/core/dbtables.py +1 -1
- lino/core/elems.py +47 -31
- lino/core/fields.py +19 -9
- lino/core/kernel.py +26 -20
- lino/core/model.py +27 -16
- lino/core/renderer.py +2 -2
- lino/core/requests.py +103 -56
- lino/core/site.py +5 -5
- lino/core/store.py +5 -2
- lino/core/utils.py +12 -7
- lino/help_texts.py +7 -8
- lino/mixins/duplicable.py +6 -4
- lino/mixins/sequenced.py +17 -6
- lino/modlib/__init__.py +0 -2
- lino/modlib/changes/models.py +21 -10
- lino/modlib/checkdata/models.py +59 -24
- lino/modlib/comments/fixtures/demo2.py +12 -3
- lino/modlib/comments/models.py +7 -7
- lino/modlib/comments/ui.py +8 -5
- lino/modlib/export_excel/models.py +7 -5
- lino/modlib/extjs/__init__.py +2 -2
- lino/modlib/extjs/views.py +66 -22
- lino/modlib/help/config/makehelp/conf.tpl.py +1 -1
- lino/modlib/jinja/mixins.py +73 -0
- lino/modlib/jinja/models.py +6 -0
- lino/modlib/linod/__init__.py +1 -0
- lino/modlib/linod/choicelists.py +21 -0
- lino/modlib/linod/consumers.py +13 -4
- lino/modlib/linod/fixtures/__init__.py +0 -0
- lino/modlib/linod/fixtures/linod.py +32 -0
- lino/modlib/linod/management/commands/linod.py +6 -2
- lino/modlib/linod/mixins.py +18 -14
- lino/modlib/linod/models.py +4 -2
- lino/modlib/memo/mixins.py +2 -1
- lino/modlib/memo/parser.py +1 -1
- lino/modlib/notify/models.py +19 -11
- lino/modlib/printing/actions.py +47 -42
- lino/modlib/printing/choicelists.py +17 -15
- lino/modlib/printing/mixins.py +22 -20
- lino/modlib/publisher/models.py +5 -5
- lino/modlib/summaries/models.py +3 -2
- lino/modlib/system/models.py +28 -29
- lino/modlib/uploads/__init__.py +14 -11
- lino/modlib/uploads/actions.py +2 -8
- lino/modlib/uploads/choicelists.py +10 -10
- lino/modlib/uploads/fixtures/std.py +17 -0
- lino/modlib/uploads/mixins.py +20 -8
- lino/modlib/uploads/models.py +62 -38
- lino/modlib/uploads/ui.py +15 -9
- lino/utils/__init__.py +0 -1
- lino/utils/jscompressor.py +4 -4
- lino/utils/media.py +45 -23
- lino/utils/report.py +5 -4
- lino/utils/restify.py +2 -2
- lino/utils/soup.py +26 -8
- lino/utils/xml.py +19 -5
- {lino-25.2.2.dist-info → lino-25.3.0.dist-info}/METADATA +1 -1
- {lino-25.2.2.dist-info → lino-25.3.0.dist-info}/RECORD +68 -65
- lino/mixins/uploadable.py +0 -3
- lino/utils/requests.py +0 -55
- {lino-25.2.2.dist-info → lino-25.3.0.dist-info}/WHEEL +0 -0
- {lino-25.2.2.dist-info → lino-25.3.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.2.2.dist-info → lino-25.3.0.dist-info}/licenses/COPYING +0 -0
lino/mixins/sequenced.py
CHANGED
@@ -33,7 +33,7 @@ class MoveByN(actions.Action):
|
|
33
33
|
This action is available on any :class:`Sequenced` object as
|
34
34
|
:attr:`Sequenced.move_by_n`.
|
35
35
|
|
36
|
-
It is currently only used by React to allow for drag and drop
|
36
|
+
It is currently only used by React to allow for drag and drop reordering.
|
37
37
|
|
38
38
|
"""
|
39
39
|
|
@@ -80,9 +80,11 @@ class MoveUp(actions.Action):
|
|
80
80
|
# label = _("Up")
|
81
81
|
# label = "\u2191" thin arrow up
|
82
82
|
# label = "\u25b2" # triangular arrow up
|
83
|
-
label = "
|
84
|
-
#
|
83
|
+
label = _("Move up")
|
84
|
+
# button_text = "\u25B2" # ▲ Black up-pointing triangle
|
85
|
+
button_text = "↑"
|
85
86
|
custom_handler = True
|
87
|
+
callable_from = "t"
|
86
88
|
# icon_name = 'arrow_up'
|
87
89
|
# ~ icon_file = 'arrow_up.png'
|
88
90
|
readonly = False
|
@@ -92,9 +94,12 @@ class MoveUp(actions.Action):
|
|
92
94
|
return False
|
93
95
|
if not super().get_action_permission(ar, obj, state):
|
94
96
|
return False
|
97
|
+
# if ar.order_by is None or "seqno" not in ar.order_by:
|
98
|
+
# return False
|
95
99
|
if ar.get_total_count() == 0:
|
96
100
|
return False
|
97
101
|
if ar.data_iterator[0] == obj:
|
102
|
+
# print(f"20250305 first of {ar.data_iterator}")
|
98
103
|
return False
|
99
104
|
# print("20161128", obj.seqno, ar.data_iterator.count())
|
100
105
|
return True
|
@@ -119,14 +124,16 @@ class MoveDown(actions.Action):
|
|
119
124
|
|
120
125
|
"""
|
121
126
|
|
127
|
+
label = _("Move down")
|
122
128
|
# label = _("Down")
|
123
|
-
|
129
|
+
button_text = "↓"
|
124
130
|
# label = "\u25bc" # triangular arrow down
|
125
131
|
# label = "\u2193"
|
126
|
-
|
132
|
+
# button_text = "\u25BC" # ▼ Black down-pointing triangle
|
127
133
|
# icon_name = 'arrow_down'
|
128
134
|
custom_handler = True
|
129
135
|
# ~ icon_file = 'arrow_down.png'
|
136
|
+
callable_from = "t"
|
130
137
|
readonly = False
|
131
138
|
|
132
139
|
def get_action_permission(self, ar, obj, state):
|
@@ -134,10 +141,13 @@ class MoveDown(actions.Action):
|
|
134
141
|
return False
|
135
142
|
if not super().get_action_permission(ar, obj, state):
|
136
143
|
return False
|
144
|
+
# if ar.order_by is None or "seqno" not in ar.order_by:
|
145
|
+
# return False
|
137
146
|
n = ar.get_total_count()
|
138
147
|
if n == 0:
|
139
148
|
return False
|
140
149
|
if ar.data_iterator[n - 1] == obj:
|
150
|
+
# print(f"20250305 last of {ar.data_iterator}")
|
141
151
|
return False
|
142
152
|
# ~ if obj.__class__.__name__=='Entry' and obj.seqno == 25:
|
143
153
|
# ~ print 20130706, ar.data_iterator.count(), ar.data_iterator
|
@@ -315,7 +325,8 @@ class Sequenced(Duplicable):
|
|
315
325
|
|
316
326
|
seq_no += 1
|
317
327
|
|
318
|
-
ar.success(
|
328
|
+
ar.success(
|
329
|
+
message=_("Renumbered {} of {} siblings.").format(n, qs.count()))
|
319
330
|
ar.set_response(refresh_all=True)
|
320
331
|
|
321
332
|
@fields.displayfield(_("Move"))
|
lino/modlib/__init__.py
CHANGED
lino/modlib/changes/models.py
CHANGED
@@ -64,7 +64,8 @@ class Change(UserAuthored):
|
|
64
64
|
related_name="changes_by_object",
|
65
65
|
)
|
66
66
|
object_id = GenericForeignKeyIdField(object_type, blank=True, null=True)
|
67
|
-
object = GenericForeignKey(
|
67
|
+
object = GenericForeignKey(
|
68
|
+
"object_type", "object_id", verbose_name=_("Object"))
|
68
69
|
|
69
70
|
master_type = dd.ForeignKey(
|
70
71
|
"contenttypes.ContentType",
|
@@ -74,9 +75,11 @@ class Change(UserAuthored):
|
|
74
75
|
related_name="changes_by_master",
|
75
76
|
)
|
76
77
|
master_id = GenericForeignKeyIdField(master_type, blank=True, null=True)
|
77
|
-
master = GenericForeignKey(
|
78
|
+
master = GenericForeignKey(
|
79
|
+
"master_type", "master_id", verbose_name=_("Master"))
|
78
80
|
|
79
|
-
diff = dd.RichTextField(_("Changes"), format="plain",
|
81
|
+
diff = dd.RichTextField(_("Changes"), format="plain",
|
82
|
+
blank=True, editable=False)
|
80
83
|
changed_fields = dd.CharField(_("Fields"), max_length=250, blank=True)
|
81
84
|
|
82
85
|
def __str__(self):
|
@@ -129,7 +132,8 @@ class Changes(dd.Table):
|
|
129
132
|
if pv.change_type:
|
130
133
|
qs = qs.filter(type=pv.change_type)
|
131
134
|
if pv.date:
|
132
|
-
qs = qs.filter(time__range=(
|
135
|
+
qs = qs.filter(time__range=(
|
136
|
+
pv.date, pv.date + datetime.timedelta(1)))
|
133
137
|
# if settings.SITE.user_model and ar.param_values.user:
|
134
138
|
# qs = qs.filter(user=ar.param_values.user)
|
135
139
|
if pv.object_type:
|
@@ -167,7 +171,9 @@ def log_change(type, request, master, obj, msg="", changed_fields=""):
|
|
167
171
|
remove_after = dd.plugins.changes.remove_after
|
168
172
|
if remove_after:
|
169
173
|
|
170
|
-
|
174
|
+
from lino.modlib.linod.choicelists import schedule_daily
|
175
|
+
|
176
|
+
@schedule_daily()
|
171
177
|
def delete_older_changes(ar):
|
172
178
|
days = datetime.timedelta(days=remove_after)
|
173
179
|
# django.core.exceptions.FieldError: Cannot resolve keyword 'time_lt' into field. Choices are: changed_fields, diff, id, list_item, master, master_id, master_type, master_type_id, name_column, navigation_panel, object, object_id, object_type, object_type_id, overview, time, type, user, user_id, workflow_buttons
|
@@ -206,7 +212,8 @@ def on_update(sender=None, watcher=None, request=None, **kw):
|
|
206
212
|
changes = []
|
207
213
|
for k, old, new in watcher.get_updates(cs.ignored_fields):
|
208
214
|
changed_fields += k + " "
|
209
|
-
changes.append("%s : %s --> %s" %
|
215
|
+
changes.append("%s : %s --> %s" %
|
216
|
+
(k, dd.obj2str(old), dd.obj2str(new)))
|
210
217
|
if len(changes) == 0:
|
211
218
|
msg = "(no changes)"
|
212
219
|
elif len(changes) == 1:
|
@@ -229,7 +236,8 @@ def on_delete(sender=None, request=None, **kw):
|
|
229
236
|
master = get_master(sender)
|
230
237
|
if master is None:
|
231
238
|
return
|
232
|
-
log_change(ChangeTypes.delete, request, master,
|
239
|
+
log_change(ChangeTypes.delete, request, master,
|
240
|
+
sender, dd.obj2str(sender, True))
|
233
241
|
|
234
242
|
|
235
243
|
@receiver(on_ui_created)
|
@@ -238,7 +246,8 @@ def on_ui_created(sender=None, request=None, **kw):
|
|
238
246
|
master = get_master(sender)
|
239
247
|
if master is None:
|
240
248
|
return
|
241
|
-
log_change(ChangeTypes.create, request, master,
|
249
|
+
log_change(ChangeTypes.create, request, master,
|
250
|
+
sender, dd.obj2str(sender, True))
|
242
251
|
|
243
252
|
|
244
253
|
@receiver(pre_add_child)
|
@@ -247,7 +256,8 @@ def on_add_child(sender=None, request=None, child=None, **kw):
|
|
247
256
|
if master is None:
|
248
257
|
return
|
249
258
|
log_change(
|
250
|
-
ChangeTypes.add_child, request, master, sender, dd.full_model_name(
|
259
|
+
ChangeTypes.add_child, request, master, sender, dd.full_model_name(
|
260
|
+
child)
|
251
261
|
)
|
252
262
|
|
253
263
|
|
@@ -257,7 +267,8 @@ def on_remove_child(sender=None, request=None, child=None, **kw):
|
|
257
267
|
if master is None:
|
258
268
|
return
|
259
269
|
log_change(
|
260
|
-
ChangeTypes.remove_child, request, master, sender, dd.full_model_name(
|
270
|
+
ChangeTypes.remove_child, request, master, sender, dd.full_model_name(
|
271
|
+
child)
|
261
272
|
)
|
262
273
|
|
263
274
|
|
lino/modlib/checkdata/models.py
CHANGED
@@ -12,6 +12,7 @@ from django.template.defaultfilters import pluralize
|
|
12
12
|
from lino.core.gfks import gfk2lookup
|
13
13
|
from lino.modlib.gfks.mixins import Controllable
|
14
14
|
from lino.modlib.users.mixins import UserAuthored
|
15
|
+
from lino.modlib.linod.choicelists import background_task
|
15
16
|
from lino.core.roles import SiteStaff
|
16
17
|
|
17
18
|
from lino.api import dd, rt, _
|
@@ -22,12 +23,27 @@ from .roles import CheckdataUser
|
|
22
23
|
from lino.core import constants
|
23
24
|
|
24
25
|
|
25
|
-
class
|
26
|
+
class CheckerAction(dd.Action):
|
27
|
+
fix_them = False
|
28
|
+
|
29
|
+
def run_it(self, ar, fix, checkers, objects):
|
30
|
+
if fix is None:
|
31
|
+
fix = self.fix_them
|
32
|
+
Message = rt.models.checkdata.Message
|
33
|
+
gfk = Message.owner
|
34
|
+
for obj in objects:
|
35
|
+
qs = Message.objects.filter(**gfk2lookup(gfk, obj))
|
36
|
+
qs.delete()
|
37
|
+
for chk in checkers:
|
38
|
+
chk.update_problems(ar, obj, False, fix)
|
39
|
+
ar.set_response(refresh=True)
|
40
|
+
|
41
|
+
|
42
|
+
class UpdateMessage(CheckerAction):
|
26
43
|
icon_name = "bell"
|
27
44
|
ui5_icon_name = "sap-icon://bell"
|
28
45
|
label = _("Check data")
|
29
46
|
combo_group = "checkdata"
|
30
|
-
fix_them = False
|
31
47
|
sort_index = 90
|
32
48
|
# custom_handler = True
|
33
49
|
# select_rows = False
|
@@ -47,11 +63,11 @@ class UpdateMessage(dd.Action):
|
|
47
63
|
# has been deleted.
|
48
64
|
obj.delete()
|
49
65
|
else:
|
50
|
-
|
51
|
-
|
52
|
-
)
|
53
|
-
qs.delete()
|
54
|
-
chk.update_problems(ar, owner, False, fix)
|
66
|
+
self.run_it(ar, fix, [chk], [owner])
|
67
|
+
# qs = Message.objects.filter(
|
68
|
+
# **gfk2lookup(Message.owner, owner, checker=chk))
|
69
|
+
# qs.delete()
|
70
|
+
# chk.update_problems(ar, owner, False, fix)
|
55
71
|
ar.set_response(refresh_all=True)
|
56
72
|
|
57
73
|
|
@@ -61,12 +77,11 @@ class FixProblem(UpdateMessage):
|
|
61
77
|
sort_index = 91
|
62
78
|
|
63
79
|
|
64
|
-
class UpdateMessagesByController(
|
80
|
+
class UpdateMessagesByController(CheckerAction):
|
65
81
|
icon_name = "bell"
|
66
82
|
ui5_icon_name = "sap-icon://bell"
|
67
83
|
label = _("Check data")
|
68
84
|
combo_group = "checkdata"
|
69
|
-
fix_them = False
|
70
85
|
required_roles = dd.login_required()
|
71
86
|
|
72
87
|
def __init__(self, model):
|
@@ -74,18 +89,19 @@ class UpdateMessagesByController(dd.Action):
|
|
74
89
|
super().__init__()
|
75
90
|
|
76
91
|
def run_from_ui(self, ar, fix=None):
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
92
|
+
self.run_it(ar, fix, get_checkers_for(self.model), ar.selected_rows)
|
93
|
+
# if fix is None:
|
94
|
+
# fix = self.fix_them
|
95
|
+
# Message = rt.models.checkdata.Message
|
96
|
+
# gfk = Message.owner
|
97
|
+
# checkers = get_checkers_for(self.model)
|
98
|
+
# for obj in ar.selected_rows:
|
99
|
+
# assert isinstance(obj, self.model)
|
100
|
+
# qs = Message.objects.filter(**gfk2lookup(gfk, obj))
|
101
|
+
# qs.delete()
|
102
|
+
# for chk in checkers:
|
103
|
+
# chk.update_problems(ar, obj, False, fix)
|
104
|
+
# ar.set_response(refresh=True)
|
89
105
|
|
90
106
|
|
91
107
|
class FixMessagesByController(UpdateMessagesByController):
|
@@ -93,6 +109,21 @@ class FixMessagesByController(UpdateMessagesByController):
|
|
93
109
|
fix_them = True
|
94
110
|
|
95
111
|
|
112
|
+
class FixAllProblems(CheckerAction):
|
113
|
+
select_rows = False
|
114
|
+
show_in_plain = True
|
115
|
+
# http_method = "POST"
|
116
|
+
label = _("Fix all data problems")
|
117
|
+
button_text = "✓" # u"\u2713"
|
118
|
+
fix_them = True
|
119
|
+
|
120
|
+
def run_from_ui(self, ar, fix=None):
|
121
|
+
mi = ar.master_instance
|
122
|
+
print(f"20250307 {mi}")
|
123
|
+
self.run_it(ar, fix, get_checkers_for(mi.__class__), [mi])
|
124
|
+
ar.set_response(refresh=True)
|
125
|
+
|
126
|
+
|
96
127
|
class Message(Controllable, UserAuthored):
|
97
128
|
class Meta(object):
|
98
129
|
app_label = "checkdata"
|
@@ -182,6 +213,8 @@ class MessagesByOwner(Messages):
|
|
182
213
|
column_names = "message checker user #fixable *"
|
183
214
|
default_display_modes = {None: constants.DISPLAY_MODE_SUMMARY}
|
184
215
|
|
216
|
+
fix_all_problems = FixAllProblems()
|
217
|
+
|
185
218
|
|
186
219
|
# This was the first use case of a slave table with something else than a model
|
187
220
|
# instance as its master
|
@@ -305,8 +338,10 @@ def check_data(ar, args=[], fix=True, prune=False):
|
|
305
338
|
assert not m._meta.abstract
|
306
339
|
if settings.SITE.is_hidden_plugin(m._meta.app_label):
|
307
340
|
continue
|
308
|
-
ct = rt.models.contenttypes.ContentType.objects.get_for_model(
|
309
|
-
|
341
|
+
ct = rt.models.contenttypes.ContentType.objects.get_for_model(
|
342
|
+
m)
|
343
|
+
qs = Message.objects.filter(
|
344
|
+
owner_type=ct, checker__in=checkers)
|
310
345
|
qs.delete()
|
311
346
|
name = str(m._meta.verbose_name_plural)
|
312
347
|
qs = m.objects.all()
|
@@ -346,7 +381,7 @@ def check_data(ar, args=[], fix=True, prune=False):
|
|
346
381
|
ar.logger.info(msg, done, what, found, fixed)
|
347
382
|
|
348
383
|
|
349
|
-
@
|
384
|
+
@background_task(every_unit="daily", every=1)
|
350
385
|
def checkdata(ar):
|
351
386
|
"""Run all data checkers."""
|
352
387
|
check_data(ar, fix=False)
|
@@ -32,9 +32,21 @@ plain1 = "Some plain text."
|
|
32
32
|
plain2 = "Two paragraphs of plain text.\n\nThe second paragraph."
|
33
33
|
# plain2 += " With an 👁 (U+1F441)." #5855 (Jane fails to store certain unicode characters)
|
34
34
|
|
35
|
+
imageDataURL = """data:image/png;base64,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"""
|
36
|
+
body_with_img = f"""\
|
37
|
+
<p>Here is an image:</p>
|
38
|
+
<p><img src="{imageDataURL}" class="bar"></p>\
|
39
|
+
"""
|
40
|
+
|
35
41
|
BODIES = Cycler(
|
36
42
|
[styled, table, lorem, short_lorem, breaking, cond_comment, plain1, plain2]
|
37
43
|
)
|
44
|
+
# Add two empty bodies that will be filled later:
|
45
|
+
BODIES.items.insert(0, "")
|
46
|
+
BODIES.items.insert(0, "")
|
47
|
+
|
48
|
+
if dd.is_installed('blogs'):
|
49
|
+
BODIES.items.append(body_with_img)
|
38
50
|
|
39
51
|
|
40
52
|
def objects():
|
@@ -44,9 +56,6 @@ def objects():
|
|
44
56
|
# use_linod = settings.SITE.use_linod
|
45
57
|
# settings.SITE.use_linod = False
|
46
58
|
|
47
|
-
# Add two empty bodies that will be filled later:
|
48
|
-
BODIES.items.insert(0, "")
|
49
|
-
BODIES.items.insert(0, "")
|
50
59
|
MENTIONED = Cycler()
|
51
60
|
for model in rt.models_by_base(Commentable):
|
52
61
|
if model.memo_command is not None:
|
lino/modlib/comments/models.py
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
# from html import escape
|
6
|
+
from .ui import *
|
7
|
+
from lino.modlib.checkdata.choicelists import Checker
|
6
8
|
from django.contrib.humanize.templatetags.humanize import naturaltime
|
7
9
|
from django.db import models
|
8
10
|
from django.db.models import Q
|
@@ -10,7 +12,7 @@ from django.core import validators
|
|
10
12
|
from django.utils.html import mark_safe, format_html, SafeString
|
11
13
|
from django.contrib.contenttypes.models import ContentType
|
12
14
|
from django.conf import settings
|
13
|
-
from lino.utils.html import E, tostring, fromstring
|
15
|
+
# from lino.utils.html import E, tostring, fromstring
|
14
16
|
|
15
17
|
from lino.api import dd, rt, _
|
16
18
|
|
@@ -144,7 +146,8 @@ class Comment(
|
|
144
146
|
u = ar.get_user()
|
145
147
|
if u.is_anonymous:
|
146
148
|
return
|
147
|
-
mr = rt.models.comments.Reaction.objects.filter(
|
149
|
+
mr = rt.models.comments.Reaction.objects.filter(
|
150
|
+
user=u, comment=self).first()
|
148
151
|
if mr:
|
149
152
|
return mr.emotion
|
150
153
|
|
@@ -399,7 +402,8 @@ class Reaction(CreatedModified, UserAuthored, DateRangeObservable):
|
|
399
402
|
|
400
403
|
allow_cascaded_delete = "user comment"
|
401
404
|
|
402
|
-
comment = dd.ForeignKey(
|
405
|
+
comment = dd.ForeignKey(
|
406
|
+
"comments.Comment", related_name="reactions_to_this")
|
403
407
|
emotion = Emotions.field(default="ok")
|
404
408
|
|
405
409
|
def as_summary_item(self, ar, text=None, **kwargs):
|
@@ -418,8 +422,6 @@ class Reaction(CreatedModified, UserAuthored, DateRangeObservable):
|
|
418
422
|
#
|
419
423
|
# mp.register_django_model('comment', Comment)
|
420
424
|
|
421
|
-
from lino.modlib.checkdata.choicelists import Checker
|
422
|
-
|
423
425
|
|
424
426
|
class CommentChecker(Checker):
|
425
427
|
# temporary checker to fix #4084 (Comment.owner is empty when replying to a comment)
|
@@ -436,5 +438,3 @@ class CommentChecker(Checker):
|
|
436
438
|
|
437
439
|
|
438
440
|
CommentChecker.activate()
|
439
|
-
|
440
|
-
from .ui import *
|
lino/modlib/comments/ui.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# Copyright 2013-2023 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
+
from lino.modlib.publisher.choicelists import PageFillers
|
5
6
|
from django.utils.translation import ngettext
|
6
7
|
from django.contrib.humanize.templatetags.humanize import naturaltime
|
7
8
|
from django.contrib.contenttypes.models import ContentType
|
@@ -125,7 +126,8 @@ class Comments(dd.Table):
|
|
125
126
|
|
126
127
|
@classmethod
|
127
128
|
def comments_created(cls, user, sd, ed):
|
128
|
-
pv = dict(user=user, start_date=sd, end_date=ed,
|
129
|
+
pv = dict(user=user, start_date=sd, end_date=ed,
|
130
|
+
observed_event=CommentEvents.created)
|
129
131
|
# pv = dict(start_date=sd, end_date=ed, observed_event=CommentEvents.created)
|
130
132
|
return cls.request(user=user, param_values=pv)
|
131
133
|
|
@@ -206,6 +208,7 @@ class CommentsByType(CommentsByX):
|
|
206
208
|
master_key = "comment_type"
|
207
209
|
column_names = "body created user *"
|
208
210
|
|
211
|
+
|
209
212
|
# TODO: rename CommentsByRFC to CommentsByOwner
|
210
213
|
class CommentsByRFC(CommentsByX):
|
211
214
|
master_key = "owner"
|
@@ -232,7 +235,8 @@ class CommentsByRFC(CommentsByX):
|
|
232
235
|
@classmethod
|
233
236
|
def param_defaults(cls, ar, **kw):
|
234
237
|
kw = super().param_defaults(ar, **kw)
|
235
|
-
|
238
|
+
if ar.display_mode == constants.DISPLAY_MODE_STORY:
|
239
|
+
kw["reply_to"] = constants.CHOICES_BLANK_FILTER_VALUE
|
236
240
|
return kw
|
237
241
|
|
238
242
|
# @classmethod
|
@@ -275,7 +279,8 @@ class CommentsByMentioned(CommentsByX):
|
|
275
279
|
assert not cls.model._meta.abstract
|
276
280
|
ct = ContentType.objects.get_for_model(cls.model)
|
277
281
|
mkw = gfk2lookup(Mention.target, mi, owner_type=ct)
|
278
|
-
mentions = Mention.objects.filter(
|
282
|
+
mentions = Mention.objects.filter(
|
283
|
+
**mkw).values_list("owner_id", flat=True)
|
279
284
|
# mentions = [o.comment_id for o in Mention.objects.filter(**mkw)]
|
280
285
|
# print(mkw, mentions)
|
281
286
|
# return super(CommentsByMentioned, cls).get_filter_kw(ar, **kw)
|
@@ -312,6 +317,4 @@ class ReactionsByComment(Reactions):
|
|
312
317
|
default_display_modes = {None: constants.DISPLAY_MODE_SUMMARY}
|
313
318
|
|
314
319
|
|
315
|
-
from lino.modlib.publisher.choicelists import PageFillers
|
316
|
-
|
317
320
|
PageFillers.add_item(RecentComments)
|
@@ -86,7 +86,8 @@ def ar2workbook(ar, column_names=None):
|
|
86
86
|
time = time.strip("-")
|
87
87
|
negative = True
|
88
88
|
time = time.split(":")
|
89
|
-
value = datetime.timedelta(
|
89
|
+
value = datetime.timedelta(
|
90
|
+
hours=int(time[0]), minutes=int(time[1]))
|
90
91
|
if negative: # Make negative.
|
91
92
|
value = value - value - value
|
92
93
|
elif iselement(value) or isinstance(value, SafeString):
|
@@ -111,7 +112,8 @@ def ar2workbook(ar, column_names=None):
|
|
111
112
|
cell.style = style
|
112
113
|
cell.value = value
|
113
114
|
except ValueError as e:
|
114
|
-
raise Exception("20190222 {} {}".format(
|
115
|
+
raise Exception("20190222 {} {}".format(
|
116
|
+
value.__class__, value))
|
115
117
|
|
116
118
|
return workbook
|
117
119
|
|
@@ -131,14 +133,14 @@ class ExportExcelAction(actions.Action):
|
|
131
133
|
def run_from_ui(self, ar, **kw):
|
132
134
|
# Prepare tmp file
|
133
135
|
mf = TmpMediaFile(ar, "xlsx")
|
134
|
-
settings.SITE.makedirs_if_missing(
|
136
|
+
settings.SITE.makedirs_if_missing(mf.path.parent)
|
135
137
|
|
136
138
|
# Render
|
137
|
-
self.render(ar, mf.
|
139
|
+
self.render(ar, mf.path)
|
138
140
|
|
139
141
|
# Tell client that the action was successful and that it
|
140
142
|
# should open a new browser window on the generated file.
|
141
|
-
ar.success(open_url=mf.
|
143
|
+
ar.success(open_url=mf.url)
|
142
144
|
|
143
145
|
def render(self, ar, file):
|
144
146
|
workbook = ar2workbook(ar)
|
lino/modlib/extjs/__init__.py
CHANGED
@@ -250,12 +250,12 @@ class Plugin(Plugin):
|
|
250
250
|
),
|
251
251
|
url(
|
252
252
|
rx + r"choices/(?P<app_label>\w+)/(?P<rptname>\w+)/"
|
253
|
-
"(?P<fldname>\w+)$",
|
253
|
+
r"(?P<fldname>\w+)$",
|
254
254
|
views.Choices.as_view(),
|
255
255
|
),
|
256
256
|
url(
|
257
257
|
rx + r"apchoices/(?P<app_label>\w+)/(?P<actor>\w+)/"
|
258
|
-
"(?P<an>\w+)/(?P<field>\w+)$",
|
258
|
+
r"(?P<an>\w+)/(?P<field>\w+)$",
|
259
259
|
views.ActionParamChoices.as_view(),
|
260
260
|
),
|
261
261
|
# the thread_id can be a negative number:
|