lino 24.9.4__py3-none-any.whl → 24.10.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 -5
- lino/api/doctest.py +29 -6
- lino/core/__init__.py +0 -1
- lino/core/actions.py +16 -9
- lino/core/actors.py +99 -30
- lino/core/choicelists.py +28 -11
- lino/core/constants.py +20 -4
- lino/core/dashboard.py +19 -18
- lino/core/dbtables.py +49 -60
- lino/core/elems.py +26 -33
- lino/core/fields.py +13 -7
- lino/core/kernel.py +3 -3
- lino/core/model.py +5 -2
- lino/core/renderer.py +52 -39
- lino/core/requests.py +876 -299
- lino/core/store.py +17 -17
- lino/core/tables.py +46 -32
- lino/core/utils.py +134 -0
- lino/mixins/dupable.py +1 -1
- lino/modlib/bootstrap3/views.py +4 -3
- lino/modlib/checkdata/models.py +1 -1
- lino/modlib/comments/mixins.py +2 -2
- lino/modlib/comments/ui.py +83 -77
- lino/modlib/dupable/models.py +1 -1
- lino/modlib/export_excel/models.py +0 -3
- lino/modlib/extjs/ext_renderer.py +8 -8
- lino/modlib/extjs/views.py +8 -17
- lino/modlib/forms/views.py +3 -3
- lino/modlib/help/management/commands/makehelp.py +1 -1
- lino/modlib/notify/models.py +1 -1
- lino/modlib/odata/views.py +2 -2
- lino/modlib/printing/actions.py +0 -5
- lino/modlib/publisher/ui.py +3 -3
- lino/modlib/publisher/views.py +14 -11
- lino/modlib/search/models.py +2 -2
- lino/modlib/system/mixins.py +0 -10
- lino/modlib/uploads/mixins.py +6 -3
- lino/modlib/uploads/ui.py +2 -2
- lino/modlib/users/mixins.py +5 -5
- lino/sphinxcontrib/actordoc.py +1 -1
- lino/sphinxcontrib/logo/static/linodocs.css +1 -8
- lino/utils/choosers.py +1 -1
- lino/utils/report.py +4 -11
- {lino-24.9.4.dist-info → lino-24.10.1.dist-info}/METADATA +1 -1
- {lino-24.9.4.dist-info → lino-24.10.1.dist-info}/RECORD +48 -49
- lino/core/tablerequest.py +0 -758
- {lino-24.9.4.dist-info → lino-24.10.1.dist-info}/WHEEL +0 -0
- {lino-24.9.4.dist-info → lino-24.10.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-24.9.4.dist-info → lino-24.10.1.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
@@ -26,11 +26,7 @@ defines no models, some template files, a series of :term:`django-admin commands
|
|
26
26
|
|
27
27
|
"""
|
28
28
|
|
29
|
-
__version__ = '24.
|
30
|
-
|
31
|
-
# from __future__ import unicode_literals
|
32
|
-
# from __future__ import absolute_import
|
33
|
-
# from builtins import str
|
29
|
+
__version__ = '24.10.1'
|
34
30
|
|
35
31
|
# import setuptools # avoid UserWarning "Distutils was imported before Setuptools"?
|
36
32
|
|
lino/api/doctest.py
CHANGED
@@ -7,9 +7,9 @@ A selection of names to be used in tested documents.
|
|
7
7
|
|
8
8
|
import six # TODO: remove here and then run all doctests
|
9
9
|
import logging
|
10
|
-
import django
|
11
10
|
import sqlparse
|
12
|
-
|
11
|
+
from urllib.parse import urlencode
|
12
|
+
import django
|
13
13
|
django.setup()
|
14
14
|
from lino.core.constants import *
|
15
15
|
from lino.api.shell import *
|
@@ -63,12 +63,18 @@ HttpQuery = collections.namedtuple(
|
|
63
63
|
|
64
64
|
def get_json_dict(username, uri, an="detail", **kwargs):
|
65
65
|
url = "/api/{0}?fmt=json&an={1}".format(uri, an)
|
66
|
-
|
67
|
-
url += "&
|
66
|
+
if kwargs:
|
67
|
+
url += "&" + urlencode(kwargs, True)
|
68
|
+
# for k, v in kwargs.items():
|
69
|
+
# url += "&{}={}".format(k, v)
|
68
70
|
test_client.force_login(rt.login(username).user)
|
69
71
|
res = test_client.get(url, REMOTE_USER=username)
|
70
72
|
assert res.status_code == 200
|
71
|
-
|
73
|
+
s = res.content.decode()
|
74
|
+
try:
|
75
|
+
return json.loads(s)
|
76
|
+
except Exception as e:
|
77
|
+
raise Exception(f"GET {url} got non-JSON response:\n{s}") from None
|
72
78
|
|
73
79
|
|
74
80
|
def get_json_soup(username, uri, fieldname, **kwargs):
|
@@ -314,7 +320,7 @@ def get_fields(model, fieldnames=None, columns=None):
|
|
314
320
|
get_field = model.get_data_elem
|
315
321
|
if fieldnames is None:
|
316
322
|
fieldnames = model.column_names
|
317
|
-
# get_handle().
|
323
|
+
# get_handle().grid_layout.main.columns
|
318
324
|
else:
|
319
325
|
get_field = model.parameters.get
|
320
326
|
if fieldnames is None:
|
@@ -773,3 +779,20 @@ def show_change_watchers():
|
|
773
779
|
[full_model_name(m), ws.master_key, " ".join(sorted(ws.ignored_fields))]
|
774
780
|
)
|
775
781
|
print(table(headers, rows, max_width=40))
|
782
|
+
|
783
|
+
def show_display_modes():
|
784
|
+
"""
|
785
|
+
Show the availble display modes per actor.
|
786
|
+
"""
|
787
|
+
dml = sorted(constants.DISPLAY_MODES - constants.BASIC_DISPLAY_MODES)
|
788
|
+
headers = ["actor"]
|
789
|
+
headers += dml
|
790
|
+
rows = []
|
791
|
+
for a in sorted(actors.actors_list, key=str):
|
792
|
+
if not a.is_abstract():
|
793
|
+
rows.append(
|
794
|
+
[str(a)] + [
|
795
|
+
("x" if dm in a.extra_display_modes else "")
|
796
|
+
for dm in dml]
|
797
|
+
)
|
798
|
+
print(table(headers, rows))
|
lino/core/__init__.py
CHANGED
lino/core/actions.py
CHANGED
@@ -33,7 +33,7 @@ from .utils import resolve_model
|
|
33
33
|
from .utils import navinfo
|
34
34
|
from .utils import Parametrizable
|
35
35
|
from .utils import traverse_ddh_fklist
|
36
|
-
from .
|
36
|
+
from .utils import InstanceAction
|
37
37
|
|
38
38
|
|
39
39
|
def discover_choosers():
|
@@ -85,7 +85,10 @@ def resolve_layout(cls, k, spec, layout_class, **options):
|
|
85
85
|
def install_layout(cls, k, layout_class, **options):
|
86
86
|
"""
|
87
87
|
- `cls` is the actor (a class object)
|
88
|
-
|
88
|
+
|
89
|
+
- `k` is one of 'grid_layout', 'detail_layout', 'insert_layout',
|
90
|
+
'params_layout', 'card_layout', 'list_layout'
|
91
|
+
|
89
92
|
- `layout_class`
|
90
93
|
|
91
94
|
"""
|
@@ -437,6 +440,8 @@ class Action(Parametrizable, Permittable):
|
|
437
440
|
On actions that opens_a_window this must be a unique one-letter
|
438
441
|
string expressing the window type.
|
439
442
|
|
443
|
+
See `constants.WINDOW_TYPES`.
|
444
|
+
|
440
445
|
Allowed values are:
|
441
446
|
|
442
447
|
- None : opens_a_window is False
|
@@ -486,6 +491,12 @@ class Action(Parametrizable, Permittable):
|
|
486
491
|
|
487
492
|
register_params(self)
|
488
493
|
|
494
|
+
if self.callable_from is not None:
|
495
|
+
for c in self.callable_from:
|
496
|
+
if not c in constants.WINDOW_TYPES:
|
497
|
+
raise Exception(f"Invalid window_type spec {c} in {self}")
|
498
|
+
|
499
|
+
|
489
500
|
def __get__(self, instance, owner):
|
490
501
|
"""
|
491
502
|
When a model has an action "foo", then getting an attribute
|
@@ -785,7 +796,7 @@ class ShowTable(TableAction):
|
|
785
796
|
use_param_panel = True
|
786
797
|
show_in_workflow = False
|
787
798
|
opens_a_window = True
|
788
|
-
window_type =
|
799
|
+
window_type = constants.WINDOW_TYPE_TABLE
|
789
800
|
action_name = "grid"
|
790
801
|
select_rows = False
|
791
802
|
callable_from = None
|
@@ -809,7 +820,7 @@ class ShowDetail(Action):
|
|
809
820
|
icon_name = "application_form"
|
810
821
|
ui5_icon_name = "sap-icon://detail-view"
|
811
822
|
opens_a_window = True
|
812
|
-
window_type =
|
823
|
+
window_type = constants.WINDOW_TYPE_DETAIL
|
813
824
|
show_in_workflow = False
|
814
825
|
save_action_name = "submit_detail"
|
815
826
|
callable_from = "t"
|
@@ -893,7 +904,7 @@ class ShowInsert(TableAction):
|
|
893
904
|
show_in_workflow = False
|
894
905
|
show_in_side_toolbar = True
|
895
906
|
opens_a_window = True
|
896
|
-
window_type =
|
907
|
+
window_type = constants.WINDOW_TYPE_INSERT
|
897
908
|
hide_navigator = True # 20210509
|
898
909
|
hide_top_toolbar = True # 20210509
|
899
910
|
sort_index = 10
|
@@ -1342,11 +1353,7 @@ class DeleteSelected(MultipleRowAction):
|
|
1342
1353
|
sort_index = 30
|
1343
1354
|
readonly = False
|
1344
1355
|
show_in_workflow = False
|
1345
|
-
# required_roles = set([SiteUser])
|
1346
|
-
# ~ callable_from = (ShowTable,ShowDetail)
|
1347
|
-
# ~ needs_selection = True
|
1348
1356
|
label = _("Delete")
|
1349
|
-
# ~ url_action_name = 'delete'
|
1350
1357
|
hotkey = keyboard.DELETE # (ctrl=True)
|
1351
1358
|
|
1352
1359
|
# ~ client_side = True
|
lino/core/actors.py
CHANGED
@@ -27,10 +27,10 @@ from lino.utils import MissingRow
|
|
27
27
|
from lino.core import fields
|
28
28
|
from lino.core import actions
|
29
29
|
from lino.core import layouts
|
30
|
-
from lino.core
|
30
|
+
from lino.core import constants
|
31
31
|
from lino.core.boundaction import BoundAction
|
32
32
|
from lino.core.exceptions import ChangedAPI
|
33
|
-
from lino.core.constants import _handle_attr_name
|
33
|
+
from lino.core.constants import _handle_attr_name
|
34
34
|
from lino.core.permissions import add_requirements, Permittable
|
35
35
|
from lino.core.utils import resolve_model
|
36
36
|
from lino.core.utils import error2str
|
@@ -162,22 +162,12 @@ class ActorMetaClass(type):
|
|
162
162
|
|
163
163
|
cls = super().__new__(meta, classname, bases, classDict)
|
164
164
|
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
#
|
171
|
-
"""
|
172
|
-
On 20110822 I thought "A Table always gets the app_label of its model,
|
173
|
-
you cannot set this yourself in a subclass
|
174
|
-
because otherwise it gets complex when inheriting reports from other
|
175
|
-
app_labels."
|
176
|
-
On 20110912 I cancelled change 20110822 because PersonsByOffer
|
177
|
-
should clearly get app_label 'jobs' and not 'contacts'.
|
178
|
-
|
179
|
-
"""
|
180
|
-
|
165
|
+
# On 20110822 I thought "A Table always gets the app_label of its model,
|
166
|
+
# you cannot set this yourself in a subclass
|
167
|
+
# because otherwise it gets complex when inheriting reports from other
|
168
|
+
# app_labels."
|
169
|
+
# On 20110912 I cancelled change 20110822 because PersonsByOffer
|
170
|
+
# should clearly get app_label 'jobs' and not 'contacts'.
|
181
171
|
if classDict.get("app_label", None) is None:
|
182
172
|
# Figure out the app_label by looking one level up.
|
183
173
|
# For 'django.contrib.sites.models', this would be 'sites'.
|
@@ -291,7 +281,17 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
291
281
|
# """
|
292
282
|
|
293
283
|
only_fields = None
|
294
|
-
|
284
|
+
|
285
|
+
default_display_modes = None
|
286
|
+
|
287
|
+
# extra_display_modes = set()
|
288
|
+
# extra_display_modes = {constants.DISPLAY_MODE_SUMMARY}
|
289
|
+
extra_display_modes = {constants.DISPLAY_MODE_HTML}
|
290
|
+
"""
|
291
|
+
A set of additional display modes to make available when rendering this table.
|
292
|
+
|
293
|
+
See :ref:`dg.dd.table.extra_display_modes`.
|
294
|
+
"""
|
295
295
|
|
296
296
|
app_label = None
|
297
297
|
"""
|
@@ -428,6 +428,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
428
428
|
default_action = None
|
429
429
|
actor_id = None
|
430
430
|
|
431
|
+
grid_layout = None
|
431
432
|
detail_layout = None
|
432
433
|
insert_layout = None
|
433
434
|
card_layout = None
|
@@ -730,8 +731,12 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
730
731
|
|
731
732
|
if hasattr(cls, "required"):
|
732
733
|
raise ChangedAPI(
|
733
|
-
"{
|
734
|
+
f"{cls} must convert `required` to `required_roles`"
|
734
735
|
)
|
736
|
+
if hasattr(cls, "display_mode"):
|
737
|
+
# cls.default_display_modes = {k:v for k, v in cls.display_mode}
|
738
|
+
# logger.info(f"{cls} uses deprecated `display_mode`, please convert to `default_display_modes`.")
|
739
|
+
raise ChangedAPI(f"{cls} must convert `display_mode` to `default_display_modes`")
|
735
740
|
|
736
741
|
master = getattr(cls, "master", None)
|
737
742
|
if isinstance(master, str):
|
@@ -760,6 +765,45 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
760
765
|
cls.virtual_fields["detail_link"] = de
|
761
766
|
# cls.add_virtual_field('detail_link', de)
|
762
767
|
|
768
|
+
if cls.abstract:
|
769
|
+
return
|
770
|
+
|
771
|
+
edm = set() # extra display modes to add automatically
|
772
|
+
if cls.default_display_modes is not None:
|
773
|
+
for v in cls.default_display_modes.values():
|
774
|
+
if v not in constants.DISPLAY_MODES:
|
775
|
+
raise Exception(f"Invalid display mode {v} in {cls}")
|
776
|
+
if v not in constants.BASIC_DISPLAY_MODES:
|
777
|
+
# be sure to have our copy the extra_display_modes set
|
778
|
+
# if str(cls) == "comments.Comments":
|
779
|
+
# print(f"20240929 extra_display_modes is {cls.extra_display_modes}, we add {v}")
|
780
|
+
# cls.extra_display_modes = cls.extra_display_modes | {v}
|
781
|
+
edm.add(v)
|
782
|
+
|
783
|
+
if cls.card_layout is not None:
|
784
|
+
edm.add(constants.DISPLAY_MODE_CARDS)
|
785
|
+
if 'row_as_paragraph' in cls.__dict__:
|
786
|
+
edm.add(constants.DISPLAY_MODE_LIST)
|
787
|
+
# if 'row_as_page' in cls.__dict__:
|
788
|
+
# edm.add(constants.DISPLAY_MODE_STORY)
|
789
|
+
if model is not None:
|
790
|
+
if model.extra_display_modes is not None:
|
791
|
+
for v in model.extra_display_modes:
|
792
|
+
if v not in constants.DISPLAY_MODES:
|
793
|
+
raise Exception(f"Invalid display mode {v} in {model}.extra_display_modes")
|
794
|
+
edm |= model.extra_display_modes
|
795
|
+
if 'as_paragraph' in model.__dict__:
|
796
|
+
edm.add(constants.DISPLAY_MODE_LIST)
|
797
|
+
if 'as_page' in model.__dict__:
|
798
|
+
edm.add(constants.DISPLAY_MODE_STORY)
|
799
|
+
# no need to automatically add summary because it's in default_display_modes of every table
|
800
|
+
# if 'as_summary_item' in model.__dict__:
|
801
|
+
# edm.add(constants.DISPLAY_MODE_SUMMARY)
|
802
|
+
if len(edm) > 0:
|
803
|
+
# if str(cls) == "comments.Comments":
|
804
|
+
# print(f"20240929 {cls} extra_display_modes add {edm}")
|
805
|
+
cls.extra_display_modes = cls.extra_display_modes | edm
|
806
|
+
|
763
807
|
@classmethod
|
764
808
|
def init_layouts(cls):
|
765
809
|
# 20200430 this was previously part of class_init, but is now called in
|
@@ -1238,7 +1282,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1238
1282
|
yield t
|
1239
1283
|
for k in self.simple_parameters:
|
1240
1284
|
v = getattr(ar.param_values, k)
|
1241
|
-
if v and v != CHOICES_BLANK_FILTER_VALUE:
|
1285
|
+
if v and v != constants.CHOICES_BLANK_FILTER_VALUE:
|
1242
1286
|
if v is True:
|
1243
1287
|
# For BooleanField no need to add "True" in the title
|
1244
1288
|
yield str(self.parameters[k].verbose_name)
|
@@ -1605,10 +1649,10 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1605
1649
|
return wl.get_layout_handle()
|
1606
1650
|
|
1607
1651
|
@classmethod
|
1608
|
-
def
|
1652
|
+
def get_grid_layout(cls, *args):
|
1609
1653
|
assert cls.default_action is not None
|
1610
1654
|
ah = cls.get_handle()
|
1611
|
-
return ah.
|
1655
|
+
return ah.get_grid_layout()
|
1612
1656
|
|
1613
1657
|
@classmethod
|
1614
1658
|
def get_detail_elems(cls):
|
@@ -1739,6 +1783,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1739
1783
|
Return an action request on this actor.
|
1740
1784
|
"""
|
1741
1785
|
kw.update(actor=self)
|
1786
|
+
from lino.core.requests import ActionRequest
|
1742
1787
|
return ActionRequest(*args, **kw)
|
1743
1788
|
|
1744
1789
|
@classmethod
|
@@ -1788,11 +1833,16 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1788
1833
|
# welfare/docs/specs/weleup/weleup1r.rst
|
1789
1834
|
# kwargs.update(request=ar.request)
|
1790
1835
|
kwargs.update(parent=ar)
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1836
|
+
kwargs.update(renderer=settings.SITE.kernel.default_renderer)
|
1837
|
+
try:
|
1838
|
+
ar = cls.request(master_instance=master, **kwargs)
|
1839
|
+
el = ar.table2xhtml()
|
1840
|
+
toolbar = ar.plain_toolbar_buttons()
|
1841
|
+
except Exception as e:
|
1842
|
+
msg = f"20241004 Error in {repr(ar)}: {e}"
|
1843
|
+
raise Exception(msg) from e
|
1844
|
+
logger.warning(msg)
|
1845
|
+
return msg
|
1796
1846
|
if len(toolbar):
|
1797
1847
|
el = E.div(el, E.p(*toolbar))
|
1798
1848
|
return el
|
@@ -1831,6 +1881,25 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1831
1881
|
# assert_safe(html_text) # temporary 20240506
|
1832
1882
|
return format_html(DIVTPL, html_text)
|
1833
1883
|
|
1884
|
+
@classmethod
|
1885
|
+
def get_table_story(cls, obj, ar):
|
1886
|
+
sar = cls.request(parent=ar, master_instance=obj, is_on_main_actor=False)
|
1887
|
+
html = mark_safe("")
|
1888
|
+
for i, obj in enumerate(sar.data_iterator):
|
1889
|
+
if i == cls.preview_limit:
|
1890
|
+
break
|
1891
|
+
s = obj.as_story_item(sar)
|
1892
|
+
# assert_safe(s) # temporary 20240506
|
1893
|
+
html += s
|
1894
|
+
if cls.insert_action is not None:
|
1895
|
+
if not cls.editable:
|
1896
|
+
return html
|
1897
|
+
ir = cls.insert_action.request_from(sar)
|
1898
|
+
if ir.get_permission():
|
1899
|
+
html = tostring(ir.ar2button()) + html
|
1900
|
+
# assert_safe(html) # temporary 20240506
|
1901
|
+
return html
|
1902
|
+
|
1834
1903
|
@classmethod
|
1835
1904
|
def get_table_summary(cls, obj, ar):
|
1836
1905
|
"""
|
@@ -1892,7 +1961,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1892
1961
|
if ar is None:
|
1893
1962
|
return str(self)
|
1894
1963
|
# cols = ar.actor.get_detail_layout().main
|
1895
|
-
cols = cls.
|
1964
|
+
cols = cls.get_grid_layout().main.columns
|
1896
1965
|
cols = [c for c in cols if not c.value.get("hidden")]
|
1897
1966
|
if fmt is None:
|
1898
1967
|
|
@@ -1914,7 +1983,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1914
1983
|
values = [v for v in values if v is not None]
|
1915
1984
|
s = ", ".join(values)
|
1916
1985
|
# s = str(ar.actor)
|
1917
|
-
# print("20231218", s) # self, ar.actor.
|
1986
|
+
# print("20231218", s) # self, ar.actor.get_grid_layout().main.columns)
|
1918
1987
|
return s
|
1919
1988
|
|
1920
1989
|
@classmethod
|
lino/core/choicelists.py
CHANGED
@@ -368,28 +368,43 @@ class ChoiceList(with_metaclass(ChoiceListMeta, tables.AbstractTable)):
|
|
368
368
|
"""A string with the name of a choice to be used as default value for
|
369
369
|
fields using this list.
|
370
370
|
|
371
|
+
Usage example in :mod:`lino_xl.lib.clients.models`::
|
372
|
+
|
373
|
+
class ClientStates(dd.Workflow):
|
374
|
+
required_roles = dd.login_required(ContactsStaff)
|
375
|
+
verbose_name_plural = _("Client states")
|
376
|
+
default_value = 'newcomer'
|
377
|
+
|
378
|
+
add = ClientStates.add_item
|
379
|
+
add('10', _("Newcomer"), 'newcomer')
|
380
|
+
add('20', _("Refused"), 'refused')
|
381
|
+
add('30', _("Coached"), 'coached')
|
382
|
+
add('50', _("Former"), 'former')
|
383
|
+
|
384
|
+
And :mod:`lino_avant.lib.avanti.models` overrides it::
|
385
|
+
|
386
|
+
from lino_xl.lib.clients.choicelists import ClientStates
|
387
|
+
ClientStates.default_value = 'coached'
|
388
|
+
|
371
389
|
Note that this specifies the *default* default value for *all*
|
372
390
|
:class:`ChoiceListField <lino.core.choicelists.ChoiceListField>`
|
373
391
|
of this choicelist, including parameter fields.
|
374
392
|
|
393
|
+
The disadvantage is that when somebody *does not* want your default value,
|
394
|
+
then they must explicitly specify `default=''` when defining a field on your
|
395
|
+
choicelist.
|
396
|
+
|
375
397
|
You can remove that "default default value" for all tables by
|
376
398
|
specifying `default=''`. There are two places where you can
|
377
399
|
specify this: (a) on the parameter field itself (which then
|
378
400
|
applies to all subtables) or (b) just on one table. For example
|
379
401
|
(excerpt from :mod:`lino_avanti.lib.avanti`)::
|
380
402
|
|
381
|
-
from lino_xl.lib.clients.choicelists import ClientStates
|
382
|
-
ClientStates.default_value = 'coached'
|
383
|
-
|
384
403
|
parameters = ObservedDateRange(
|
385
404
|
...
|
386
405
|
client_state=ClientStates.field(blank=True, default=''))
|
387
406
|
|
388
|
-
|
389
|
-
is used as the *models default table* will apply for the choices
|
390
|
-
of pointers to that model. Concrete use case is the choicelist of
|
391
|
-
`cal.Guest.partner` in :ref:`avanti`, which should show only
|
392
|
-
coached clients. So instead of above code we actually now do::
|
407
|
+
Example for (b)::
|
393
408
|
|
394
409
|
class MyClients(My, Clients):
|
395
410
|
@classmethod
|
@@ -398,9 +413,11 @@ class ChoiceList(with_metaclass(ChoiceListMeta, tables.AbstractTable)):
|
|
398
413
|
kw.update(client_state='')
|
399
414
|
return kw
|
400
415
|
|
401
|
-
|
402
|
-
|
403
|
-
choicelist
|
416
|
+
Note that the default values of parameter fields of a table that
|
417
|
+
is used as the *model's default table* will apply for the choices
|
418
|
+
of pointers to that model. Concrete use case is the choicelist of
|
419
|
+
`cal.Guest.partner` in :ref:`avanti`, which we want to show only
|
420
|
+
coached clients.
|
404
421
|
|
405
422
|
"""
|
406
423
|
|
lino/core/constants.py
CHANGED
@@ -47,22 +47,38 @@ URL_PARAM_WINDOW_TYPE = "wt"
|
|
47
47
|
|
48
48
|
WINDOW_TYPE_TABLE = "t"
|
49
49
|
WINDOW_TYPE_DETAIL = "d"
|
50
|
-
WINDOW_TYPE_CARDS = "c"
|
51
|
-
WINDOW_TYPE_GALLERIA = "g"
|
52
50
|
WINDOW_TYPE_INSERT = "i"
|
53
51
|
WINDOW_TYPE_PARAMS = "p"
|
54
52
|
|
53
|
+
WINDOW_TYPES = {
|
54
|
+
WINDOW_TYPE_TABLE, WINDOW_TYPE_DETAIL, WINDOW_TYPE_INSERT,
|
55
|
+
WINDOW_TYPE_PARAMS
|
56
|
+
}
|
57
|
+
|
55
58
|
URL_PARAM_DISPLAY_MODE = "dm"
|
56
59
|
|
57
|
-
DISPLAY_MODE_TABLE = "grid" # deprecated
|
58
60
|
DISPLAY_MODE_GRID = "grid"
|
59
61
|
DISPLAY_MODE_DETAIL = "detail"
|
62
|
+
DISPLAY_MODE_HTML = "html"
|
60
63
|
DISPLAY_MODE_SUMMARY = "summary"
|
61
64
|
DISPLAY_MODE_LIST = "list"
|
62
65
|
DISPLAY_MODE_CARDS = "cards"
|
63
66
|
DISPLAY_MODE_GALLERY = "gallery"
|
64
67
|
DISPLAY_MODE_STORY = "story"
|
65
|
-
|
68
|
+
|
69
|
+
DISPLAY_MODES = {
|
70
|
+
DISPLAY_MODE_GRID,
|
71
|
+
DISPLAY_MODE_DETAIL,
|
72
|
+
DISPLAY_MODE_HTML,
|
73
|
+
DISPLAY_MODE_SUMMARY,
|
74
|
+
DISPLAY_MODE_LIST,
|
75
|
+
DISPLAY_MODE_CARDS,
|
76
|
+
DISPLAY_MODE_GALLERY,
|
77
|
+
DISPLAY_MODE_STORY}
|
78
|
+
|
79
|
+
BASIC_DISPLAY_MODES = {
|
80
|
+
DISPLAY_MODE_GRID,
|
81
|
+
DISPLAY_MODE_DETAIL}
|
66
82
|
|
67
83
|
# ~ URL_PARAM_EUSER = 'euser'
|
68
84
|
# ~ URL_PARAM_EUSER = 'su'
|
lino/core/dashboard.py
CHANGED
@@ -7,9 +7,13 @@
|
|
7
7
|
|
8
8
|
from lino.api import _
|
9
9
|
from lino.core.permissions import Permittable
|
10
|
+
from lino.core.requests import ActionRequest
|
11
|
+
from lino.core.tables import AbstractTable
|
12
|
+
# from lino.core.actions import ShowTable
|
10
13
|
from lino.utils.html import E, tostring, assert_safe
|
11
14
|
from django.utils.html import mark_safe
|
12
15
|
|
16
|
+
|
13
17
|
class DashboardItem(Permittable):
|
14
18
|
"""Base class for all dashboard items.
|
15
19
|
|
@@ -51,9 +55,6 @@ class DashboardItem(Permittable):
|
|
51
55
|
This is a helper function for shared use by :class:`ActorItem`
|
52
56
|
and :class:`RequestItem`.
|
53
57
|
"""
|
54
|
-
from lino.core.tables import TableRequest
|
55
|
-
from lino.core.requests import ActionRequest
|
56
|
-
|
57
58
|
assert ar.user is sar.user
|
58
59
|
# T = sar.actor
|
59
60
|
# print("20210112 render_request()", sar.actor, sar)
|
@@ -72,22 +73,22 @@ class DashboardItem(Permittable):
|
|
72
73
|
yield tostring(E.h2(str(sar.actor.get_title_base(sar)), " ", *elems))
|
73
74
|
|
74
75
|
assert sar.renderer is not None
|
75
|
-
if isinstance(sar,
|
76
|
+
if isinstance(sar, ActionRequest):
|
76
77
|
# TODO 20220930 until now, dashboard was always acting as if
|
77
|
-
# display_mode was
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
78
|
+
# display_mode was DISPLAY_MODE_GRID
|
79
|
+
if issubclass(sar.actor, AbstractTable):
|
80
|
+
# if isinstance(sar.bound_action.action, ShowTable):
|
81
|
+
for e in sar.renderer.table2story(sar, **kwargs):
|
82
|
+
# assert_safe(tostring(e))
|
83
|
+
yield tostring(e)
|
84
|
+
else:
|
85
|
+
# example : courses.StatusReport in dashboard
|
86
|
+
yield sar.renderer.show_story(
|
87
|
+
ar, sar.actor.get_story(None, ar), **kwargs)
|
88
|
+
# for e in sar.renderer.show_story(
|
89
|
+
# ar, sar.actor.get_story(None, ar), **kwargs):
|
90
|
+
# # assert_safe(tostring(e))
|
91
|
+
# yield tostring(e)
|
91
92
|
else:
|
92
93
|
raise Exception("20240908 Cannot render {}".format(sar))
|
93
94
|
yield "Cannot render {}".format(sar)
|