lino 25.8.2__py3-none-any.whl → 25.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lino/__init__.py +1 -1
- lino/api/dd.py +0 -1
- lino/config/unused/403.html +1 -1
- lino/config/unused/404.html +1 -1
- lino/config/unused/500.html +1 -1
- lino/core/__init__.py +0 -1
- lino/core/actions.py +2 -2
- lino/core/actors.py +10 -2
- lino/core/elems.py +1 -1
- lino/core/fields.py +4 -1
- lino/core/kernel.py +5 -1
- lino/core/model.py +2 -11
- lino/core/renderer.py +2 -2
- lino/core/requests.py +12 -12
- lino/core/site.py +5 -82
- lino/core/store.py +3 -1
- lino/core/urls.py +1 -1
- lino/core/user_types.py +1 -10
- lino/help_texts.py +6 -6
- lino/management/commands/initdb.py +0 -3
- lino/modlib/__init__.py +0 -1
- lino/modlib/bootstrap5/README.txt +2 -0
- lino/modlib/bootstrap5/__init__.py +69 -0
- lino/modlib/{bootstrap3/config/bootstrap3 → bootstrap5/config/bootstrap5}/base.html +9 -4
- lino/modlib/{bootstrap3/config/bootstrap3 → bootstrap5/config/bootstrap5}/detail.html +1 -1
- lino/modlib/{bootstrap3/config/bootstrap3 → bootstrap5/config/bootstrap5}/index.html +1 -1
- lino/modlib/{bootstrap3/config/bootstrap3 → bootstrap5/config/bootstrap5}/table.html +1 -1
- lino/modlib/bootstrap5/models.py +30 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.css +4085 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.rtl.css +4084 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.rtl.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.rtl.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-grid.rtl.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.css +597 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.rtl.css +594 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.rtl.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.rtl.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-reboot.rtl.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.css +5406 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.rtl.css +5397 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.rtl.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.rtl.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap-utilities.rtl.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.css +12043 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.rtl.css +12016 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.rtl.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.rtl.min.css +6 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/css/bootstrap.rtl.min.css.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.bundle.js +6315 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.bundle.js.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.bundle.min.js +7 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.bundle.min.js.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.esm.js +4450 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.esm.js.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.esm.min.js +7 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.esm.min.js.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.js +4497 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.js.map +1 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.min.js +7 -0
- lino/modlib/bootstrap5/static/bootstrap-5.3.7/js/bootstrap.min.js.map +1 -0
- lino/modlib/{bootstrap3 → bootstrap5}/views.py +12 -117
- lino/modlib/checkdata/choicelists.py +1 -1
- lino/modlib/comments/fixtures/demo2.py +1 -0
- lino/modlib/comments/mixins.py +1 -8
- lino/modlib/comments/models.py +2 -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/jinja/renderer.py +1 -1
- lino/modlib/linod/mixins.py +3 -2
- lino/modlib/memo/__init__.py +11 -11
- 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/odata/views.py +7 -7
- lino/modlib/publisher/__init__.py +15 -3
- lino/modlib/publisher/choicelists.py +8 -94
- lino/modlib/publisher/config/publisher/page.pub.html +82 -19
- lino/modlib/publisher/fixtures/std.py +14 -1
- lino/modlib/publisher/fixtures/synodalworld.py +3 -1
- lino/modlib/publisher/mixins.py +59 -77
- lino/modlib/publisher/models.py +109 -204
- lino/modlib/publisher/renderer.py +31 -11
- lino/modlib/publisher/ui.py +46 -98
- lino/modlib/publisher/views.py +61 -11
- 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/fixtures/abc.py +20 -0
- lino/modlib/users/mixins.py +6 -6
- lino/modlib/users/models.py +37 -36
- lino/modlib/weasyprint/__init__.py +25 -14
- lino/modlib/weasyprint/choicelists.py +6 -0
- lino/modlib/weasyprint/config/weasyprint/base.weasy.html +43 -27
- 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.2.dist-info → lino-25.9.0.dist-info}/METADATA +1 -1
- {lino-25.8.2.dist-info → lino-25.9.0.dist-info}/RECORD +135 -95
- lino/modlib/bootstrap3/README.txt +0 -2
- lino/modlib/bootstrap3/__init__.py +0 -73
- lino/modlib/bootstrap3/models.py +0 -30
- lino/modlib/bootstrap3/static/bootstrap-3.3.4/css/bootstrap.css +0 -6584
- lino/modlib/bootstrap3/static/bootstrap-3.3.4/css/bootstrap.css.map +0 -1
- lino/modlib/bootstrap3/static/bootstrap-3.3.4/css/bootstrap.min.css +0 -5
- lino/modlib/bootstrap3/static/bootstrap-3.3.4/js/bootstrap.js +0 -2317
- lino/modlib/bootstrap3/static/bootstrap-3.3.4/js/bootstrap.min.js +0 -7
- /lino/modlib/{bootstrap3 → bootstrap5}/renderer.py +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/css/bootstrap-theme.css +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/css/bootstrap-theme.css.map +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/css/bootstrap-theme.min.css +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/fonts/glyphicons-halflings-regular.eot +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/fonts/glyphicons-halflings-regular.svg +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/fonts/glyphicons-halflings-regular.ttf +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/fonts/glyphicons-halflings-regular.woff +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/fonts/glyphicons-halflings-regular.woff2 +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/js/bootstrap_lino.js +0 -0
- /lino/modlib/{bootstrap3/static/bootstrap-3.3.4 → bootstrap5/static/bootstrap-5.3.7}/js/npm.js +0 -0
- {lino-25.8.2.dist-info → lino-25.9.0.dist-info}/WHEEL +0 -0
- {lino-25.8.2.dist-info → lino-25.9.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.8.2.dist-info → lino-25.9.0.dist-info}/licenses/COPYING +0 -0
lino/modlib/publisher/models.py
CHANGED
@@ -1,58 +1,64 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2012-
|
2
|
+
# Copyright 2012-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
from html import escape
|
6
|
+
from lorem import get_paragraph
|
6
7
|
from django.db import models
|
7
|
-
from django.http import HttpResponseRedirect
|
8
8
|
from django.conf import settings
|
9
9
|
from django.utils import translation
|
10
|
-
from django.utils.translation import
|
11
|
-
|
12
|
-
from django.utils import translation
|
13
|
-
from django.conf import settings
|
14
|
-
|
15
|
-
try:
|
16
|
-
from lorem import get_paragraph
|
17
|
-
except ImportError:
|
18
|
-
lorem = None
|
19
|
-
|
20
|
-
# from django.utils.translation import get_language
|
21
|
-
from django.utils.html import mark_safe
|
22
|
-
|
10
|
+
from django.utils.translation import get_language
|
23
11
|
from lino.api import dd, rt, _
|
24
|
-
from lino.utils import mti
|
25
|
-
from lino.utils.html import E, tostring
|
26
|
-
from lino.
|
12
|
+
# from lino.utils import mti
|
13
|
+
from lino.utils.html import E, tostring, format_html
|
14
|
+
from lino.utils.instantiator import get_or_create
|
27
15
|
# from lino.core.renderer import add_user_language
|
28
|
-
|
29
|
-
from lino.utils.mldbc.fields import LanguageField
|
30
|
-
from lino import mixins
|
16
|
+
# from lino.utils.mldbc.fields import LanguageField
|
31
17
|
from lino.mixins import Hierarchical, Sequenced, Referrable
|
32
|
-
|
33
18
|
# from lino.modlib.summaries.mixins import Summarized
|
34
|
-
from lino.modlib.office.roles import OfficeUser
|
35
19
|
from lino.modlib.publisher.mixins import Publishable, PublishableContent
|
36
20
|
from lino.modlib.comments.mixins import Commentable
|
37
21
|
from lino.modlib.linod.choicelists import schedule_daily
|
38
22
|
from lino.modlib.memo.mixins import Previewable
|
39
|
-
from lino.mixins.polymorphic import Polymorphic
|
40
|
-
from lino_xl.lib.topics.mixins import Taggable
|
41
23
|
from lino.modlib.users.mixins import PrivacyRelevant
|
42
|
-
|
24
|
+
from lino_xl.lib.topics.mixins import Taggable
|
43
25
|
|
44
|
-
from
|
45
|
-
from .choicelists import PublishingStates, PageFillers, SpecialPages
|
26
|
+
from .choicelists import PublishingStates, SpecialPages
|
46
27
|
from .mixins import Publishable
|
47
28
|
from .ui import *
|
48
29
|
|
49
|
-
|
50
|
-
|
30
|
+
|
31
|
+
class Tree(PrivacyRelevant, Referrable):
|
32
|
+
class Meta:
|
33
|
+
verbose_name = _("Tree")
|
34
|
+
verbose_name_plural = _("Trees")
|
35
|
+
abstract = dd.is_abstract_model(__name__, "Tree")
|
36
|
+
# unique_together = ["ref", "language"]
|
37
|
+
|
38
|
+
# ref = dd.CharField(_("Reference"), max_length=200, blank=True, null=True)
|
39
|
+
# root_page = dd.ForeignKey(
|
40
|
+
# "publisher.Page", null=True, blank=True,
|
41
|
+
# verbose_name=_("Root page"), related_name='+')
|
42
|
+
|
43
|
+
@dd.virtualfield(dd.ForeignKey(
|
44
|
+
'publisher.Page', verbose_name=_("Root page")))
|
45
|
+
def root_page(self, ar=None):
|
46
|
+
return self.get_root_page(get_language())
|
47
|
+
|
48
|
+
def get_root_page(self, language):
|
49
|
+
if self.pk is not None:
|
50
|
+
qs = Page.objects.filter(
|
51
|
+
parent__isnull=True, publisher_tree=self, language=language)
|
52
|
+
return qs.first()
|
53
|
+
# try:
|
54
|
+
# return Page.objects.get(parent=None, publisher_tree=self)
|
55
|
+
# except Page.DoesNotExist:
|
56
|
+
# return None
|
51
57
|
|
52
58
|
|
53
59
|
class Page(
|
54
60
|
Hierarchical, Sequenced, Previewable, Commentable, PublishableContent,
|
55
|
-
Taggable
|
61
|
+
Taggable
|
56
62
|
):
|
57
63
|
class Meta:
|
58
64
|
verbose_name = _("Page")
|
@@ -62,30 +68,21 @@ class Page(
|
|
62
68
|
# unique_together = ["group", "ref", "language"]
|
63
69
|
# else:
|
64
70
|
# unique_together = ["ref", "language"]
|
65
|
-
unique_together = ["
|
71
|
+
# unique_together = ["publisher_tree", "language"]
|
66
72
|
|
67
73
|
memo_command = "page"
|
74
|
+
allow_cascaded_delete = ['parent']
|
68
75
|
|
69
|
-
ref = dd.CharField(_("Reference"), max_length=200, blank=True, null=True)
|
70
76
|
title = dd.CharField(_("Title"), max_length=250, blank=True)
|
71
77
|
child_node_depth = models.IntegerField(default=1)
|
72
|
-
# page_type = PageTypes.field(blank=True, null=True)
|
73
78
|
special_page = SpecialPages.field(blank=True)
|
74
79
|
|
75
|
-
translated_from = dd.ForeignKey(
|
76
|
-
"publisher.Page",
|
77
|
-
verbose_name=_("Translated from"),
|
78
|
-
null=True,
|
79
|
-
blank=True,
|
80
|
-
related_name="translated_to",
|
81
|
-
)
|
82
|
-
|
83
80
|
previous_page = dd.ForeignKey(
|
84
|
-
"self", null=True, blank=True,
|
85
|
-
|
81
|
+
"self", null=True, blank=True, editable=False,
|
82
|
+
verbose_name=_("Previous page"), related_name='+')
|
86
83
|
|
87
84
|
def __str__(self):
|
88
|
-
return self.title or
|
85
|
+
return self.title or super().__str__()
|
89
86
|
|
90
87
|
# def on_create(self, ar):
|
91
88
|
# self.page_type = self.get_page_type()
|
@@ -102,22 +99,27 @@ class Page(
|
|
102
99
|
def get_node_info(self, ar):
|
103
100
|
return ""
|
104
101
|
|
105
|
-
|
106
|
-
|
107
|
-
# super().full_clean()
|
102
|
+
def is_public(self):
|
103
|
+
return not self.publisher_tree.private
|
108
104
|
|
109
105
|
def mti_child(self):
|
110
106
|
# if self.page_type:
|
111
107
|
# return mti.get_child(self, self.page_type.nodes_table.model) or self
|
112
108
|
return self
|
113
109
|
|
110
|
+
def walk(self):
|
111
|
+
yield self
|
112
|
+
for c in self.children.all():
|
113
|
+
for i in c.walk():
|
114
|
+
yield i
|
115
|
+
|
114
116
|
# def as_summary_row(self, ar, **kwargs):
|
115
117
|
# return ar.obj2htmls(self, **kwargs)
|
116
118
|
|
117
119
|
# def as_story_item(self, ar, **kwargs):
|
118
120
|
# return "".join(self.as_page(ar, **kwargs))
|
119
121
|
|
120
|
-
def
|
122
|
+
def old_as_paragraph(self, ar):
|
121
123
|
title = E.b(escape(self.title))
|
122
124
|
url = ar.obj2url(self)
|
123
125
|
if url is not None:
|
@@ -128,6 +130,17 @@ class Page(
|
|
128
130
|
item = E.li(title, body)
|
129
131
|
return tostring(item)
|
130
132
|
|
133
|
+
def as_paragraph(self, ar):
|
134
|
+
title = format_html("<b>{}</b>", self.title)
|
135
|
+
if (url := ar.obj2url(self)) is not None:
|
136
|
+
title = format_html(
|
137
|
+
'<a href="{url}" style="text-decoration:none;color:black;">{title}</a>',
|
138
|
+
title=title, url=url)
|
139
|
+
body = self.get_body_parsed(ar, short=True)
|
140
|
+
if body:
|
141
|
+
return format_html("{} — {}", title, body)
|
142
|
+
return title
|
143
|
+
|
131
144
|
def toc_html(self, ar, max_depth=1):
|
132
145
|
def li(obj):
|
133
146
|
# return "<li>{}</li>".format(obj.memo2html(ar, str(obj)))
|
@@ -144,8 +157,7 @@ class Page(
|
|
144
157
|
if len(breadcrumbs) > 1:
|
145
158
|
breadcrumbs = [
|
146
159
|
"""<a href="{0}">{1}</a>""".format(
|
147
|
-
ar.obj2url(p.mti_child()), p.title
|
148
|
-
)
|
160
|
+
ar.obj2url(p.mti_child()), p.title)
|
149
161
|
for p in breadcrumbs[:-1]
|
150
162
|
]
|
151
163
|
yield "<p>{}</p>".format(" » ".join(breadcrumbs))
|
@@ -181,7 +193,7 @@ class Page(
|
|
181
193
|
|
182
194
|
# if display_mode in ("detail", "story"):
|
183
195
|
if display_mode == "detail":
|
184
|
-
if hlevel == 1 and not dd.plugins.memo.use_markup and self.
|
196
|
+
if hlevel == 1 and not dd.plugins.memo.use_markup and self.parent_id:
|
185
197
|
yield self.toc_html(ar)
|
186
198
|
|
187
199
|
if hlevel == 1 and self.main_image:
|
@@ -198,12 +210,11 @@ class Page(
|
|
198
210
|
# yield self.body_full_preview
|
199
211
|
yield self.get_body_parsed(ar, short=False)
|
200
212
|
|
201
|
-
if self.filler:
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
yield self.filler.get_dynamic_paragraph(ar, self)
|
213
|
+
# if self.filler:
|
214
|
+
# if hlevel == 1:
|
215
|
+
# yield self.filler.get_dynamic_story(ar, self)
|
216
|
+
# else:
|
217
|
+
# yield self.filler.get_dynamic_paragraph(ar, self)
|
207
218
|
|
208
219
|
# if dd.plugins.memo.use_markup:
|
209
220
|
# return
|
@@ -246,77 +257,20 @@ class Page(
|
|
246
257
|
return
|
247
258
|
return "".join(ar.row_as_page(self))
|
248
259
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
# node.set_prev(prev)
|
257
|
-
# prev = node
|
258
|
-
# for c in node.children.all():
|
259
|
-
# prev = walk(c, prev)
|
260
|
-
# return prev
|
261
|
-
# root = self.get_ancestor()
|
262
|
-
# last = walk(root)
|
263
|
-
# root.set_prev(last)
|
264
|
-
|
265
|
-
# from pprint import pprint
|
266
|
-
# pprint(self.whole_tree())
|
267
|
-
|
268
|
-
# def get_sidebar_caption(self):
|
269
|
-
# if self.title:
|
270
|
-
# return self.title
|
271
|
-
# if self.ref:
|
272
|
-
# return self.ref
|
273
|
-
# return str(self.id)
|
274
|
-
#
|
275
|
-
# #~ if self.ref or self.parent:
|
276
|
-
# #~ return self.ref
|
277
|
-
# #~ return unicode(_('Home'))
|
278
|
-
|
279
|
-
# def get_sidebar_item(self, request, other):
|
280
|
-
# kw = dict()
|
281
|
-
# add_user_language(kw, request)
|
282
|
-
# url = self.get_absolute_url(**kw)
|
283
|
-
# a = E.a(self.get_sidebar_caption(), href=url)
|
284
|
-
# if self == other:
|
285
|
-
# return E.li(a, **{'class':'active'})
|
286
|
-
# return E.li(a)
|
287
|
-
#
|
288
|
-
# def get_sidebar_html(self, request):
|
289
|
-
# items = []
|
290
|
-
# #~ loop over top-level nodes
|
291
|
-
# for n in self.__class__.objects.filter(parent__isnull=True).order_by('seqno'):
|
292
|
-
# #~ items += [li for li in n.get_sidebar_items(request,self)]
|
293
|
-
# items.append(n.get_sidebar_item(request, self))
|
294
|
-
# if self.is_parented(n):
|
295
|
-
# children = []
|
296
|
-
# for ch in n.children.order_by('seqno'):
|
297
|
-
# children.append(ch.get_sidebar_item(request, self))
|
298
|
-
# if len(children):
|
299
|
-
# items.append(E.ul(*children, **{'class':'nav nav-list'}))
|
300
|
-
#
|
301
|
-
# e = E.ul(*items, **{'class':'nav nav-list'})
|
302
|
-
# return tostring_pretty(e)
|
303
|
-
#
|
304
|
-
# def get_sidebar_menu(self, request):
|
305
|
-
# qs = self.__class__.objects.filter(parent__isnull=True, language=get_language())
|
306
|
-
# #~ qs = self.children.all()
|
307
|
-
# yield ('/', 'index', str(_('Home')))
|
308
|
-
# #~ yield ('/downloads/', 'downloads', 'Downloads')
|
309
|
-
# #~ yield ('/about', 'about', 'About')
|
310
|
-
# #~ if qs is not None:
|
311
|
-
# for obj in qs.order_by("seqno"):
|
312
|
-
# if obj.ref and obj.title:
|
313
|
-
# yield ('/' + obj.ref, obj.ref, obj.title)
|
314
|
-
# #~ else:
|
315
|
-
# #~ yield ('/','index',obj.title)
|
316
|
-
|
317
|
-
def set_previous_page(self, prev):
|
260
|
+
def full_clean(self):
|
261
|
+
if self.publisher_tree is None and self.parent is not None:
|
262
|
+
self.publisher_tree = self.parent.publisher_tree
|
263
|
+
super().full_clean()
|
264
|
+
|
265
|
+
def update_page(self, prev, tree):
|
266
|
+
save = False
|
318
267
|
if self.previous_page != prev:
|
319
268
|
self.previous_page = prev
|
269
|
+
save = True
|
270
|
+
if self.publisher_tree != tree:
|
271
|
+
self.publisher_tree = tree
|
272
|
+
save = True
|
273
|
+
if save:
|
320
274
|
self.save()
|
321
275
|
|
322
276
|
def get_prev_link(self, ar, text="◄"): # "◄" 0x25c4
|
@@ -339,18 +293,6 @@ class Page(
|
|
339
293
|
# url = ar.obj2url(next_node.mti_child())
|
340
294
|
# return """<a href="{}">{}</a>""".format(url, text)
|
341
295
|
|
342
|
-
@classmethod
|
343
|
-
def get_publisher_pages(cls):
|
344
|
-
def walk(page, prev=None):
|
345
|
-
yield page
|
346
|
-
for c in page.children.all():
|
347
|
-
for i in walk(c):
|
348
|
-
yield i
|
349
|
-
|
350
|
-
for root in cls.objects.filter(parent__isnull=True):
|
351
|
-
for i in walk(root):
|
352
|
-
yield i
|
353
|
-
|
354
296
|
@classmethod
|
355
297
|
def get_dashboard_objects(cls, user):
|
356
298
|
# print("20210114 get_dashboard_objects()", get_language())
|
@@ -367,80 +309,41 @@ class Page(
|
|
367
309
|
|
368
310
|
def get_absolute_url(self, **kwargs):
|
369
311
|
parts = []
|
370
|
-
if self.group is not None:
|
371
|
-
|
372
|
-
|
373
|
-
if self.ref:
|
374
|
-
if self.ref != "index":
|
375
|
-
parts.append(self.
|
312
|
+
# if self.group is not None:
|
313
|
+
# if self.group.ref is not None:
|
314
|
+
# parts.append(self.group.ref)
|
315
|
+
if self.publisher_tree.ref:
|
316
|
+
if self.publisher_tree.ref != "index":
|
317
|
+
parts.append(self.publisher_tree.ref)
|
376
318
|
return dd.plugins.publisher.build_plain_url(*parts, **kwargs)
|
377
319
|
|
378
|
-
def get_publisher_response(self, ar):
|
379
|
-
if ar and ar.request and self.language != ar.request.LANGUAGE_CODE:
|
380
|
-
rqlang = ar.request.LANGUAGE_CODE
|
381
|
-
# tt = rt.models.pages.Translation.objects.filter(
|
382
|
-
# parent=self, language=ar.request.LANGUAGE_CODE).first()
|
383
|
-
obj = None
|
384
|
-
if self.translated_from_id and self.translated_from.language == rqlang:
|
385
|
-
obj = self.translated_from
|
386
|
-
else:
|
387
|
-
sources = set([self.id])
|
388
|
-
p = self.translated_from
|
389
|
-
while p is not None:
|
390
|
-
sources.add(p.id)
|
391
|
-
p = p.translated_from
|
392
|
-
qs = self.__class__.objects.filter(
|
393
|
-
language=rqlang, translated_from__in=sources)
|
394
|
-
obj = qs.first()
|
395
|
-
# obj = self.translated_to.filter(language=rqlang).first()
|
396
|
-
# print("20231027 redirect to translation", tt.language, ar.request.LANGUAGE_CODE)
|
397
|
-
if obj is not None:
|
398
|
-
# print("20231028", self.language, "!=", ar.request.LANGUAGE_CODE, tt)
|
399
|
-
ar.selected_rows = [obj]
|
400
|
-
url = ar.get_request_url()
|
401
|
-
return HttpResponseRedirect(url)
|
402
|
-
return super().get_publisher_response(ar)
|
403
|
-
|
404
320
|
|
405
321
|
if dd.plugins.memo.use_markup:
|
406
322
|
dd.update_field(Page, "body", format="plain")
|
407
323
|
|
408
|
-
# class Translation(dd.Model):
|
409
|
-
# class Meta:
|
410
|
-
# verbose_name = _("Page translation")
|
411
|
-
# verbose_name_plural = _("Page translations")
|
412
|
-
#
|
413
|
-
# parent = dd.ForeignKey(
|
414
|
-
# 'publisher.Page',
|
415
|
-
# verbose_name=_("Translated from..."),
|
416
|
-
# related_name='translated_from')
|
417
|
-
# child = dd.ForeignKey(
|
418
|
-
# 'publisher.Page',
|
419
|
-
# blank=True, null=True,
|
420
|
-
# verbose_name=_("Translated to..."),
|
421
|
-
# related_name='translated_to')
|
422
|
-
# language = dd.LanguageField()
|
423
|
-
|
424
324
|
|
425
325
|
@schedule_daily()
|
426
326
|
def update_publisher_pages(ar):
|
427
327
|
# BaseRequest(parent=ar).run(settings.SITE.site_config.check_all_summaries)
|
428
328
|
# rt.login().run(settings.SITE.site_config.check_all_summaries)
|
429
|
-
Page =
|
329
|
+
Page = rt.models.publisher.Page
|
430
330
|
# for pv in PublisherViews.get_list_items():
|
431
331
|
# for m in rt.models_by_base(Published, toplevel_only=True):
|
432
|
-
prev = None
|
433
332
|
count = 0
|
434
333
|
ar.logger.info("Update publisher pages...")
|
435
334
|
|
436
|
-
for
|
437
|
-
|
438
|
-
|
439
|
-
|
335
|
+
for root in Page.objects.filter(parent__isnull=True):
|
336
|
+
prev = None
|
337
|
+
for obj in root.walk():
|
338
|
+
obj.update_page(prev, root.publisher_tree)
|
339
|
+
prev = obj
|
340
|
+
count += 1
|
440
341
|
ar.logger.info("%d pages have been updated.", count)
|
441
342
|
|
442
343
|
|
443
|
-
def make_demo_pages(pages_desc):
|
344
|
+
def make_demo_pages(pages_desc, root_ref, group=None):
|
345
|
+
Tree = rt.models.publisher.Tree
|
346
|
+
tree = get_or_create(Tree, ref=root_ref, group=group)
|
444
347
|
# Translation = rt.models.pages.Translation
|
445
348
|
# for lc in settings.SITE.LANGUAGE_CHOICES:
|
446
349
|
# language = lc[0]
|
@@ -451,31 +354,32 @@ def make_demo_pages(pages_desc):
|
|
451
354
|
for lng in settings.SITE.languages:
|
452
355
|
counter = {None: 0}
|
453
356
|
# count = 0
|
454
|
-
home_page = Page.objects.get(
|
455
|
-
|
357
|
+
# home_page = Page.objects.get(
|
358
|
+
# special_page=SpecialPages.home, language=lng.django_code)
|
456
359
|
|
457
360
|
with translation.override(lng.django_code):
|
458
361
|
|
459
|
-
def make_pages(pages, parent=None):
|
362
|
+
# def make_pages(pages, parent=None):
|
363
|
+
def make_pages(pages, parent=None, root_ref=None):
|
460
364
|
for page in pages:
|
461
365
|
if len(page) != 3:
|
462
366
|
raise Exception(f"Oops {page}")
|
463
367
|
title, body, children = page
|
464
|
-
kwargs = dict(title=title)
|
368
|
+
# kwargs = dict(title=title, group=group)
|
369
|
+
kwargs = dict(title=title, publisher_tree=tree,
|
370
|
+
language=lng.django_code)
|
465
371
|
if body is None:
|
466
372
|
kwargs.update(body=get_paragraph())
|
467
373
|
else:
|
468
374
|
kwargs.update(body=body)
|
469
|
-
if parent is None:
|
470
|
-
|
471
|
-
continue # home page is created by SpecialPages
|
375
|
+
if parent is not None:
|
376
|
+
kwargs.update(parent=parent)
|
472
377
|
if lng.suffix:
|
473
378
|
kwargs.update(
|
474
379
|
translated_from=parent_nodes[counter[None]])
|
475
|
-
kwargs.update(language=lng.django_code)
|
476
380
|
if dd.is_installed("publisher"):
|
477
381
|
kwargs.update(publishing_state='published')
|
478
|
-
obj = Page(
|
382
|
+
obj = Page(**kwargs)
|
479
383
|
yield obj
|
480
384
|
if not lng.suffix:
|
481
385
|
parent_nodes.append(obj)
|
@@ -483,4 +387,5 @@ def make_demo_pages(pages_desc):
|
|
483
387
|
# print("20230324", title, kwargs)
|
484
388
|
yield make_pages(children, obj)
|
485
389
|
|
486
|
-
yield make_pages(pages_desc, parent=home_page)
|
390
|
+
# yield make_pages(pages_desc, parent=home_page)
|
391
|
+
yield make_pages(pages_desc, None, root_ref)
|
@@ -1,31 +1,43 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2023 Rumma & Ko Ltd
|
2
|
+
# Copyright 2023-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
-
from lino import logger
|
6
5
|
from lino.core.renderer import add_user_language
|
7
|
-
from lino.
|
6
|
+
from lino.core.renderer import HtmlRenderer
|
8
7
|
|
8
|
+
from lino.modlib.publisher.mixins import Publishable
|
9
|
+
|
10
|
+
|
11
|
+
class Renderer(HtmlRenderer):
|
12
|
+
|
13
|
+
tableattrs = {"class": "table table-hover table-striped table-condensed"}
|
14
|
+
cellattrs = dict(align="left", valign="top")
|
15
|
+
|
16
|
+
can_auth = False
|
9
17
|
|
10
|
-
class Renderer(Renderer):
|
11
18
|
def __init__(self, front_end):
|
12
19
|
super().__init__(front_end)
|
13
20
|
dr = front_end.site.kernel.default_renderer
|
14
21
|
for k in ("row_action_button", "get_detail_url"):
|
15
22
|
setattr(self, k, getattr(dr, k))
|
16
23
|
|
17
|
-
def get_request_url(self, ar, *args, **kwargs):
|
18
|
-
obj = ar.selected_rows[0]
|
19
|
-
return self.obj2url(ar, obj, **kwargs)
|
20
|
-
# return obj.publisher_url(ar, **kwargs)
|
21
|
-
|
22
24
|
def obj2url(self, ar, obj, **kwargs):
|
25
|
+
if not isinstance(obj, Publishable):
|
26
|
+
return super().obj2url(ar, obj, **kwargs)
|
23
27
|
# if ar.actor is None or not isinstance(obj, ar.actor.model):
|
28
|
+
add_user_language(kwargs, ar)
|
29
|
+
# if isinstance(obj, self.front_end.site.models.publisher.Page) and obj.ref == 'index':
|
30
|
+
if isinstance(obj, self.front_end.site.models.publisher.Page) and obj.parent is None:
|
31
|
+
if obj.publisher_tree.ref is not None:
|
32
|
+
if obj.publisher_tree.ref == 'index':
|
33
|
+
return self.front_end.buildurl(**kwargs)
|
34
|
+
return self.front_end.buildurl(obj.publisher_tree.ref, **kwargs)
|
35
|
+
# if obj.ref:
|
36
|
+
# return self.front_end.buildurl(obj.ref, **kwargs)
|
24
37
|
loc = obj.__class__._lino_publisher_location
|
25
38
|
if loc is None:
|
26
39
|
# logger.warning("No location for %s", obj.__class__)
|
27
40
|
return None
|
28
|
-
add_user_language(kwargs, ar)
|
29
41
|
return self.front_end.buildurl(loc, str(obj.pk), **kwargs)
|
30
42
|
# for i in PublisherViews.get_list_items():
|
31
43
|
# if isinstance(obj, i.table_class.model):
|
@@ -39,4 +51,12 @@ class Renderer(Renderer):
|
|
39
51
|
# publisher view,
|
40
52
|
return None
|
41
53
|
return self.front_end.site.kernel.default_renderer.obj2url(ar, obj, **kwargs)
|
42
|
-
|
54
|
+
|
55
|
+
def get_home_url(self, ar, *args, **kw):
|
56
|
+
add_user_language(kw, ar)
|
57
|
+
return self.front_end.build_plain_url(*args, **kw)
|
58
|
+
|
59
|
+
def get_request_url(self, ar, *args, **kwargs):
|
60
|
+
obj = ar.selected_rows[0]
|
61
|
+
return self.obj2url(ar, obj, **kwargs)
|
62
|
+
# return obj.publisher_url(ar, **kwargs)
|