lino 25.8.3__py3-none-any.whl → 25.9.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/dd.py +0 -1
- lino/core/__init__.py +0 -1
- lino/core/actions.py +1 -1
- lino/core/actors.py +8 -0
- lino/core/elems.py +1 -1
- lino/core/fields.py +4 -1
- lino/core/model.py +2 -11
- lino/core/requests.py +8 -7
- lino/core/site.py +0 -79
- lino/core/user_types.py +1 -10
- lino/help_texts.py +1 -5
- lino/management/commands/dump2py.py +4 -3
- lino/management/commands/initdb.py +0 -3
- lino/modlib/__init__.py +0 -1
- lino/modlib/bootstrap5/README.txt +1 -1
- lino/modlib/bootstrap5/__init__.py +34 -38
- lino/modlib/bootstrap5/config/bootstrap5/base.html +4 -0
- lino/modlib/bootstrap5/models.py +23 -23
- lino/modlib/bootstrap5/views.py +2 -107
- lino/modlib/checkdata/choicelists.py +1 -1
- lino/modlib/comments/fixtures/demo2.py +1 -0
- lino/modlib/comments/ui.py +7 -7
- lino/modlib/extjs/__init__.py +2 -4
- lino/modlib/extjs/config/extjs/index.html +1 -1
- lino/modlib/extjs/ext_renderer.py +1 -7
- lino/modlib/extjs/views.py +2 -0
- lino/modlib/help/models.py +1 -12
- lino/modlib/linod/__init__.py +2 -2
- lino/modlib/linod/mixins.py +3 -2
- lino/modlib/memo/__init__.py +10 -9
- lino/modlib/memo/mixins.py +38 -21
- lino/modlib/memo/models.py +10 -7
- lino/modlib/memo/parser.py +3 -1
- lino/modlib/notify/models.py +6 -9
- lino/modlib/publisher/__init__.py +12 -7
- lino/modlib/publisher/choicelists.py +9 -64
- lino/modlib/publisher/config/publisher/page.pub.html +73 -7
- lino/modlib/publisher/fixtures/std.py +14 -1
- lino/modlib/publisher/mixins.py +41 -12
- lino/modlib/publisher/models.py +74 -75
- lino/modlib/publisher/renderer.py +28 -12
- lino/modlib/publisher/ui.py +35 -35
- lino/modlib/publisher/views.py +59 -24
- lino/modlib/system/models.py +3 -2
- lino/modlib/uploads/__init__.py +1 -0
- lino/modlib/uploads/mixins.py +2 -2
- lino/modlib/uploads/models.py +55 -21
- lino/modlib/uploads/ui.py +1 -0
- lino/modlib/uploads/utils.py +2 -2
- lino/modlib/users/__init__.py +2 -3
- lino/modlib/users/actions.py +12 -17
- lino/modlib/users/models.py +37 -36
- lino/modlib/weasyprint/choicelists.py +6 -0
- lino/utils/diag.py +5 -3
- lino/utils/html.py +103 -0
- lino/utils/mldbc/mixins.py +2 -2
- lino/utils/soup.py +16 -8
- {lino-25.8.3.dist-info → lino-25.9.1.dist-info}/METADATA +1 -2
- {lino-25.8.3.dist-info → lino-25.9.1.dist-info}/RECORD +63 -63
- {lino-25.8.3.dist-info → lino-25.9.1.dist-info}/WHEEL +0 -0
- {lino-25.8.3.dist-info → lino-25.9.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.8.3.dist-info → lino-25.9.1.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
@@ -31,7 +31,7 @@ from django import VERSION
|
|
31
31
|
from django.apps import AppConfig
|
32
32
|
from django.conf import settings
|
33
33
|
import warnings
|
34
|
-
__version__ = '25.
|
34
|
+
__version__ = '25.9.1'
|
35
35
|
|
36
36
|
# import setuptools # avoid UserWarning "Distutils was imported before Setuptools"?
|
37
37
|
|
lino/api/dd.py
CHANGED
@@ -189,7 +189,6 @@ resolve_plugin = settings.SITE.resolve_plugin
|
|
189
189
|
get_plugin_setting = settings.SITE.get_plugin_setting
|
190
190
|
add_welcome_handler = settings.SITE.add_welcome_handler
|
191
191
|
build_media_url = settings.SITE.build_media_url
|
192
|
-
build_site_cache_url = settings.SITE.build_site_cache_url
|
193
192
|
build_static_url = settings.SITE.build_static_url
|
194
193
|
get_default_language = settings.SITE.get_default_language
|
195
194
|
get_language_info = settings.SITE.get_language_info
|
lino/core/__init__.py
CHANGED
lino/core/actions.py
CHANGED
@@ -595,7 +595,7 @@ class SubmitDetail(SaveGridCell):
|
|
595
595
|
ar.goto_instance(elem)
|
596
596
|
else:
|
597
597
|
if len(ar.selected_rows) == 1:
|
598
|
-
ar.
|
598
|
+
ar.success(data_record=ar.elem2rec_detailed(elem))
|
599
599
|
|
600
600
|
|
601
601
|
class CreateRow(Action):
|
lino/core/actors.py
CHANGED
@@ -1715,6 +1715,14 @@ class Actor(Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1715
1715
|
kw = self.model.param_defaults(ar, **kw)
|
1716
1716
|
return kw
|
1717
1717
|
|
1718
|
+
# @classmethod
|
1719
|
+
# def get_parent_links(cls, ar):
|
1720
|
+
# if cls.model is not None:
|
1721
|
+
# for pl in cls.model.get_parent_links(ar):
|
1722
|
+
# yield pl
|
1723
|
+
# # if (mi := ar.master_instance) is not None:
|
1724
|
+
# # yield ar.obj2htmls(mi, str(mi))
|
1725
|
+
|
1718
1726
|
@classmethod
|
1719
1727
|
def request(cls, *args, **kwargs):
|
1720
1728
|
"""
|
lino/core/elems.py
CHANGED
@@ -37,7 +37,7 @@ from lino.core import actions
|
|
37
37
|
from lino.core.utils import resolve_model
|
38
38
|
from lino.core.gfks import GenericRelation, GenericRel
|
39
39
|
from lino.core.permissions import Permittable
|
40
|
-
from lino.
|
40
|
+
from lino.utils.html import table2html
|
41
41
|
|
42
42
|
from lino.utils.jsgen import VisibleComponent
|
43
43
|
from lino.utils.html import E, tostring, forcetext, html2text
|
lino/core/fields.py
CHANGED
@@ -1265,7 +1265,7 @@ class ImportedFields(object):
|
|
1265
1265
|
# ~ cls,cls._imported_fields))
|
1266
1266
|
|
1267
1267
|
|
1268
|
-
class TableRow
|
1268
|
+
class TableRow:
|
1269
1269
|
"""Base class for everything that can be used as a table row."""
|
1270
1270
|
|
1271
1271
|
_lino_default_table = None
|
@@ -1420,6 +1420,9 @@ class TableRow(object):
|
|
1420
1420
|
# raise Exception("20230425 {}".format(ar.actor))
|
1421
1421
|
return a
|
1422
1422
|
|
1423
|
+
def get_parent_links(self, ar):
|
1424
|
+
return []
|
1425
|
+
|
1423
1426
|
def get_choices_text(self, ar, actor, field):
|
1424
1427
|
return self.as_str(ar)
|
1425
1428
|
# return str(self)
|
lino/core/model.py
CHANGED
@@ -44,7 +44,7 @@ from .tables import AbstractTable
|
|
44
44
|
|
45
45
|
class Model(models.Model, fields.TableRow):
|
46
46
|
|
47
|
-
class Meta
|
47
|
+
class Meta:
|
48
48
|
abstract = True
|
49
49
|
|
50
50
|
allow_cascaded_delete = frozenset()
|
@@ -436,16 +436,6 @@ class Model(models.Model, fields.TableRow):
|
|
436
436
|
new = old
|
437
437
|
else:
|
438
438
|
new = sanitize(old, **kwargs)
|
439
|
-
# try:
|
440
|
-
# new = bleach.clean(
|
441
|
-
# new,
|
442
|
-
# tags=settings.SITE.bleach_allowed_tags,
|
443
|
-
# attributes=settings.SITE.bleach_allowed_attributes,
|
444
|
-
# strip=True,
|
445
|
-
# )
|
446
|
-
# except TypeError as e:
|
447
|
-
# logger.warning("Could not bleach %r : %s (%s)", old, e, self)
|
448
|
-
# continue
|
449
439
|
if old != new:
|
450
440
|
logger.debug("Bleaching %s from %r to %r", f.name, old, new)
|
451
441
|
yield f, old, new
|
@@ -1003,6 +993,7 @@ LINO_MODEL_ATTRIBS = (
|
|
1003
993
|
"show_in_site_search",
|
1004
994
|
"allow_merge_action",
|
1005
995
|
"get_overview_elems",
|
996
|
+
"get_parent_links",
|
1006
997
|
)
|
1007
998
|
|
1008
999
|
|
lino/core/requests.py
CHANGED
@@ -1676,17 +1676,18 @@ class BaseRequest:
|
|
1676
1676
|
return rec
|
1677
1677
|
|
1678
1678
|
def get_breadcrumbs(self, elem=None):
|
1679
|
+
# print("20250910 get_breadcrumbs", self)
|
1679
1680
|
list_title = self.get_title()
|
1680
|
-
|
1681
|
-
if elem is None or self.actor.default_record_id is not None:
|
1682
|
-
return list_title
|
1683
|
-
else:
|
1684
|
-
# print("20190703", self.actor, self.actor.default_action)
|
1681
|
+
if self.actor.default_record_id is None:
|
1685
1682
|
sar = self.spawn_request(actor=self.actor)
|
1686
1683
|
list_title = tostring(sar.href_to_request(
|
1687
1684
|
sar, list_title, icon_name=None))
|
1688
|
-
|
1689
|
-
|
1685
|
+
if elem is not None:
|
1686
|
+
list_title = format_html(
|
1687
|
+
"{} » {}", list_title, self.get_detail_title(elem))
|
1688
|
+
for pl in elem.get_parent_links(self):
|
1689
|
+
list_title = format_html("{} » {}", pl, list_title)
|
1690
|
+
return list_title
|
1690
1691
|
|
1691
1692
|
def form2obj_and_save(ar, data, elem, is_new):
|
1692
1693
|
"""
|
lino/core/site.py
CHANGED
@@ -262,7 +262,6 @@ class Site(object):
|
|
262
262
|
use_elasticsearch = False
|
263
263
|
use_solr = False
|
264
264
|
developer_site_cache = None
|
265
|
-
never_build_site_cache = False
|
266
265
|
keep_erroneous_cache_files = False
|
267
266
|
use_java = True
|
268
267
|
use_systemd = False
|
@@ -1131,48 +1130,8 @@ class Site(object):
|
|
1131
1130
|
# sfd = tuple([x for x in sfd if x != root])
|
1132
1131
|
# self.update_settings(STATICFILES_DIRS=sfd)
|
1133
1132
|
|
1134
|
-
# if self.build_js_cache_on_startup or self.never_build_site_cache:
|
1135
|
-
# sfd = list(self.django_settings.get('STATICFILES_DIRS', []))
|
1136
|
-
# sfd.append(self.media_root)
|
1137
|
-
# self.update_settings(STATICFILES_DIRS=sfd)
|
1138
|
-
|
1139
1133
|
# print(20150331, self.django_settings['FIXTURE_DIRS'])
|
1140
1134
|
|
1141
|
-
# def setup_cache_directory(self):
|
1142
|
-
# stamp = self.site_dir / "lino_cache.txt"
|
1143
|
-
# this = class2str(self.__class__)
|
1144
|
-
# if stamp.exists():
|
1145
|
-
# other = stamp.read_file()
|
1146
|
-
# if other == this:
|
1147
|
-
# ok = True
|
1148
|
-
# else:
|
1149
|
-
# ok = False
|
1150
|
-
# for parent in self.__class__.__mro__:
|
1151
|
-
# if other == class2str(parent):
|
1152
|
-
# ok = True
|
1153
|
-
# break
|
1154
|
-
# if not ok:
|
1155
|
-
# # Can happen e.g. when `python -m lino.hello` is
|
1156
|
-
# # called. in certain conditions.
|
1157
|
-
# msg = (
|
1158
|
-
# "Cannot use {site_dir} for {this} "
|
1159
|
-
# "because it is used for {other}. (Settings {settings})"
|
1160
|
-
# )
|
1161
|
-
# msg = msg.format(
|
1162
|
-
# site_dir=self.site_dir,
|
1163
|
-
# this=this,
|
1164
|
-
# settings=self.django_settings.get("SETTINGS_MODULE"),
|
1165
|
-
# other=other,
|
1166
|
-
# )
|
1167
|
-
# if True:
|
1168
|
-
# raise Exception(msg)
|
1169
|
-
# else:
|
1170
|
-
# # print(msg)
|
1171
|
-
# self.site_dir = None
|
1172
|
-
# else:
|
1173
|
-
# self.makedirs_if_missing(self.site_dir)
|
1174
|
-
# stamp.write_file(this)
|
1175
|
-
|
1176
1135
|
def set_user_model(self, spec):
|
1177
1136
|
# if self.user_model is not None:
|
1178
1137
|
# msg = "Site.user_model was already set!"
|
@@ -2022,44 +1981,12 @@ class Site(object):
|
|
2022
1981
|
def build_site_cache(self, force=False, later=False, verbosity=1):
|
2023
1982
|
from lino.modlib.users.utils import with_user_profile
|
2024
1983
|
from lino.modlib.users.choicelists import UserTypes
|
2025
|
-
# from django.utils import translation
|
2026
|
-
# if not self.is_prepared:
|
2027
|
-
# self.prepare_layouts()
|
2028
|
-
# self.is_prepared = True
|
2029
|
-
# settings_file = self.django_settings.get("__file__")
|
2030
|
-
# Path(settings_file).touch()
|
2031
|
-
# p = self.site_dir / "lino_version.txt"
|
2032
|
-
# p.touch()
|
2033
1984
|
self.kernel.touch_lino_version()
|
2034
1985
|
|
2035
1986
|
if later:
|
2036
1987
|
# print("20230823 later")
|
2037
1988
|
return
|
2038
1989
|
|
2039
|
-
if self.never_build_site_cache:
|
2040
|
-
self.logger.debug(
|
2041
|
-
"Not building site cache because `settings.SITE.never_build_site_cache` is True"
|
2042
|
-
)
|
2043
|
-
# print("20230823 never")
|
2044
|
-
return
|
2045
|
-
|
2046
|
-
# logger.info("20140401 build_site_cache started")
|
2047
|
-
if False:
|
2048
|
-
# 20240907 until now the Site class creates the media directory if
|
2049
|
-
# it doesn't exist, but the initdb command removes it again. So the
|
2050
|
-
# following code seems really useless:
|
2051
|
-
if not self.media_root.is_dir():
|
2052
|
-
self.media_root.mkdir()
|
2053
|
-
# try:
|
2054
|
-
# settings.SITE.media_root.mkdir()
|
2055
|
-
# except Exception as e:
|
2056
|
-
# logger.debug(
|
2057
|
-
# "Not building site cache because 'mkdir %s' says %s.",
|
2058
|
-
# settings.SITE.media_root, e)
|
2059
|
-
# return
|
2060
|
-
|
2061
|
-
self.makedirs_if_missing(self.media_root / "webdav")
|
2062
|
-
|
2063
1990
|
if verbosity > 0:
|
2064
1991
|
self.logger.info("Build site cache in %s.", self.media_root)
|
2065
1992
|
|
@@ -2220,12 +2147,6 @@ class Site(object):
|
|
2220
2147
|
def build_static_url(self, *args, **kw):
|
2221
2148
|
return buildurl(settings.STATIC_URL, *args, **kw)
|
2222
2149
|
|
2223
|
-
def build_site_cache_url(self, *args, **kw):
|
2224
|
-
assert str(self.media_root) == str(settings.MEDIA_ROOT)
|
2225
|
-
# if str(self.media_root) != str(settings.MEDIA_ROOT):
|
2226
|
-
# return self.build_static_url(*args, **kw)
|
2227
|
-
return self.build_media_url(*args, **kw)
|
2228
|
-
|
2229
2150
|
def welcome_html(self, ui=None):
|
2230
2151
|
from django.utils.translation import gettext as _
|
2231
2152
|
|
lino/core/user_types.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2015-
|
1
|
+
# Copyright 2015-2025 Rumma & Ko Ltd
|
2
2
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
3
3
|
"""
|
4
4
|
Defines a set of user types "Anonymous", "User" and
|
@@ -10,17 +10,8 @@ This can be used directly as :attr:`user_types_module
|
|
10
10
|
|
11
11
|
from django.utils.translation import gettext_lazy as _
|
12
12
|
from lino.core.roles import UserRole, SiteAdmin, SiteUser
|
13
|
-
|
14
|
-
# from lino.modlib.office.roles import OfficeUser, OfficeStaff
|
15
13
|
from lino.modlib.users.choicelists import UserTypes
|
16
14
|
|
17
|
-
# class SiteAdmin(SiteAdmin, OfficeStaff):
|
18
|
-
# pass
|
19
|
-
#
|
20
|
-
# class SiteUser(SiteUser, OfficeUser):
|
21
|
-
# pass
|
22
|
-
|
23
|
-
UserTypes.clear()
|
24
15
|
add = UserTypes.add_item
|
25
16
|
add("000", _("Anonymous"), UserRole, name="anonymous", readonly=True)
|
26
17
|
add("100", _("User"), SiteUser, name="user")
|
lino/help_texts.py
CHANGED
@@ -103,10 +103,6 @@ help_texts = {
|
|
103
103
|
'lino.mixins.sequenced.Hierarchical.whole_clan' : _("""Return a set of this instance and all children and grandchildren."""),
|
104
104
|
'lino.mixins.sequenced.Hierarchical.whole_tree' : _("""Returns a tuple with two items (obj, children) representing the whole tree."""),
|
105
105
|
'lino.modlib.about.Plugin' : _("""See /dev/plugins."""),
|
106
|
-
'lino.modlib.bootstrap5.renderer.Renderer' : _("""A HTML render that uses Bootstrap3."""),
|
107
|
-
'lino.modlib.bootstrap5.views.List' : _("""Render a list of records."""),
|
108
|
-
'lino.modlib.bootstrap5.views.Element' : _("""Render a single record."""),
|
109
|
-
'lino.modlib.bootstrap5.views.Index' : _("""Render the main page."""),
|
110
106
|
'lino.modlib.checkdata.Plugin' : _("""The config descriptor for this plugin."""),
|
111
107
|
'lino.modlib.checkdata.Plugin.on_plugins_loaded' : _("""Set responsible_user to "'robin' if this is a demo site (is_demo_site)."""),
|
112
108
|
'lino.modlib.checkdata.roles.CheckdataUser' : _("""Can see checkdata messages."""),
|
@@ -216,6 +212,7 @@ help_texts = {
|
|
216
212
|
'lino.utils.diag.Analyzer.show_window_fields' : _("""List all window actions and the form fields they contain."""),
|
217
213
|
'lino.utils.diag.Analyzer.show_window_permissions' : _("""List all window actions and the user types that can see them."""),
|
218
214
|
'lino.utils.diag.Analyzer.show_memo_commands' : _("""List the memo commands defined in this application."""),
|
215
|
+
'lino.utils.diag.Analyzer.show_db_structure' : _("""Show a bullet list of all models and their fields."""),
|
219
216
|
'lino.utils.diag.Analyzer.show_database_structure' : _("""Show a bullet list of all models and their fields."""),
|
220
217
|
'lino.utils.diag.Analyzer.show_db_overview' : _("""Print a reStructredText-formatted “database overview” report. Used by test cases in tested documents."""),
|
221
218
|
'lino.utils.diag.Analyzer.show_foreign_keys' : _("""Return a list that shows how database objects are being referred to by some other database object. This information is important (1) before deleting objects and (2) when merging them."""),
|
@@ -399,7 +396,6 @@ help_texts = {
|
|
399
396
|
'lino.modlib.publisher.PublishableContent.publishing_state' : _("""Default value is ‘draft’"""),
|
400
397
|
'lino.modlib.publisher.PublishableContent.filler' : _("""Pointer to PageFillers"""),
|
401
398
|
'lino.modlib.publisher.PublishingStates' : _("""A choicelist with the possible states of a publisher page."""),
|
402
|
-
'lino.modlib.publisher.PageFillers' : _("""A choicelist with the page fillers that are available for this application."""),
|
403
399
|
'lino.modlib.publisher.SpecialPages' : _("""A choicelist with the special pages available on this site."""),
|
404
400
|
'lino.modlib.search.SiteSearch' : _("""A virtual table that searches in all database tables."""),
|
405
401
|
'lino.modlib.search.ElasticSiteSearch' : _("""A virtual table used to search on this Lino site using ElasticSearch."""),
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2013-
|
2
|
+
# Copyright 2013-2025 by Rumma & Ko Ltd.
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
from lino.utils.mldbc.fields import BabelCharField, BabelTextField
|
@@ -12,7 +12,7 @@ from lino import logger
|
|
12
12
|
import os
|
13
13
|
from decimal import Decimal
|
14
14
|
|
15
|
-
from
|
15
|
+
from click import progressbar
|
16
16
|
|
17
17
|
from django.db import models
|
18
18
|
from django.conf import settings
|
@@ -311,7 +311,8 @@ def main(args):
|
|
311
311
|
)
|
312
312
|
|
313
313
|
max_row_count = self.options["max_row_count"]
|
314
|
-
|
314
|
+
with progressbar(self.models) as bar:
|
315
|
+
for model in bar:
|
315
316
|
try:
|
316
317
|
qs = model.objects.all()
|
317
318
|
total_count = qs.count()
|
@@ -301,9 +301,6 @@ class Command(BaseCommand):
|
|
301
301
|
# if engine == 'django.db.backends.postgresql':
|
302
302
|
# foralltables(using, "ALTER TABLE {} ENABLE TRIGGER ALL;")
|
303
303
|
|
304
|
-
# if buildcache: # why did we add this at all?
|
305
|
-
# settings.SITE.build_site_cache(verbosity=verbosity)
|
306
|
-
|
307
304
|
settings.SITE.clear_site_config()
|
308
305
|
|
309
306
|
# dblogger.info("Lino initdb %s done on database %s.", args, dbname)
|
lino/modlib/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
The content of directory `static/bootstrap-5.3.7` comes from
|
2
|
-
|
2
|
+
https://getbootstrap.com
|
@@ -18,44 +18,40 @@ from lino.api.ad import Plugin
|
|
18
18
|
|
19
19
|
class Plugin(Plugin):
|
20
20
|
# ui_label = _("Bootstrap")
|
21
|
-
ui_handle_attr_name = "bootstrap5_handle"
|
22
|
-
|
23
21
|
# site_js_snippets = ['snippets/plain.js']
|
24
|
-
|
25
22
|
needs_plugins = ["lino.modlib.jinja"]
|
26
|
-
|
27
|
-
url_prefix = "bs5"
|
28
|
-
|
29
23
|
media_name = "bootstrap-5.3.7"
|
30
|
-
|
31
24
|
# media_base_url = "http://maxcdn.bootstrapcdn.com/bootstrap/5.3.7/"
|
32
25
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
26
|
+
# ui_handle_attr_name = "bootstrap5_handle"
|
27
|
+
# url_prefix = "bs5"
|
28
|
+
#
|
29
|
+
# def on_ui_init(self, kernel):
|
30
|
+
# from .renderer import Renderer
|
31
|
+
#
|
32
|
+
# self.renderer = Renderer(self)
|
33
|
+
# # ui.bs5_renderer = self.renderer
|
34
|
+
#
|
35
|
+
# def get_patterns(self):
|
36
|
+
# # from django.conf.urls import url
|
37
|
+
# from django.urls import re_path as url
|
38
|
+
# from . import views
|
39
|
+
#
|
40
|
+
# rx = "^"
|
41
|
+
#
|
42
|
+
# urls = [
|
43
|
+
# # url(rx + r'/?$', views.Index.as_view()),
|
44
|
+
# url(rx + r"$", views.Index.as_view()),
|
45
|
+
# url(rx + r"auth", views.Authenticate.as_view()),
|
46
|
+
# # NB app_label must be at least 3 chars long to avoid clash with
|
47
|
+
# # publisher patterns
|
48
|
+
# url(rx + r"(?P<app_label>\w\w\w+)/(?P<actor>\w+)$", views.List.as_view()),
|
49
|
+
# url(
|
50
|
+
# rx + r"(?P<app_label>\w\w\w+)/(?P<actor>\w+)/(?P<pk>.+)$",
|
51
|
+
# views.Element.as_view(),
|
52
|
+
# ),
|
53
|
+
# ]
|
54
|
+
# return urls
|
59
55
|
|
60
56
|
def get_detail_url(self, ar, actor, pk, *args, **kw):
|
61
57
|
return self.build_plain_url(
|
@@ -64,10 +60,10 @@ class Plugin(Plugin):
|
|
64
60
|
|
65
61
|
def get_used_libs(self, html=False):
|
66
62
|
if html is not None:
|
67
|
-
yield ("Bootstrap", "5.3.7", "
|
63
|
+
yield ("Bootstrap", "5.3.7", "https://getbootstrap.com")
|
68
64
|
# yield ("jQuery", '?', "http://...")
|
69
65
|
|
70
|
-
def get_index_view(self):
|
71
|
-
|
72
|
-
|
73
|
-
|
66
|
+
# def get_index_view(self):
|
67
|
+
# from . import views
|
68
|
+
#
|
69
|
+
# return views.Index.as_view()
|
@@ -6,7 +6,11 @@
|
|
6
6
|
<link rel="stylesheet" href="{{site.plugins.bootstrap5.build_lib_url('css','bootstrap.css')}}" type="text/css">
|
7
7
|
<link rel="stylesheet" href="{{site.build_static_url('bootstrap.css')}}" type="text/css">
|
8
8
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/timepicker@1.11.12/jquery.timepicker.min.css" type="text/css">
|
9
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@enzedonline/quill-blot-formatter2/dist/css/quill-blot-formatter2.css">
|
10
|
+
<link rel="stylesheet" href="https://unpkg.com/primeicons/primeicons.css"/>
|
11
|
+
{# Do we need jquery? Isn't this an invalid URL?
|
9
12
|
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
|
13
|
+
#}
|
10
14
|
<link rel="shortcut icon" type="image/png" href="{{ site.build_static_url('favicon2.ico') }}" />
|
11
15
|
|
12
16
|
</head><body>
|
lino/modlib/bootstrap5/models.py
CHANGED
@@ -2,29 +2,29 @@
|
|
2
2
|
# Copyright 2014-2023 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
-
from django.conf import settings
|
6
|
-
from lino.core.tables import AbstractTable
|
7
|
-
from lino.core.roles import Expert
|
5
|
+
# from django.conf import settings
|
6
|
+
# from lino.core.tables import AbstractTable
|
7
|
+
# from lino.core.roles import Expert
|
8
|
+
#
|
9
|
+
# from lino.api import dd, _
|
8
10
|
|
9
|
-
from lino.api import dd, _
|
10
11
|
|
12
|
+
# class ShowAsHtml(dd.Action):
|
13
|
+
# label = _("HTML")
|
14
|
+
# help_text = _("Show this table in Bootstrap3 interface")
|
15
|
+
# icon_name = "html"
|
16
|
+
# ui5_icon_name = "sap-icon://attachment-html"
|
17
|
+
# sort_index = -15
|
18
|
+
# select_rows = False
|
19
|
+
# default_format = "ajax"
|
20
|
+
# preprocessor = "Lino.get_current_grid_config"
|
21
|
+
# callable_from = "t"
|
22
|
+
# required_roles = dd.login_required(Expert)
|
23
|
+
#
|
24
|
+
# def run_from_ui(self, ar, **kw):
|
25
|
+
# url = dd.plugins.bootstrap5.renderer.get_request_url(ar)
|
26
|
+
# ar.success(open_url=url)
|
27
|
+
#
|
11
28
|
|
12
|
-
|
13
|
-
|
14
|
-
help_text = _("Show this table in Bootstrap3 interface")
|
15
|
-
icon_name = "html"
|
16
|
-
ui5_icon_name = "sap-icon://attachment-html"
|
17
|
-
sort_index = -15
|
18
|
-
select_rows = False
|
19
|
-
default_format = "ajax"
|
20
|
-
preprocessor = "Lino.get_current_grid_config"
|
21
|
-
callable_from = "t"
|
22
|
-
required_roles = dd.login_required(Expert)
|
23
|
-
|
24
|
-
def run_from_ui(self, ar, **kw):
|
25
|
-
url = dd.plugins.bootstrap5.renderer.get_request_url(ar)
|
26
|
-
ar.success(open_url=url)
|
27
|
-
|
28
|
-
|
29
|
-
if settings.SITE.default_ui != "lino.modlib.bootstrap5":
|
30
|
-
AbstractTable.show_as_html = ShowAsHtml()
|
29
|
+
# if settings.SITE.default_ui != "lino.modlib.bootstrap5":
|
30
|
+
# AbstractTable.show_as_html = ShowAsHtml()
|
lino/modlib/bootstrap5/views.py
CHANGED
@@ -4,30 +4,26 @@
|
|
4
4
|
"""Views for `lino.modlib.bootstrap5`.
|
5
5
|
|
6
6
|
"""
|
7
|
-
from past.utils import old_div
|
8
7
|
|
9
8
|
from django import http
|
10
9
|
from django.conf import settings
|
11
10
|
from django.views.generic import View
|
12
|
-
from django.core import exceptions
|
13
11
|
from django.utils.translation import gettext as _
|
14
12
|
from django.utils.translation import get_language
|
15
13
|
from django.utils.decorators import method_decorator
|
16
14
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
17
|
-
|
18
15
|
# from django.contrib import auth
|
19
16
|
from lino.core import auth
|
20
|
-
|
21
17
|
# from lino.api import dd
|
22
18
|
from lino.core import constants
|
23
|
-
|
24
19
|
# from lino.core import auth
|
25
20
|
from lino.core.requests import BaseRequest
|
26
21
|
from lino.core.tables import AbstractTable
|
27
22
|
from lino.core.views import action_request
|
28
23
|
from lino.core.utils import navinfo
|
29
24
|
from lino.utils.html import E, tostring
|
30
|
-
|
25
|
+
|
26
|
+
raise Exception("No longer used since 20250826")
|
31
27
|
|
32
28
|
PLAIN_PAGE_LENGTH = 15
|
33
29
|
|
@@ -78,107 +74,6 @@ def buttons2pager(buttons, title=None):
|
|
78
74
|
return E.ul(*items, **{"class": "pagination pagination-sm"})
|
79
75
|
|
80
76
|
|
81
|
-
def table2html(ar, as_main=True):
|
82
|
-
"""Represent the given table request as an HTML table.
|
83
|
-
|
84
|
-
`ar` is the request to be rendered, an instance of
|
85
|
-
:class:`lino.core.requests.ActionRequest`.
|
86
|
-
|
87
|
-
The returned HTML enclosed in a ``<div>`` tag and generated using
|
88
|
-
:mod:`etgen.html`.
|
89
|
-
|
90
|
-
If `as_main` is True, include additional elements such as a paging
|
91
|
-
toolbar. (This argument is currently being ignored.)
|
92
|
-
|
93
|
-
"""
|
94
|
-
# as_main = True
|
95
|
-
t = xghtml.Table()
|
96
|
-
t.attrib.update(**{"class": "table table-striped table-hover"})
|
97
|
-
if ar.limit is None:
|
98
|
-
ar.limit = PLAIN_PAGE_LENGTH
|
99
|
-
pglen = ar.limit
|
100
|
-
if ar.offset is None:
|
101
|
-
page = 1
|
102
|
-
else:
|
103
|
-
"""
|
104
|
-
(assuming pglen is 5)
|
105
|
-
offset page
|
106
|
-
0 1
|
107
|
-
5 2
|
108
|
-
"""
|
109
|
-
page = int(old_div(ar.offset, pglen)) + 1
|
110
|
-
|
111
|
-
ar.dump2html(t, ar.sliced_data_iterator, header_links=as_main)
|
112
|
-
if not as_main:
|
113
|
-
url = ar.get_request_url() or "#" # open in own window
|
114
|
-
return E.div(
|
115
|
-
E.div(
|
116
|
-
E.div(
|
117
|
-
E.a(
|
118
|
-
E.span(**{"class": "glyphicon glyphicon-folder-open"}),
|
119
|
-
href=url,
|
120
|
-
style="margin-left: 4px;",
|
121
|
-
**{"class": "btn btn-default pull-right"},
|
122
|
-
),
|
123
|
-
E.h5(str(ar.get_title()), style="display: inline-block;"),
|
124
|
-
**{"class": "panel-title"},
|
125
|
-
),
|
126
|
-
**{"class": "panel-heading"},
|
127
|
-
),
|
128
|
-
t.as_element(),
|
129
|
-
style="display: inline-block;",
|
130
|
-
**{"class": "panel panel-default"},
|
131
|
-
)
|
132
|
-
|
133
|
-
buttons = []
|
134
|
-
kw = dict()
|
135
|
-
kw = {}
|
136
|
-
if pglen != PLAIN_PAGE_LENGTH:
|
137
|
-
kw[constants.URL_PARAM_LIMIT] = pglen
|
138
|
-
|
139
|
-
if page > 1:
|
140
|
-
kw[constants.URL_PARAM_START] = pglen * (page - 2)
|
141
|
-
prev_url = ar.get_request_url(**kw)
|
142
|
-
kw[constants.URL_PARAM_START] = 0
|
143
|
-
first_url = ar.get_request_url(**kw)
|
144
|
-
else:
|
145
|
-
prev_url = None
|
146
|
-
first_url = None
|
147
|
-
buttons.append(("<<", _("First page"), first_url))
|
148
|
-
buttons.append(("<", _("Previous page"), prev_url))
|
149
|
-
|
150
|
-
next_start = pglen * page
|
151
|
-
if next_start < ar.get_total_count():
|
152
|
-
kw[constants.URL_PARAM_START] = next_start
|
153
|
-
next_url = ar.get_request_url(**kw)
|
154
|
-
last_page = int(old_div((ar.get_total_count() - 1), pglen))
|
155
|
-
kw[constants.URL_PARAM_START] = pglen * last_page
|
156
|
-
last_url = ar.get_request_url(**kw)
|
157
|
-
else:
|
158
|
-
next_url = None
|
159
|
-
last_url = None
|
160
|
-
buttons.append((">", _("Next page"), next_url))
|
161
|
-
buttons.append((">>", _("Last page"), last_url))
|
162
|
-
|
163
|
-
return E.div(buttons2pager(buttons), t.as_element())
|
164
|
-
|
165
|
-
|
166
|
-
def layout2html(ar, elem):
|
167
|
-
wl = ar.bound_action.get_window_layout()
|
168
|
-
if wl is None:
|
169
|
-
raise Exception("{!r} has no window layout".format(ar.bound_action))
|
170
|
-
# ~ print 20120901, wl.main
|
171
|
-
lh = wl.get_layout_handle()
|
172
|
-
|
173
|
-
items = list(lh.main.as_plain_html(ar, elem))
|
174
|
-
# if navigator:
|
175
|
-
# items.insert(0, navigator)
|
176
|
-
# ~ print tostring(E.div())
|
177
|
-
# ~ if len(items) == 0: return ""
|
178
|
-
return E.form(*items)
|
179
|
-
# ~ print 20120901, lh.main.__html__(ar)
|
180
|
-
|
181
|
-
|
182
77
|
class List(View):
|
183
78
|
"""Render a list of records."""
|
184
79
|
|