lino 25.7.0__py3-none-any.whl → 25.7.2__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 +1 -0
- lino/api/doctest.py +13 -10
- lino/core/__init__.py +0 -2
- lino/core/actions.py +24 -5
- lino/core/actors.py +22 -177
- lino/core/dashboard.py +3 -2
- lino/core/dbtables.py +1 -1
- lino/core/elems.py +1 -1
- lino/core/fields.py +3 -0
- lino/core/kernel.py +6 -0
- lino/core/layouts.py +5 -7
- lino/core/model.py +1 -0
- lino/core/plugin.py +1 -1
- lino/core/renderer.py +7 -5
- lino/core/requests.py +4 -5
- lino/core/site.py +1 -1
- lino/core/utils.py +6 -4
- lino/help_texts.py +2 -1
- lino/mixins/registrable.py +4 -2
- lino/modlib/checkdata/management/commands/checkdata.py +3 -3
- lino/modlib/extjs/views.py +7 -0
- lino/modlib/help/models.py +3 -1
- lino/modlib/linod/__init__.py +1 -1
- lino/modlib/memo/__init__.py +1 -2
- lino/modlib/office/roles.py +0 -1
- lino/modlib/printing/actions.py +2 -6
- lino/modlib/printing/choicelists.py +6 -6
- lino/modlib/printing/mixins.py +2 -2
- lino/modlib/publisher/__init__.py +21 -30
- lino/modlib/publisher/models.py +3 -1
- lino/modlib/publisher/renderer.py +2 -5
- lino/modlib/publisher/views.py +4 -11
- lino/modlib/weasyprint/__init__.py +9 -0
- lino/modlib/weasyprint/choicelists.py +14 -9
- lino/modlib/weasyprint/config/weasyprint/base.weasy.html +15 -13
- lino/utils/jsgen.py +2 -1
- {lino-25.7.0.dist-info → lino-25.7.2.dist-info}/METADATA +1 -1
- {lino-25.7.0.dist-info → lino-25.7.2.dist-info}/RECORD +42 -46
- lino/modlib/forms/__init__.py +0 -51
- lino/modlib/forms/models.py +0 -0
- lino/modlib/forms/renderer.py +0 -74
- lino/modlib/forms/views.py +0 -311
- {lino-25.7.0.dist-info → lino-25.7.2.dist-info}/WHEEL +0 -0
- {lino-25.7.0.dist-info → lino-25.7.2.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.7.0.dist-info → lino-25.7.2.dist-info}/licenses/COPYING +0 -0
lino/core/utils.py
CHANGED
@@ -664,10 +664,11 @@ class Parametrizable:
|
|
664
664
|
parameters = None
|
665
665
|
params_layout = None
|
666
666
|
params_panel_hidden = True
|
667
|
-
params_panel_pos = "
|
667
|
+
params_panel_pos = "bottom" # allowed values "top", "bottom", "left" and "right"
|
668
668
|
use_detail_param_panel = False
|
669
669
|
|
670
670
|
_params_layout_class = NotImplementedError
|
671
|
+
_field_actions = dict()
|
671
672
|
|
672
673
|
def get_window_layout(self, actor):
|
673
674
|
return self.params_layout
|
@@ -1238,11 +1239,12 @@ def register_params(cls):
|
|
1238
1239
|
cls.params_layout = cls._params_layout_class.join_str.join(
|
1239
1240
|
cls.parameters.keys()
|
1240
1241
|
)
|
1242
|
+
if cls.params_layout is not None:
|
1241
1243
|
install_layout(cls, "params_layout", cls._params_layout_class)
|
1242
1244
|
|
1243
|
-
# e.g. accounting.ByJournal is just a mixin but provides a default value for its children
|
1244
|
-
elif cls.params_layout is not None:
|
1245
|
-
|
1245
|
+
# # e.g. accounting.ByJournal is just a mixin but provides a default value for its children
|
1246
|
+
# elif cls.params_layout is not None:
|
1247
|
+
# raise Exception("{} has a params_layout but no parameters".format(cls))
|
1246
1248
|
|
1247
1249
|
# if isinstance(cls, type) and cls.__name__.endswith("Users"):
|
1248
1250
|
# # if isinstance(cls, type) and cls.model is not None and cls.model.__name__ == "User":
|
lino/help_texts.py
CHANGED
@@ -312,7 +312,6 @@ help_texts = {
|
|
312
312
|
'lino.core.model.Model.create_from_choice' : _("""Called when a learning combo has been submitted. Create a persistent database object if the given text contains enough information."""),
|
313
313
|
'lino.core.model.Model.choice_text_to_dict' : _("""Return a dict of the fields to fill when the given text contains enough information for creating a new database object."""),
|
314
314
|
'lino.core.model.Model.allow_cascaded_delete' : _("""A set of names of ForeignKey or GenericForeignKey fields of this model that allow for cascaded delete."""),
|
315
|
-
'lino.core.model.Model.disabled_fields' : _("""Return a set of field names that should be disabled (i.e. not editable) for this database object."""),
|
316
315
|
'lino.core.model.Model.__str__' : _("""Return a translatable text that describes this database row."""),
|
317
316
|
'lino.core.model.Model.as_str' : _("""Return a translatable text that describes this database row. Unlike __str__() this method gets an action request when it is called, so it knows the context."""),
|
318
317
|
'lino.core.model.Model.get_str_words' : _("""Yield a series of words that describe this database row in plain text."""),
|
@@ -705,11 +704,13 @@ help_texts = {
|
|
705
704
|
'lino.modlib.weasyprint.WeasyHtmlBuildMethod' : _("""Renders the input template and returns the unmodified output as plain HTML."""),
|
706
705
|
'lino.modlib.weasyprint.WeasyPdfBuildMethod' : _("""Like WeasyBuildMethod, but the rendered HTML is then passed through weasyprint which converts from HTML to PDF."""),
|
707
706
|
'lino.core.model.Model' : _("""Lino extension of Django’s database model. This is a subclass of Django’s Model class (django.db.models.Model)."""),
|
707
|
+
'lino.core.model.Model.__init__' : _("""The first positional argument is the optional label, other arguments should be specified as keywords and can be any of the existing class attributes."""),
|
708
708
|
'lino.core.model.Model.overview' : _("""A multi-paragraph representation of this database row."""),
|
709
709
|
'lino.core.model.Model.navigation_panel' : _("""A virtual field that displays the navigation panel for this row. This may be included in a detail layout, usually either on the left or the right side with full height."""),
|
710
710
|
'lino.core.model.Model.workflow_buttons' : _("""Shows the current workflow state of this database row and a list of available workflow actions."""),
|
711
711
|
'lino.core.model.Model.workflow_state_field' : _("""Optional default value for the workflow_state_field of all data tables based on this model."""),
|
712
712
|
'lino.core.model.Model.workflow_owner_field' : _("""Optional default value for workflow_owner_field on all data tables based on this model."""),
|
713
|
+
'lino.core.model.Model.disabled_fields' : _("""Return a set of field names that should be disabled (i.e. not editable) for this database object."""),
|
713
714
|
'lino.core.model.Model.FOO_changed' : _("""Called when field FOO of an instance of this model has been modified through the user interface."""),
|
714
715
|
'lino.core.model.Model.FOO_choices' : _("""Return a queryset or list of allowed choices for field FOO."""),
|
715
716
|
'lino.core.model.Model.create_FOO_choice' : _("""For every field named “FOO” for which a chooser exists, if the model also has a method called “create_FOO_choice”, then this chooser will be a learning chooser. That is, users can enter text into the combobox, and Lino will create a new database object from it."""),
|
lino/mixins/registrable.py
CHANGED
@@ -118,12 +118,14 @@ class Registrable(model.Model):
|
|
118
118
|
# yield 'date'
|
119
119
|
|
120
120
|
def disabled_fields(self, ar):
|
121
|
+
rv = super().disabled_fields(ar)
|
121
122
|
if not self.state.is_editable:
|
122
123
|
# return self._registrable_fields
|
123
124
|
# Copy _registrable_fields otherwise _registrable_fields get
|
124
125
|
# modified as more disabled fields are added to the set.
|
125
|
-
return self._registrable_fields.copy()
|
126
|
-
|
126
|
+
# return self._registrable_fields.copy()
|
127
|
+
rv |= self._registrable_fields
|
128
|
+
return rv
|
127
129
|
|
128
130
|
def get_row_permission(self, ar, state, ba):
|
129
131
|
"""Only rows in an editable state may be edited.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2015-
|
2
|
+
# Copyright 2015-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
from django.core.management.base import BaseCommand, CommandError
|
@@ -7,7 +7,7 @@ from django.core.management.base import BaseCommand, CommandError
|
|
7
7
|
from lino.modlib.checkdata.choicelists import Checkers
|
8
8
|
from lino.modlib.checkdata.models import check_data
|
9
9
|
|
10
|
-
from lino.api import rt
|
10
|
+
from lino.api import dd, rt
|
11
11
|
|
12
12
|
|
13
13
|
class Command(BaseCommand):
|
@@ -56,7 +56,7 @@ class Command(BaseCommand):
|
|
56
56
|
app = options.get("checkers", args)
|
57
57
|
if app:
|
58
58
|
args += tuple(app)
|
59
|
-
ar = rt.login()
|
59
|
+
ar = rt.login(dd.plugins.users.demo_username)
|
60
60
|
if options["list"]:
|
61
61
|
ar.show(Checkers, column_names="value text")
|
62
62
|
else:
|
lino/modlib/extjs/views.py
CHANGED
@@ -463,6 +463,13 @@ class ApiElement(View):
|
|
463
463
|
else:
|
464
464
|
datarec = ar.elem2rec_detailed(elem)
|
465
465
|
datarec.update(**vm)
|
466
|
+
|
467
|
+
fa = dict()
|
468
|
+
for k, lst in rpt._field_actions.items():
|
469
|
+
fa[k] = [ar.row_action_button(elem, ba) for ba in lst]
|
470
|
+
if fa:
|
471
|
+
datarec.update(field_actions=fa)
|
472
|
+
|
466
473
|
return json_response(datarec)
|
467
474
|
|
468
475
|
after_show = ar.get_status(record_id=pk)
|
lino/modlib/help/models.py
CHANGED
@@ -21,7 +21,9 @@ class OpenHelpWindow(dd.Action):
|
|
21
21
|
# I undid that change:
|
22
22
|
# button_text = " ? "
|
23
23
|
# button_text = "?"
|
24
|
-
button_text = "🛈"
|
24
|
+
# button_text = "🛈"
|
25
|
+
button_text = "ⓘ" # 24d8
|
26
|
+
# button_text = "🯄" # 1fbc4
|
25
27
|
select_rows = False
|
26
28
|
help_text = _("Open Help Window")
|
27
29
|
show_in_plain = True
|
lino/modlib/linod/__init__.py
CHANGED
@@ -50,7 +50,7 @@ class Plugin(ad.Plugin):
|
|
50
50
|
m = m.add_menu(mg.app_label, mg.verbose_name)
|
51
51
|
m.add_action("linod.Procedures")
|
52
52
|
|
53
|
-
def
|
53
|
+
def get_needed_plugins(self):
|
54
54
|
# We don't use needs_plugins because it depends on use_channels. We must
|
55
55
|
# not install the plugin when the Python package isn't installed because
|
56
56
|
# otherwise `pm install` fails with ModuleNotFoundError: No module named
|
lino/modlib/memo/__init__.py
CHANGED
@@ -50,7 +50,7 @@ class Plugin(ad.Plugin):
|
|
50
50
|
"""The front end to use when writing previews.
|
51
51
|
|
52
52
|
If this is `None`, Lino will use the default :term:`front end`
|
53
|
-
(:attr:`lino.core.site.Site.
|
53
|
+
(:attr:`lino.core.site.Site.editing_front_end`).
|
54
54
|
|
55
55
|
Used on sites that are available through more than one web front ends. The
|
56
56
|
:term:`server administrator` must then decide which front end is the primary
|
@@ -115,7 +115,6 @@ class Plugin(ad.Plugin):
|
|
115
115
|
def post_site_startup(self, site):
|
116
116
|
if self.front_end is None:
|
117
117
|
self.front_end = site.kernel.editing_front_end
|
118
|
-
# web_front_ends[0]
|
119
118
|
else:
|
120
119
|
self.front_end = site.plugins.resolve(self.front_end)
|
121
120
|
|
lino/modlib/office/roles.py
CHANGED
lino/modlib/printing/actions.py
CHANGED
@@ -294,19 +294,15 @@ class EditTemplate(BasePrintAction):
|
|
294
294
|
ar.confirm(ok, msg, _("Are you sure?"))
|
295
295
|
|
296
296
|
|
297
|
-
class
|
297
|
+
class ClearCache(Action):
|
298
298
|
sort_index = 51
|
299
299
|
url_action_name = "clear"
|
300
300
|
label = _("Clear cache")
|
301
301
|
icon_name = "printer_delete"
|
302
302
|
|
303
|
-
# def disabled_for(self,obj,request):
|
304
|
-
# if not obj.build_time:
|
305
|
-
# return True
|
306
|
-
|
307
303
|
def get_action_permission(self, ar, obj, state):
|
308
304
|
# obj may be None when Lino asks whether this action
|
309
|
-
# should be visible in the
|
305
|
+
# should be visible in the table toolbar
|
310
306
|
if obj is not None and not obj.build_time:
|
311
307
|
return False
|
312
308
|
return super().get_action_permission(ar, obj, state)
|
@@ -33,9 +33,9 @@ except ImportError:
|
|
33
33
|
|
34
34
|
|
35
35
|
class BuildMethod(Choice):
|
36
|
-
target_ext = None
|
37
|
-
cache_name = "cache"
|
38
|
-
use_webdav = False
|
36
|
+
target_ext: str = None
|
37
|
+
cache_name: str = "cache"
|
38
|
+
use_webdav: bool = False
|
39
39
|
|
40
40
|
def __init__(self, names=None, **kwargs):
|
41
41
|
# For build methods, `Choice.names` and `Choice.value` are the
|
@@ -65,9 +65,9 @@ class BuildMethod(Choice):
|
|
65
65
|
|
66
66
|
|
67
67
|
class TemplatedBuildMethod(BuildMethod):
|
68
|
-
template_ext = None
|
69
|
-
templates_name = None
|
70
|
-
default_template = "" # overridden by lino_xl.lib.appypod
|
68
|
+
template_ext: str = None
|
69
|
+
templates_name: str = None
|
70
|
+
default_template: str = "" # overridden by lino_xl.lib.appypod
|
71
71
|
|
72
72
|
def __init__(self, *args, **kwargs):
|
73
73
|
super().__init__(*args, **kwargs)
|
lino/modlib/printing/mixins.py
CHANGED
@@ -22,7 +22,7 @@ from .choicelists import BuildMethods
|
|
22
22
|
from .actions import (
|
23
23
|
DirectPrintAction,
|
24
24
|
CachedPrintAction,
|
25
|
-
|
25
|
+
ClearCache,
|
26
26
|
EditTemplate,
|
27
27
|
)
|
28
28
|
|
@@ -153,7 +153,7 @@ class CachedPrintable(Duplicable, Printable):
|
|
153
153
|
abstract = True
|
154
154
|
|
155
155
|
do_print = CachedPrintAction()
|
156
|
-
do_clear_cache =
|
156
|
+
do_clear_cache = ClearCache()
|
157
157
|
edit_template = EditTemplate()
|
158
158
|
|
159
159
|
build_time = models.DateTimeField(
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2020-
|
2
|
+
# Copyright 2020-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
from lino.api.ad import Plugin
|
@@ -12,17 +12,7 @@ class Plugin(Plugin):
|
|
12
12
|
"lino.modlib.jinja",
|
13
13
|
"lino.modlib.bootstrap3",
|
14
14
|
]
|
15
|
-
locations = []
|
16
|
-
|
17
|
-
def setup_main_menu(self, site, user_type, m, ar=None):
|
18
|
-
mg = self.get_menu_group()
|
19
|
-
m = m.add_menu(mg.app_label, mg.verbose_name)
|
20
|
-
m.add_action("publisher.Pages")
|
21
|
-
|
22
|
-
def setup_config_menu(self, site, user_type, m, ar=None):
|
23
|
-
mg = self.get_menu_group()
|
24
|
-
m = m.add_menu(mg.app_label, mg.verbose_name)
|
25
|
-
m.add_action("publisher.SpecialPages")
|
15
|
+
locations: list[tuple[str, str]] = []
|
26
16
|
|
27
17
|
def get_requirements(self, site):
|
28
18
|
yield "python-lorem"
|
@@ -41,34 +31,35 @@ class Plugin(Plugin):
|
|
41
31
|
app = site.models.get(app_label)
|
42
32
|
cls = getattr(app, model_name, None)
|
43
33
|
if not isinstance(cls, type) or not issubclass(cls, Actor):
|
44
|
-
raise Exception("location {}: {} is not an Actor"
|
34
|
+
raise Exception(f"location {loc}: {cls} is not an Actor")
|
45
35
|
if not issubclass(cls.model, Publishable):
|
46
36
|
raise Exception(
|
47
|
-
"location {}
|
48
|
-
|
49
|
-
)
|
50
|
-
)
|
51
|
-
|
37
|
+
f"location {loc},{view}: "
|
38
|
+
f"model {type(cls.model)} is not Publishable")
|
52
39
|
cls.model._lino_publisher_location = loc
|
53
40
|
locations.append((loc, cls))
|
54
41
|
self.locations = tuple(locations)
|
55
42
|
|
56
43
|
def get_patterns(self):
|
57
44
|
from django.urls import re_path as url
|
58
|
-
from lino.core.utils import models_by_base
|
59
45
|
from . import views
|
60
|
-
# from .choicelists import PublisherViews
|
61
|
-
# raise Exception("20220927")
|
62
|
-
# print("20220927", list(PublisherViews.get_list_items()))
|
63
46
|
|
64
|
-
|
65
|
-
for publisher_location, table_class in self.locations:
|
66
|
-
# print("20220927", pv.publisher_location)
|
67
|
-
# if publisher_location is not None:
|
47
|
+
for location, table_class in self.locations:
|
68
48
|
yield url(
|
69
|
-
"^{}/(?P<pk>.+)$"
|
70
|
-
views.Element.as_view(table_class=table_class)
|
71
|
-
)
|
49
|
+
f"^{location}/(?P<pk>.+)$",
|
50
|
+
views.Element.as_view(table_class=table_class))
|
72
51
|
|
73
|
-
|
52
|
+
# Only if this is the primary front end:
|
53
|
+
if self.site.kernel.web_front_ends[0] is self:
|
54
|
+
yield url("^$", views.Index.as_view())
|
74
55
|
# yield url('^login$',views.Login.as_view())
|
56
|
+
|
57
|
+
def setup_main_menu(self, site, user_type, m, ar=None):
|
58
|
+
mg = self.get_menu_group()
|
59
|
+
m = m.add_menu(mg.app_label, mg.verbose_name)
|
60
|
+
m.add_action("publisher.Pages")
|
61
|
+
|
62
|
+
def setup_config_menu(self, site, user_type, m, ar=None):
|
63
|
+
mg = self.get_menu_group()
|
64
|
+
m = m.add_menu(mg.app_label, mg.verbose_name)
|
65
|
+
m.add_action("publisher.SpecialPages")
|
lino/modlib/publisher/models.py
CHANGED
@@ -47,6 +47,8 @@ from .ui import *
|
|
47
47
|
|
48
48
|
# class Node(Referrable, Hierarchical, Sequenced, Previewable, Publishable, Commentable):
|
49
49
|
# Polymorphic,
|
50
|
+
|
51
|
+
|
50
52
|
class Page(
|
51
53
|
Hierarchical, Sequenced, Previewable, Commentable, PublishableContent, Taggable
|
52
54
|
):
|
@@ -205,7 +207,7 @@ class Page(
|
|
205
207
|
if not self.children.exists():
|
206
208
|
return
|
207
209
|
|
208
|
-
yield "<p><b>{}</b></p>".format(_("Children:"))
|
210
|
+
# yield "<p><b>{}</b></p>".format(_("Children:"))
|
209
211
|
|
210
212
|
if hlevel > home.child_node_depth:
|
211
213
|
yield " (...)"
|
@@ -2,13 +2,9 @@
|
|
2
2
|
# Copyright 2023 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
-
from lino
|
6
|
-
from lino.core.renderer import HtmlRenderer
|
5
|
+
from lino import logger
|
7
6
|
from lino.core.renderer import add_user_language
|
8
|
-
|
9
7
|
from lino.modlib.bootstrap3.renderer import Renderer
|
10
|
-
from .mixins import Publishable
|
11
|
-
# from .choicelists import PublisherViews
|
12
8
|
|
13
9
|
|
14
10
|
class Renderer(Renderer):
|
@@ -27,6 +23,7 @@ class Renderer(Renderer):
|
|
27
23
|
# if ar.actor is None or not isinstance(obj, ar.actor.model):
|
28
24
|
loc = obj.__class__._lino_publisher_location
|
29
25
|
if loc is None:
|
26
|
+
# logger.warning("No location for %s", obj.__class__)
|
30
27
|
return None
|
31
28
|
add_user_language(kwargs, ar)
|
32
29
|
return self.front_end.buildurl(loc, str(obj.pk), **kwargs)
|
lino/modlib/publisher/views.py
CHANGED
@@ -1,19 +1,12 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2020-
|
2
|
+
# Copyright 2020-2025 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
5
|
from django import http
|
7
|
-
from django.
|
8
|
-
from django.utils import translation
|
9
|
-
|
10
|
-
from lino.api import dd
|
11
|
-
from lino.core import auth
|
12
|
-
from lino.core.requests import BaseRequest, ActionRequest
|
6
|
+
from django.conf import settings
|
13
7
|
from django.core.exceptions import ObjectDoesNotExist
|
14
|
-
|
15
|
-
from django.
|
16
|
-
from django.views.decorators.csrf import ensure_csrf_cookie
|
8
|
+
from django.utils import translation
|
9
|
+
from django.views.generic import View
|
17
10
|
|
18
11
|
|
19
12
|
class Element(View):
|
@@ -39,9 +39,18 @@ class Plugin(ad.Plugin):
|
|
39
39
|
margin_left = 17
|
40
40
|
margin_right = 10
|
41
41
|
space_before_recipient = 15
|
42
|
+
with_bulma = False
|
43
|
+
|
44
|
+
def get_needed_plugins(self):
|
45
|
+
for p in super().get_needed_plugins():
|
46
|
+
yield p
|
47
|
+
if self.with_bulma:
|
48
|
+
yield 'bulma'
|
42
49
|
|
43
50
|
def get_requirements(self, site):
|
44
51
|
yield "imagesize"
|
52
|
+
if self.with_bulma:
|
53
|
+
yield 'django-bulma'
|
45
54
|
|
46
55
|
def pre_site_startup(self, site):
|
47
56
|
for ext in ("jpg", "png"):
|
@@ -2,22 +2,26 @@
|
|
2
2
|
# Copyright 2016-2024 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
-
from pathlib import Path
|
6
5
|
from lino.modlib.jinja.choicelists import JinjaBuildMethod
|
7
6
|
from lino.modlib.printing.choicelists import BuildMethods
|
7
|
+
from lino.api import dd
|
8
8
|
|
9
9
|
try:
|
10
10
|
from weasyprint import HTML
|
11
11
|
except ImportError:
|
12
12
|
HTML = None
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
BULMA_CSS = None
|
15
|
+
|
16
|
+
if dd.plugins.weasyprint.with_bulma:
|
17
|
+
try:
|
18
|
+
from pathlib import Path
|
19
|
+
import bulma
|
20
|
+
from weasyprint import CSS
|
21
|
+
BULMA_CSS = Path(bulma.__file__).parent / "static/bulma/css/style.min.css"
|
22
|
+
assert BULMA_CSS.exists()
|
23
|
+
except ImportError:
|
24
|
+
pass
|
21
25
|
|
22
26
|
|
23
27
|
class WeasyBuildMethod(JinjaBuildMethod):
|
@@ -38,7 +42,8 @@ class WeasyPdfBuildMethod(WeasyBuildMethod):
|
|
38
42
|
def html2file(self, html, filename, context):
|
39
43
|
pdf = HTML(string=html)
|
40
44
|
if BULMA_CSS and context.get('use_bulma_css', False):
|
41
|
-
pdf.write_pdf(
|
45
|
+
pdf.write_pdf(
|
46
|
+
filename, stylesheets=[CSS(filename=BULMA_CSS)])
|
42
47
|
else:
|
43
48
|
pdf.write_pdf(filename)
|
44
49
|
|
@@ -31,13 +31,18 @@ table.footer td {
|
|
31
31
|
border: none;
|
32
32
|
padding: 6pt;
|
33
33
|
}
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
{#
|
35
|
+
Removed after #6179 (The footer of a multipage invoice shows the same
|
36
|
+
pagenumber on each page)
|
37
37
|
|
38
|
-
span.
|
39
|
-
|
40
|
-
}
|
38
|
+
span.page_num_of::after {
|
39
|
+
content: '{{_("Page")}} ' counter(page) ' {{_("of {0}").format("")}}' counter(pages);
|
40
|
+
}
|
41
|
+
|
42
|
+
span.printed_time::after {
|
43
|
+
content: '{{_("Printed")}} {{fdm(dd.today())}} {{_("at")}} {{now.time().strftime("%H:%M")}}';
|
44
|
+
}
|
45
|
+
#}
|
41
46
|
|
42
47
|
body {
|
43
48
|
font-family: "Liberation sans", "Arial", "Helvetica";
|
@@ -83,13 +88,10 @@ div.recipient {
|
|
83
88
|
margin-left: {{dd.plugins.weasyprint.margin_left}}mm;
|
84
89
|
margin-right: {{dd.plugins.weasyprint.margin_right}}mm;
|
85
90
|
{%- if dd.plugins.weasyprint.page_background_image -%}
|
86
|
-
|
87
|
-
background:
|
88
|
-
|
89
|
-
|
90
|
-
background-repeat: no-repeat;
|
91
|
-
background-attachment: fixed;
|
92
|
-
background-size: contain;
|
91
|
+
background-image: url(file://{{dd.plugins.weasyprint.page_background_image}});
|
92
|
+
background-repeat: no-repeat;
|
93
|
+
background-attachment: fixed;
|
94
|
+
background-size: contain;
|
93
95
|
{%- endif -%}
|
94
96
|
font-family: "Liberation sans", "arial";
|
95
97
|
font-size: 10pt;
|
lino/utils/jsgen.py
CHANGED
@@ -430,7 +430,8 @@ def py2js(v, compact=True):
|
|
430
430
|
# raise Exception("Please call the function yourself")
|
431
431
|
return "\n".join([ln for ln in v()])
|
432
432
|
if isinstance(v, MissingRow):
|
433
|
-
|
433
|
+
return json.dumps(repr(v))
|
434
|
+
# raise Exception("Cannot render {}".format(v))
|
434
435
|
if isinstance(v, js_code):
|
435
436
|
return str(v.s) # v.s might be a unicode
|
436
437
|
if v is None:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: lino
|
3
|
-
Version: 25.7.
|
3
|
+
Version: 25.7.2
|
4
4
|
Summary: A framework for writing desktop-like web applications using Django and ExtJS or React
|
5
5
|
Project-URL: Homepage, https://www.lino-framework.org
|
6
6
|
Project-URL: Repository, https://gitlab.com/lino-framework/lino
|