lino 24.10.3__py3-none-any.whl → 24.11.1__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 +1 -1
- lino/api/doctest.py +11 -10
- lino/api/rt.py +2 -3
- lino/config/admin_main_base.html +2 -2
- lino/core/actions.py +2 -4
- lino/core/actors.py +70 -35
- lino/core/choicelists.py +2 -2
- lino/core/dashboard.py +2 -1
- lino/core/dbtables.py +15 -15
- lino/core/elems.py +8 -4
- lino/core/fields.py +12 -3
- lino/core/inject.py +9 -2
- lino/core/kernel.py +11 -11
- lino/core/layouts.py +1 -1
- lino/core/model.py +25 -36
- lino/core/plugin.py +1 -0
- lino/core/renderer.py +21 -21
- lino/core/requests.py +94 -83
- lino/core/site.py +9 -90
- lino/core/store.py +16 -19
- lino/core/tables.py +0 -17
- lino/core/utils.py +32 -2
- lino/core/views.py +2 -1
- lino/help_texts.py +10 -5
- lino/locale/bn/LC_MESSAGES/django.po +1210 -907
- lino/locale/de/LC_MESSAGES/django.po +1760 -1375
- lino/locale/django.pot +1136 -906
- lino/locale/es/LC_MESSAGES/django.po +1709 -1347
- lino/locale/et/LC_MESSAGES/django.po +1206 -906
- lino/locale/fr/LC_MESSAGES/django.mo +0 -0
- lino/locale/fr/LC_MESSAGES/django.po +1193 -923
- lino/locale/nl/LC_MESSAGES/django.po +1247 -942
- lino/locale/pt_BR/LC_MESSAGES/django.po +1190 -903
- lino/locale/zh_Hant/LC_MESSAGES/django.po +1190 -903
- lino/management/commands/show.py +2 -4
- lino/mixins/periods.py +15 -7
- lino/mixins/polymorphic.py +3 -3
- lino/mixins/ref.py +6 -3
- lino/modlib/checkdata/__init__.py +3 -3
- lino/modlib/comments/choicelists.py +1 -1
- lino/modlib/comments/fixtures/demo2.py +4 -1
- lino/modlib/comments/mixins.py +9 -10
- lino/modlib/comments/models.py +4 -4
- lino/modlib/comments/ui.py +5 -0
- lino/modlib/extjs/ext_renderer.py +1 -1
- lino/modlib/linod/consumers.py +2 -3
- lino/modlib/linod/mixins.py +3 -2
- lino/modlib/memo/mixins.py +11 -209
- lino/modlib/notify/mixins.py +33 -32
- lino/modlib/periods/__init__.py +12 -1
- lino/modlib/periods/fixtures/std.py +2 -1
- lino/modlib/periods/mixins.py +0 -1
- lino/modlib/periods/models.py +79 -75
- lino/modlib/printing/actions.py +2 -0
- lino/modlib/printing/choicelists.py +3 -3
- lino/modlib/publisher/ui.py +2 -2
- lino/modlib/search/models.py +17 -11
- lino/modlib/system/__init__.py +0 -2
- lino/modlib/system/choicelists.py +55 -1
- lino/modlib/system/fixtures/__init__.py +0 -0
- lino/modlib/system/fixtures/std.py +5 -0
- lino/modlib/system/models.py +4 -2
- lino/modlib/uploads/__init__.py +10 -1
- lino/modlib/uploads/choicelists.py +3 -3
- lino/modlib/uploads/mixins.py +30 -32
- lino/modlib/uploads/models.py +89 -56
- lino/modlib/uploads/ui.py +12 -6
- lino/modlib/uploads/utils.py +107 -0
- lino/modlib/users/models.py +2 -2
- lino/modlib/weasyprint/__init__.py +2 -0
- lino/utils/__init__.py +14 -9
- lino/utils/djangotest.py +2 -1
- lino/utils/html.py +32 -1
- lino/utils/media.py +2 -3
- lino/utils/soup.py +311 -0
- {lino-24.10.3.dist-info → lino-24.11.1.dist-info}/METADATA +1 -3
- {lino-24.10.3.dist-info → lino-24.11.1.dist-info}/RECORD +80 -76
- {lino-24.10.3.dist-info → lino-24.11.1.dist-info}/WHEEL +1 -1
- {lino-24.10.3.dist-info → lino-24.11.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-24.10.3.dist-info → lino-24.11.1.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
lino/api/doctest.py
CHANGED
@@ -478,7 +478,7 @@ def walk_menu_items(username=None, severe=True):
|
|
478
478
|
print(s)
|
479
479
|
|
480
480
|
if settings.SITE.user_types_module:
|
481
|
-
ar =
|
481
|
+
ar = rt.login(username)
|
482
482
|
with translation.override(ar.user.language):
|
483
483
|
doit(ar)
|
484
484
|
else:
|
@@ -642,27 +642,28 @@ def pprint_json_string(s):
|
|
642
642
|
print(json.dumps(json.loads(s), indent=2, sort_keys=True, separators=(",", ": ")))
|
643
643
|
|
644
644
|
|
645
|
-
def show_dashboard(username, **options):
|
645
|
+
def show_dashboard(username, show_urls=False, **options):
|
646
646
|
"""Show the dashboard of the given user.
|
647
647
|
|
648
648
|
Useful options:
|
649
649
|
|
650
|
+
- show_urls=False
|
650
651
|
- ignore_links=True
|
651
652
|
|
652
653
|
For more options, see
|
653
654
|
https://pypi.org/project/html2text/ and
|
654
655
|
https://github.com/Alir3z4/html2text/blob/master/docs/usage.md
|
655
656
|
|
656
|
-
|
657
|
-
|
658
|
-
:mod:`django.contrib.humanize.templatetags.humanize`) ignores
|
659
|
-
therefore produces results that
|
657
|
+
This is currently not much used because the result is difficult to maintain.
|
658
|
+
One reason for this is that :func:`naturaltime` (from
|
659
|
+
:mod:`django.contrib.humanize.templatetags.humanize`) ignores
|
660
|
+
:attr:`lino.core.site.Site.the_demo_date` and therefore produces results that
|
661
|
+
depend on the current date/time.
|
660
662
|
|
661
663
|
"""
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
html = settings.SITE.get_main_html(ar) # , front_end=rnd.front_end)
|
664
|
+
renderer = settings.SITE.kernel.text_renderer
|
665
|
+
ar = rt.login(username, renderer=renderer, show_urls=show_urls)
|
666
|
+
html = settings.SITE.get_main_html(ar)
|
666
667
|
print(html2text(html, **options).strip())
|
667
668
|
|
668
669
|
|
lino/api/rt.py
CHANGED
@@ -15,7 +15,7 @@ from lino.core.exceptions import ChangedAPI
|
|
15
15
|
|
16
16
|
# actors = settings.SITE.models
|
17
17
|
|
18
|
-
login =
|
18
|
+
# login = rt.login
|
19
19
|
startup = settings.SITE.startup
|
20
20
|
# get_printable_context = settings.SITE.get_printable_context
|
21
21
|
lookup_filter = settings.SITE.lookup_filter
|
@@ -32,8 +32,7 @@ def get_template(*args, **kw):
|
|
32
32
|
return settings.SITE.plugins.jinja.renderer.jinja_env.get_template(*args, **kw)
|
33
33
|
|
34
34
|
|
35
|
-
|
36
|
-
return login().show(*args, **kw)
|
35
|
+
from lino.core.utils import login, show, shows
|
37
36
|
|
38
37
|
|
39
38
|
# def send_email(*args, **kw):
|
lino/config/admin_main_base.html
CHANGED
@@ -100,8 +100,8 @@
|
|
100
100
|
|
101
101
|
{% block admin_main_items %}
|
102
102
|
{% if not ar.renderer.support_dashboard_layout %}
|
103
|
-
{% for
|
104
|
-
{{''.join(
|
103
|
+
{% for di in user.get_preferences().dashboard_items %}
|
104
|
+
{{''.join(di.render(ar))}}
|
105
105
|
{% endfor %}
|
106
106
|
{% endif %}
|
107
107
|
{% endblock %}
|
lino/core/actions.py
CHANGED
@@ -87,7 +87,7 @@ def install_layout(cls, k, layout_class, **options):
|
|
87
87
|
- `cls` is the actor (a class object)
|
88
88
|
|
89
89
|
- `k` is one of 'grid_layout', 'detail_layout', 'insert_layout',
|
90
|
-
'params_layout', 'card_layout'
|
90
|
+
'params_layout', 'card_layout'
|
91
91
|
|
92
92
|
- `layout_class`
|
93
93
|
|
@@ -575,7 +575,7 @@ class Action(Parametrizable, Permittable):
|
|
575
575
|
|
576
576
|
def is_window_action(self):
|
577
577
|
"""Return `True` if this is a "window action" (i.e. which opens a GUI
|
578
|
-
window on the client before
|
578
|
+
window on the client before executing).
|
579
579
|
|
580
580
|
"""
|
581
581
|
return self.opens_a_window or (self.parameters and not self.no_params_window)
|
@@ -805,9 +805,7 @@ class ShowTable(TableAction):
|
|
805
805
|
return self.label or self.defining_actor.label
|
806
806
|
|
807
807
|
def get_window_layout(self, actor):
|
808
|
-
# ~ return self.actor.list_layout
|
809
808
|
return None
|
810
|
-
# return actor.card_layout or actor.list_layout # 20210910
|
811
809
|
|
812
810
|
def get_window_size(self, actor):
|
813
811
|
return actor.window_size
|
lino/core/actors.py
CHANGED
@@ -39,7 +39,8 @@ from lino.core.utils import ParameterPanel
|
|
39
39
|
from lino.core.utils import navinfo, dbfield2params_field
|
40
40
|
from lino.utils import curry, AttrDict, is_string
|
41
41
|
|
42
|
-
from lino.utils.html import E, forcetext, tostring,
|
42
|
+
from lino.utils.html import E, forcetext, tostring, Grouper, SAFE_EMPTY
|
43
|
+
# from lino.utils.html import assert_safe
|
43
44
|
|
44
45
|
from .roles import SiteUser
|
45
46
|
|
@@ -283,6 +284,12 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
283
284
|
only_fields = None
|
284
285
|
|
285
286
|
default_display_modes = None
|
287
|
+
"""
|
288
|
+
Which :term:`display mode` to use in a :term:`slave panel`,
|
289
|
+
depending on available width.
|
290
|
+
|
291
|
+
See :ref:`dg.table.default_display_modes`.
|
292
|
+
"""
|
286
293
|
|
287
294
|
# extra_display_modes = set()
|
288
295
|
# extra_display_modes = {constants.DISPLAY_MODE_SUMMARY}
|
@@ -432,11 +439,13 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
432
439
|
detail_layout = None
|
433
440
|
insert_layout = None
|
434
441
|
card_layout = None
|
435
|
-
list_layout = None
|
442
|
+
list_layout = None # no longer used
|
436
443
|
|
437
444
|
detail_template = None # deprecated: use insert_layout instead
|
438
445
|
insert_template = None # deprecated: use detail_layout instead
|
439
446
|
|
447
|
+
row_template = "{row}"
|
448
|
+
|
440
449
|
help_text = None
|
441
450
|
detail_action = None
|
442
451
|
update_action = None
|
@@ -502,6 +511,14 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
502
511
|
def is_installed(self):
|
503
512
|
return settings.SITE.is_installed(self.app_label)
|
504
513
|
|
514
|
+
@classmethod
|
515
|
+
def before_group_change(cls, gh, row):
|
516
|
+
return SAFE_EMPTY
|
517
|
+
|
518
|
+
@classmethod
|
519
|
+
def after_group_change(cls, gh, row):
|
520
|
+
return SAFE_EMPTY
|
521
|
+
|
505
522
|
@classmethod
|
506
523
|
def is_hidden(self):
|
507
524
|
return settings.SITE.is_hidden_plugin(self.app_label)
|
@@ -706,8 +723,10 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
706
723
|
pass
|
707
724
|
|
708
725
|
@classmethod
|
709
|
-
def row_as_summary(cls, ar, obj,
|
710
|
-
|
726
|
+
def row_as_summary(cls, ar, obj, text=None, **kwargs):
|
727
|
+
if ar is None:
|
728
|
+
return text or str(obj)
|
729
|
+
return obj.as_summary_item(ar, text, **kwargs)
|
711
730
|
|
712
731
|
@classmethod
|
713
732
|
def do_setup(self):
|
@@ -817,7 +836,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
817
836
|
window_size=(cls.insert_layout_width, "auto"),
|
818
837
|
)
|
819
838
|
actions.install_layout(cls, "card_layout", layouts.DetailLayout)
|
820
|
-
actions.install_layout(cls, "list_layout", layouts.DetailLayout)
|
839
|
+
# actions.install_layout(cls, "list_layout", layouts.DetailLayout)
|
821
840
|
|
822
841
|
cls.extra_layouts = dict()
|
823
842
|
for name, main in cls.get_extra_layouts():
|
@@ -1775,37 +1794,37 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1775
1794
|
for k, pf in self.parameters.items():
|
1776
1795
|
# if not isinstance(pf, fields.DummyField):
|
1777
1796
|
kw[k] = pf.get_default()
|
1797
|
+
if self.model is not None:
|
1798
|
+
kw = self.model.param_defaults(ar, **kw)
|
1778
1799
|
return kw
|
1779
1800
|
|
1780
1801
|
@classmethod
|
1781
|
-
def request(
|
1782
|
-
"""
|
1783
|
-
|
1784
|
-
"""
|
1785
|
-
kw.update(actor=self)
|
1786
|
-
from lino.core.requests import ActionRequest
|
1787
|
-
return ActionRequest(*args, **kw)
|
1802
|
+
def request(cls, master_instance=None, **kwargs):
|
1803
|
+
"""Return a new :class:`ActionRequest
|
1804
|
+
<lino.core.requests.ActionRequest>` on this actor.
|
1788
1805
|
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
Return an action request on this actor which inherits from the
|
1793
|
-
given parent request.
|
1806
|
+
The :attr:`master_instance
|
1807
|
+
<lino.core.requests.ActionRequest.master_instance>` can be
|
1808
|
+
specified as optional first positional argument.
|
1794
1809
|
|
1795
|
-
Deprecated. Rather call cls.request(parent=ar)
|
1796
1810
|
"""
|
1797
|
-
|
1798
|
-
|
1799
|
-
)
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
return
|
1811
|
+
from lino.core.requests import ActionRequest
|
1812
|
+
kwargs.update(actor=cls)
|
1813
|
+
kwargs.setdefault("action", cls.default_action)
|
1814
|
+
if master_instance is not None:
|
1815
|
+
kwargs.update(master_instance=master_instance)
|
1816
|
+
# kw.setdefault("renderer", settings.SITE.kernel.text_renderer)
|
1817
|
+
return ActionRequest(**kwargs)
|
1818
|
+
|
1819
|
+
# @classmethod
|
1820
|
+
# def show(cls, master_instance=None, renderer=None, **kwargs):
|
1821
|
+
# if renderer is None:
|
1822
|
+
# renderer = settings.SITE.kernel.text_renderer
|
1823
|
+
# ar = cls.request(master_instance, renderer=renderer)
|
1824
|
+
# ar.show(**kwargs)
|
1804
1825
|
|
1805
1826
|
@classmethod
|
1806
1827
|
def to_html(self, **kw):
|
1807
|
-
""" """
|
1808
|
-
# ~ settings.SITE.startup()
|
1809
1828
|
return tostring(self.request(**kw).table2xhtml())
|
1810
1829
|
|
1811
1830
|
@classmethod
|
@@ -1828,7 +1847,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1828
1847
|
# print(f"20240914 slave_as_html() {ar.request}")
|
1829
1848
|
|
1830
1849
|
# 20240911 We don't want to re-parse the original request, especially
|
1831
|
-
# because it might contain disturbing things like selected_pks. But
|
1850
|
+
# because it might contain disturbing things like selected_pks. But the
|
1832
1851
|
# slave must at least inherit the user, as shown in
|
1833
1852
|
# welfare/docs/specs/weleup/weleup1r.rst
|
1834
1853
|
# kwargs.update(request=ar.request)
|
@@ -1836,15 +1855,12 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1836
1855
|
kwargs.update(renderer=settings.SITE.kernel.default_renderer)
|
1837
1856
|
try:
|
1838
1857
|
ar = cls.request(master_instance=master, **kwargs)
|
1839
|
-
el =
|
1840
|
-
toolbar = ar.plain_toolbar_buttons()
|
1858
|
+
el = cls.table_as_html(ar)
|
1841
1859
|
except Exception as e:
|
1842
1860
|
msg = f"20241004 Error in {repr(ar)}: {e}"
|
1843
1861
|
raise Exception(msg) from e
|
1844
1862
|
logger.warning(msg)
|
1845
1863
|
return msg
|
1846
|
-
if len(toolbar):
|
1847
|
-
el = E.div(el, E.p(*toolbar))
|
1848
1864
|
return el
|
1849
1865
|
|
1850
1866
|
# summary_sep = "<br/>"
|
@@ -1854,7 +1870,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1854
1870
|
def get_table_as_list(cls, obj, ar):
|
1855
1871
|
# raise Exception("20240316")
|
1856
1872
|
sar = cls.request(parent=ar, master_instance=obj, is_on_main_actor=False)
|
1857
|
-
|
1873
|
+
grp = Grouper(sar)
|
1874
|
+
html_text = grp.begin()
|
1858
1875
|
for i, obj in enumerate(sar.data_iterator):
|
1859
1876
|
if i == cls.preview_limit:
|
1860
1877
|
break
|
@@ -1870,7 +1887,10 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1870
1887
|
# else: # a funny way to debug:
|
1871
1888
|
# par = '<a href="{}">{}</a>'.format(str(sar.renderer), par)
|
1872
1889
|
|
1890
|
+
html_text += grp.before_row(obj)
|
1873
1891
|
html_text += par
|
1892
|
+
html_text += grp.after_row(obj)
|
1893
|
+
html_text += grp.stop()
|
1874
1894
|
|
1875
1895
|
if cls.editable and cls.insert_action is not None:
|
1876
1896
|
ir = cls.insert_action.request_from(sar)
|
@@ -1884,7 +1904,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1884
1904
|
@classmethod
|
1885
1905
|
def get_table_story(cls, obj, ar):
|
1886
1906
|
sar = cls.request(parent=ar, master_instance=obj, is_on_main_actor=False)
|
1887
|
-
html =
|
1907
|
+
html = SAFE_EMPTY
|
1888
1908
|
for i, obj in enumerate(sar.data_iterator):
|
1889
1909
|
if i == cls.preview_limit:
|
1890
1910
|
break
|
@@ -1901,7 +1921,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1901
1921
|
return html
|
1902
1922
|
|
1903
1923
|
@classmethod
|
1904
|
-
def get_table_summary(cls, obj, ar):
|
1924
|
+
def get_table_summary(cls, obj, ar=None):
|
1905
1925
|
"""
|
1906
1926
|
Return the HTML `<div>` to be displayed by
|
1907
1927
|
:class:`lino.core.elems.TableSummaryPanel`.
|
@@ -1952,6 +1972,21 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1952
1972
|
p += tostring(b) + btn_sep
|
1953
1973
|
return p
|
1954
1974
|
|
1975
|
+
@classmethod
|
1976
|
+
def table_as_html(cls, ar):
|
1977
|
+
"""
|
1978
|
+
Return an ElementTree element that represents the given action
|
1979
|
+
request `ar` on this actor in :term:`display mode` "HTML".
|
1980
|
+
|
1981
|
+
An :term:`application developer` may override this method. Usage example
|
1982
|
+
is :class:`lino_prima.lib.prima.PupilsAndProjects`.
|
1983
|
+
|
1984
|
+
"""
|
1985
|
+
el = ar.table2xhtml()
|
1986
|
+
if len(toolbar := ar.plain_toolbar_buttons()):
|
1987
|
+
el = E.div(el, E.p(*toolbar))
|
1988
|
+
return el
|
1989
|
+
|
1955
1990
|
@classmethod
|
1956
1991
|
def columns_to_paragraph(cls, self, ar=None, fmt=None):
|
1957
1992
|
"""
|
lino/core/choicelists.py
CHANGED
@@ -246,9 +246,9 @@ Django creates copies of them when inheriting models.
|
|
246
246
|
def get_chooser_for_field(cls, fieldname):
|
247
247
|
return None
|
248
248
|
|
249
|
-
def as_summary_item(self, ar,
|
249
|
+
def as_summary_item(self, ar, text=None, **kwargs):
|
250
250
|
# needed by `detail_pointer`
|
251
|
-
return str(self)
|
251
|
+
return text or str(self)
|
252
252
|
|
253
253
|
|
254
254
|
class UnresolvedValue(Choice):
|
lino/core/dashboard.py
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
|
6
6
|
"""
|
7
7
|
|
8
|
+
from django.conf import settings
|
8
9
|
from lino.api import _
|
9
10
|
from lino.core.permissions import Permittable
|
10
11
|
from lino.core.requests import ActionRequest
|
@@ -148,7 +149,7 @@ class ActorItem(DashboardItem):
|
|
148
149
|
# from lino.core.tables import AbstractTable
|
149
150
|
T = self.actor
|
150
151
|
# if isinstance(T, AbstractTable):
|
151
|
-
sar = T.request(limit=T.preview_limit, parent=ar)
|
152
|
+
sar = T.request(limit=T.preview_limit, parent=ar) #, renderer=settings.SITE.kernel.default_renderer)
|
152
153
|
# sar = ar.spawn(T, limit=T.preview_limit)
|
153
154
|
# sar = ar.spawn_request(actor=T, limit=T.preview_limit)
|
154
155
|
# raise Exception("20230331 {}".format(ar.subst_user))
|
lino/core/dbtables.py
CHANGED
@@ -201,26 +201,26 @@ class Table(AbstractTable):
|
|
201
201
|
"""If when in a detail view will override default param values with the detail's pv values.
|
202
202
|
"""
|
203
203
|
|
204
|
-
react_responsive = True
|
205
|
-
"""If viewing the grid view on a mobile, should the grid use responsive mode
|
206
|
-
Default: True"""
|
204
|
+
# react_responsive = True
|
205
|
+
# """If viewing the grid view on a mobile, should the grid use responsive mode
|
206
|
+
# Default: True"""
|
207
207
|
|
208
208
|
# react_big_search = False
|
209
209
|
"""If True will position the quick search input to the bottom of the header and have it full width.
|
210
210
|
Default: False"""
|
211
211
|
|
212
|
-
@classmethod
|
213
|
-
def init_layouts(cls):
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
212
|
+
# @classmethod
|
213
|
+
# def init_layouts(cls):
|
214
|
+
# if cls.model is not None and issubclass(cls.model, Model):
|
215
|
+
# if not cls.abstract:
|
216
|
+
# for tbl in cls.__mro__:
|
217
|
+
# # print("20210629", tbl)
|
218
|
+
# if "list_layout" in tbl.__dict__:
|
219
|
+
# break
|
220
|
+
# if issubclass(tbl, actors.Actor):
|
221
|
+
# cls.list_layout = "list_item"
|
222
|
+
# break
|
223
|
+
# super().init_layouts()
|
224
224
|
|
225
225
|
@classmethod
|
226
226
|
def add_quick_search_filter(cls, qs, search_text):
|
lino/core/elems.py
CHANGED
@@ -671,7 +671,7 @@ class FieldElement(LayoutElement):
|
|
671
671
|
return kw
|
672
672
|
|
673
673
|
def ext_options(self, **kw):
|
674
|
-
kw =
|
674
|
+
kw = super().ext_options(**kw)
|
675
675
|
kw.update(self.get_field_options())
|
676
676
|
return kw
|
677
677
|
|
@@ -1565,6 +1565,10 @@ class BooleanDisplayElement(DisplayElement):
|
|
1565
1565
|
# kw.update(always_enabled=True)
|
1566
1566
|
FieldElement.__init__(self, *args, **kw)
|
1567
1567
|
|
1568
|
+
def value2html(self, ar, v, **cellattrs):
|
1569
|
+
txt = self.format_value(ar, v)
|
1570
|
+
return E.td(txt, **cellattrs)
|
1571
|
+
|
1568
1572
|
|
1569
1573
|
class BooleanFieldElement(FieldElement):
|
1570
1574
|
value_template = "new Ext.form.Checkbox(%s)"
|
@@ -2534,7 +2538,7 @@ class TabPanel(Panel):
|
|
2534
2538
|
# self.reactive_elem_name = actor.reactive_elem_name
|
2535
2539
|
# super().__init__(lh, actor, **kw)
|
2536
2540
|
|
2537
|
-
_FIELD2ELEM =
|
2541
|
+
_FIELD2ELEM = [
|
2538
2542
|
# (dd.Constant, ConstantElement),
|
2539
2543
|
(fields.RecurrenceField, RecurrenceElement),
|
2540
2544
|
(fields.DelayedHtmlBox, DisplayElement),
|
@@ -2555,7 +2559,7 @@ _FIELD2ELEM = (
|
|
2555
2559
|
(models.JSONField, CharFieldElement), # workaround
|
2556
2560
|
(fields.PasswordField, PasswordFieldElement),
|
2557
2561
|
(models.CharField, CharFieldElement),
|
2558
|
-
(fields.MeasurementField, CharFieldElement),
|
2562
|
+
# (fields.MeasurementField, CharFieldElement),
|
2559
2563
|
(fields.MonthField, MonthFieldElement),
|
2560
2564
|
(models.DateTimeField, DateTimeFieldElement),
|
2561
2565
|
(fields.DatePickerField, DatePickerFieldElement),
|
@@ -2569,7 +2573,7 @@ _FIELD2ELEM = (
|
|
2569
2573
|
(models.NullBooleanField, BooleanFieldElement),
|
2570
2574
|
# (models.ManyToManyField, M2mGridElement),
|
2571
2575
|
(models.ForeignKey, ForeignKeyElement),
|
2572
|
-
|
2576
|
+
]
|
2573
2577
|
|
2574
2578
|
TRIGGER_BUTTON_WIDTH = 3
|
2575
2579
|
|
lino/core/fields.py
CHANGED
@@ -1264,6 +1264,10 @@ class TableRow(object):
|
|
1264
1264
|
"""
|
1265
1265
|
return []
|
1266
1266
|
|
1267
|
+
@classmethod
|
1268
|
+
def param_defaults(self, ar, **kw):
|
1269
|
+
return kw
|
1270
|
+
|
1267
1271
|
@classmethod
|
1268
1272
|
def get_title_tags(self, ar):
|
1269
1273
|
return []
|
@@ -1353,6 +1357,8 @@ class TableRow(object):
|
|
1353
1357
|
|
1354
1358
|
@htmlbox()
|
1355
1359
|
def list_item(self, ar):
|
1360
|
+
if ar is None:
|
1361
|
+
return escape(str(self))
|
1356
1362
|
return self.as_paragraph(ar)
|
1357
1363
|
|
1358
1364
|
def get_overview_elems(self, ar):
|
@@ -1363,9 +1369,15 @@ class TableRow(object):
|
|
1363
1369
|
# must return an ET element
|
1364
1370
|
if ar is None:
|
1365
1371
|
return text or str(self)
|
1372
|
+
if text is None and ar.actor is not None:
|
1373
|
+
text = ar.actor.row_template.format(row=self)
|
1374
|
+
# raise Exception("20241029")
|
1366
1375
|
return ar.obj2html(self, text, **kwargs)
|
1367
1376
|
|
1368
1377
|
def as_paragraph(self, ar, **kwargs):
|
1378
|
+
# must return a safe html string
|
1379
|
+
if ar is None:
|
1380
|
+
return escape(str(self))
|
1369
1381
|
return tostring(self.as_summary_item(ar, **kwargs))
|
1370
1382
|
|
1371
1383
|
def as_story_item(self, ar, **kwargs):
|
@@ -1752,6 +1764,3 @@ def choices_for_field(ar, holder, field):
|
|
1752
1764
|
else:
|
1753
1765
|
raise http.Http404("No choices for %s" % field)
|
1754
1766
|
return (qs, row2dict)
|
1755
|
-
|
1756
|
-
|
1757
|
-
from lino_xl.lib.measurements.fields import MeasurementField
|
lino/core/inject.py
CHANGED
@@ -111,15 +111,22 @@ def check_pending_injects(sender, models_list=None, **kw):
|
|
111
111
|
# raise Exception(20150304)
|
112
112
|
# called from kernel.analyze_models()
|
113
113
|
# ~ logger.info("20130212 check_pending_injects()...")
|
114
|
+
# if PENDING_INJECTS:
|
115
|
+
# for spec, todos in PENDING_INJECTS.items():
|
116
|
+
# model = resolve_model(spec, strict=True)
|
117
|
+
# if todos is not None:
|
118
|
+
# for func, caller in todos:
|
119
|
+
# func(model)
|
120
|
+
|
114
121
|
if PENDING_INJECTS:
|
115
122
|
msg = ""
|
116
|
-
for spec, funcs in
|
123
|
+
for spec, funcs in PENDING_INJECTS.items():
|
117
124
|
msg += spec + ": "
|
118
125
|
msg += ", ".join([fmt(f) for f in funcs])
|
119
126
|
# ~ msg += '\n'.join([str(dir(func)) for func in funcs])
|
120
127
|
# ~ msg += '\n'.join([str(func.func_code.co_consts) for func in funcs])
|
121
128
|
# ~ msg += str(funcs)
|
122
|
-
raise Exception("Oops, there are pending injects:
|
129
|
+
raise Exception(f"Oops, there are pending injects: {msg}")
|
123
130
|
# ~ logger.warning("pending injects: %s", msg)
|
124
131
|
|
125
132
|
# ~ logger.info("20131110 no pending injects")
|
lino/core/kernel.py
CHANGED
@@ -298,8 +298,11 @@ class Kernel(object):
|
|
298
298
|
# if f.__class__ is models.CharField and f.null:
|
299
299
|
# msg = "Nullable CharField %s in %s" % (f.name, model)
|
300
300
|
# raise Exception(msg)
|
301
|
+
|
301
302
|
if isinstance(f, models.ForeignKey):
|
303
|
+
# f.remote_field.model = resolve_model(f.remote_field.model)
|
302
304
|
if isinstance(f.remote_field.model, str):
|
305
|
+
# models_list = [f"{m}({m._meta.abstract})".format(m) for m in models_list]
|
303
306
|
raise Exception(
|
304
307
|
"Could not resolve target %r of "
|
305
308
|
"ForeignKey '%s' in %s "
|
@@ -308,12 +311,10 @@ class Kernel(object):
|
|
308
311
|
)
|
309
312
|
|
310
313
|
set_default_verbose_name(f)
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
to a Company as well.
|
316
|
-
"""
|
314
|
+
# If JobProvider is an MTI child of Company,
|
315
|
+
# then mti.delete_child(JobProvider) must not fail on a
|
316
|
+
# JobProvider being referred only by objects that can refer
|
317
|
+
# to a Company as well.
|
317
318
|
if not hasattr(f.remote_field.model, "_lino_ddh"):
|
318
319
|
msg = "20150824 {1} (needed by {0}) " "has no _lino_ddh"
|
319
320
|
raise Exception(
|
@@ -867,7 +868,7 @@ class Kernel(object):
|
|
867
868
|
every actor handle because it potentially requires other actor
|
868
869
|
handles to be instantiated.
|
869
870
|
|
870
|
-
ar is usually None, except for actors with dynamic handle
|
871
|
+
`ar` is usually None, except for actors with dynamic handle
|
871
872
|
"""
|
872
873
|
# logger.info('20121010 Kernel.setup_handle() %s', h.actor)
|
873
874
|
|
@@ -877,10 +878,9 @@ class Kernel(object):
|
|
877
878
|
|
878
879
|
if isinstance(h, tables.TableHandle):
|
879
880
|
he = set(h.actor.hidden_columns | h.actor.hidden_elements)
|
880
|
-
|
881
|
-
h.actor.get_column_names(ar), h.actor, hidden_elements=he
|
882
|
-
)
|
883
|
-
h.grid_layout = gl.get_layout_handle()
|
881
|
+
cl = layouts.ColumnsLayout(
|
882
|
+
h.actor.get_column_names(ar), h.actor, hidden_elements=he)
|
883
|
+
h.grid_layout = cl.get_layout_handle()
|
884
884
|
else:
|
885
885
|
h.grid_layout = None
|
886
886
|
|
lino/core/layouts.py
CHANGED
@@ -785,7 +785,7 @@ class ColumnsLayout(FieldLayout):
|
|
785
785
|
def set_datasource(self, ds):
|
786
786
|
if ds is None:
|
787
787
|
raise Exception("20130327 No datasource for %r" % self)
|
788
|
-
super(
|
788
|
+
super().set_datasource(ds)
|
789
789
|
|
790
790
|
|
791
791
|
class ParamsLayout(BaseLayout):
|