lino 25.8.2__py3-none-any.whl → 25.8.3__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/config/unused/403.html +1 -1
- lino/config/unused/404.html +1 -1
- lino/config/unused/500.html +1 -1
- lino/core/actions.py +1 -1
- lino/core/actors.py +2 -2
- lino/core/elems.py +1 -1
- lino/core/kernel.py +5 -1
- lino/core/renderer.py +2 -2
- lino/core/requests.py +4 -5
- lino/core/site.py +5 -3
- lino/core/store.py +3 -1
- lino/core/urls.py +1 -1
- lino/help_texts.py +9 -5
- lino/modlib/__init__.py +1 -1
- lino/modlib/bootstrap5/README.txt +2 -0
- lino/modlib/{bootstrap3 → bootstrap5}/__init__.py +6 -6
- lino/modlib/{bootstrap3/config/bootstrap3 → bootstrap5/config/bootstrap5}/base.html +5 -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/{bootstrap3 → bootstrap5}/models.py +2 -2
- 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 +10 -10
- lino/modlib/comments/mixins.py +1 -8
- lino/modlib/comments/models.py +2 -0
- lino/modlib/extjs/__init__.py +1 -1
- lino/modlib/jinja/renderer.py +1 -1
- lino/modlib/memo/__init__.py +1 -2
- lino/modlib/odata/views.py +7 -7
- lino/modlib/publisher/__init__.py +9 -2
- lino/modlib/publisher/choicelists.py +12 -43
- lino/modlib/publisher/config/publisher/page.pub.html +10 -13
- lino/modlib/publisher/fixtures/synodalworld.py +3 -1
- lino/modlib/publisher/mixins.py +28 -75
- lino/modlib/publisher/models.py +49 -143
- lino/modlib/publisher/renderer.py +6 -2
- lino/modlib/publisher/ui.py +23 -75
- lino/modlib/publisher/views.py +30 -15
- lino/modlib/users/fixtures/abc.py +20 -0
- lino/modlib/users/mixins.py +6 -6
- lino/modlib/weasyprint/__init__.py +25 -14
- lino/modlib/weasyprint/config/weasyprint/base.weasy.html +43 -27
- {lino-25.8.2.dist-info → lino-25.8.3.dist-info}/METADATA +1 -1
- {lino-25.8.2.dist-info → lino-25.8.3.dist-info}/RECORD +102 -62
- lino/modlib/bootstrap3/README.txt +0 -2
- 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.8.3.dist-info}/WHEEL +0 -0
- {lino-25.8.2.dist-info → lino-25.8.3.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.8.2.dist-info → lino-25.8.3.dist-info}/licenses/COPYING +0 -0
lino/modlib/publisher/models.py
CHANGED
@@ -1,58 +1,35 @@
|
|
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
8
|
from django.http import HttpResponseRedirect
|
8
9
|
from django.conf import settings
|
9
10
|
from django.utils import translation
|
10
|
-
from django.utils.translation import pgettext_lazy
|
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
11
|
# from django.utils.translation import get_language
|
21
|
-
from django.utils.html import mark_safe
|
22
|
-
|
23
12
|
from lino.api import dd, rt, _
|
24
|
-
from lino.utils import mti
|
13
|
+
# from lino.utils import mti
|
25
14
|
from lino.utils.html import E, tostring
|
26
|
-
from lino.core import constants
|
27
15
|
# from lino.core.renderer import add_user_language
|
28
|
-
|
29
|
-
from lino.
|
30
|
-
from lino import mixins
|
31
|
-
from lino.mixins import Hierarchical, Sequenced, Referrable
|
32
|
-
|
16
|
+
# from lino.utils.mldbc.fields import LanguageField
|
17
|
+
from lino.mixins import Hierarchical, Sequenced
|
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
23
|
from lino_xl.lib.topics.mixins import Taggable
|
41
|
-
from lino.modlib.users.mixins import PrivacyRelevant
|
42
|
-
# from .utils import render_node
|
43
24
|
|
44
|
-
from lino.api import rt, dd
|
45
25
|
from .choicelists import PublishingStates, PageFillers, SpecialPages
|
46
26
|
from .mixins import Publishable
|
47
27
|
from .ui import *
|
48
28
|
|
49
|
-
# class Node(Referrable, Hierarchical, Sequenced, Previewable, Publishable, Commentable):
|
50
|
-
# Polymorphic,
|
51
|
-
|
52
29
|
|
53
30
|
class Page(
|
54
31
|
Hierarchical, Sequenced, Previewable, Commentable, PublishableContent,
|
55
|
-
Taggable
|
32
|
+
Taggable
|
56
33
|
):
|
57
34
|
class Meta:
|
58
35
|
verbose_name = _("Page")
|
@@ -65,6 +42,7 @@ class Page(
|
|
65
42
|
unique_together = ["ref", "language"]
|
66
43
|
|
67
44
|
memo_command = "page"
|
45
|
+
allow_cascaded_delete = ['parent']
|
68
46
|
|
69
47
|
ref = dd.CharField(_("Reference"), max_length=200, blank=True, null=True)
|
70
48
|
title = dd.CharField(_("Title"), max_length=250, blank=True)
|
@@ -81,8 +59,8 @@ class Page(
|
|
81
59
|
)
|
82
60
|
|
83
61
|
previous_page = dd.ForeignKey(
|
84
|
-
"self", null=True, blank=True,
|
85
|
-
|
62
|
+
"self", null=True, blank=True, editable=False,
|
63
|
+
verbose_name=_("Previous page"), related_name='+')
|
86
64
|
|
87
65
|
def __str__(self):
|
88
66
|
return self.title or self.ref or super().__str__()
|
@@ -102,6 +80,9 @@ class Page(
|
|
102
80
|
def get_node_info(self, ar):
|
103
81
|
return ""
|
104
82
|
|
83
|
+
def is_public(self):
|
84
|
+
return not self.private
|
85
|
+
|
105
86
|
# def full_clean(self):
|
106
87
|
# self.page_type = self.mti_child().get_page_type()
|
107
88
|
# super().full_clean()
|
@@ -111,6 +92,12 @@ class Page(
|
|
111
92
|
# return mti.get_child(self, self.page_type.nodes_table.model) or self
|
112
93
|
return self
|
113
94
|
|
95
|
+
def walk(self):
|
96
|
+
yield self
|
97
|
+
for c in self.children.all():
|
98
|
+
for i in c.walk():
|
99
|
+
yield i
|
100
|
+
|
114
101
|
# def as_summary_row(self, ar, **kwargs):
|
115
102
|
# return ar.obj2htmls(self, **kwargs)
|
116
103
|
|
@@ -246,77 +233,20 @@ class Page(
|
|
246
233
|
return
|
247
234
|
return "".join(ar.row_as_page(self))
|
248
235
|
|
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):
|
236
|
+
def full_clean(self):
|
237
|
+
if self.root_page is None and self.parent is not None:
|
238
|
+
self.root_page = self.parent.root_page
|
239
|
+
super().full_clean()
|
240
|
+
|
241
|
+
def update_page(self, prev, root):
|
242
|
+
save = False
|
318
243
|
if self.previous_page != prev:
|
319
244
|
self.previous_page = prev
|
245
|
+
save = True
|
246
|
+
if self.root_page != root:
|
247
|
+
self.root_page = root
|
248
|
+
save = True
|
249
|
+
if save:
|
320
250
|
self.save()
|
321
251
|
|
322
252
|
def get_prev_link(self, ar, text="◄"): # "◄" 0x25c4
|
@@ -339,18 +269,6 @@ class Page(
|
|
339
269
|
# url = ar.obj2url(next_node.mti_child())
|
340
270
|
# return """<a href="{}">{}</a>""".format(url, text)
|
341
271
|
|
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
272
|
@classmethod
|
355
273
|
def get_dashboard_objects(cls, user):
|
356
274
|
# print("20210114 get_dashboard_objects()", get_language())
|
@@ -405,42 +323,27 @@ class Page(
|
|
405
323
|
if dd.plugins.memo.use_markup:
|
406
324
|
dd.update_field(Page, "body", format="plain")
|
407
325
|
|
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
326
|
|
425
327
|
@schedule_daily()
|
426
328
|
def update_publisher_pages(ar):
|
427
329
|
# BaseRequest(parent=ar).run(settings.SITE.site_config.check_all_summaries)
|
428
330
|
# rt.login().run(settings.SITE.site_config.check_all_summaries)
|
429
|
-
Page =
|
331
|
+
Page = rt.models.publisher.Page
|
430
332
|
# for pv in PublisherViews.get_list_items():
|
431
333
|
# for m in rt.models_by_base(Published, toplevel_only=True):
|
432
|
-
prev = None
|
433
334
|
count = 0
|
434
335
|
ar.logger.info("Update publisher pages...")
|
435
336
|
|
436
|
-
for
|
437
|
-
|
438
|
-
|
439
|
-
|
337
|
+
for root in Page.objects.filter(parent__isnull=True):
|
338
|
+
prev = None
|
339
|
+
for obj in root.walk():
|
340
|
+
obj.update_page(prev, root)
|
341
|
+
prev = obj
|
342
|
+
count += 1
|
440
343
|
ar.logger.info("%d pages have been updated.", count)
|
441
344
|
|
442
345
|
|
443
|
-
def make_demo_pages(pages_desc):
|
346
|
+
def make_demo_pages(pages_desc, root_ref, group=None):
|
444
347
|
# Translation = rt.models.pages.Translation
|
445
348
|
# for lc in settings.SITE.LANGUAGE_CHOICES:
|
446
349
|
# language = lc[0]
|
@@ -451,31 +354,33 @@ 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)
|
465
369
|
if body is None:
|
466
370
|
kwargs.update(body=get_paragraph())
|
467
371
|
else:
|
468
372
|
kwargs.update(body=body)
|
469
373
|
if parent is None:
|
470
|
-
|
471
|
-
|
374
|
+
kwargs.update(ref=root_ref)
|
375
|
+
else:
|
376
|
+
kwargs.update(parent=parent)
|
472
377
|
if lng.suffix:
|
473
378
|
kwargs.update(
|
474
379
|
translated_from=parent_nodes[counter[None]])
|
475
380
|
kwargs.update(language=lng.django_code)
|
476
381
|
if dd.is_installed("publisher"):
|
477
382
|
kwargs.update(publishing_state='published')
|
478
|
-
obj = Page(
|
383
|
+
obj = Page(**kwargs)
|
479
384
|
yield obj
|
480
385
|
if not lng.suffix:
|
481
386
|
parent_nodes.append(obj)
|
@@ -483,4 +388,5 @@ def make_demo_pages(pages_desc):
|
|
483
388
|
# print("20230324", title, kwargs)
|
484
389
|
yield make_pages(children, obj)
|
485
390
|
|
486
|
-
yield make_pages(pages_desc, parent=home_page)
|
391
|
+
# yield make_pages(pages_desc, parent=home_page)
|
392
|
+
yield make_pages(pages_desc, None, root_ref)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
from lino import logger
|
6
6
|
from lino.core.renderer import add_user_language
|
7
|
-
from lino.modlib.
|
7
|
+
from lino.modlib.bootstrap5.renderer import Renderer
|
8
8
|
|
9
9
|
|
10
10
|
class Renderer(Renderer):
|
@@ -21,11 +21,15 @@ class Renderer(Renderer):
|
|
21
21
|
|
22
22
|
def obj2url(self, ar, obj, **kwargs):
|
23
23
|
# if ar.actor is None or not isinstance(obj, ar.actor.model):
|
24
|
+
add_user_language(kwargs, ar)
|
25
|
+
if isinstance(obj, self.front_end.site.models.publisher.Page) and obj.ref == 'index':
|
26
|
+
return self.front_end.buildurl(**kwargs)
|
27
|
+
# if obj.ref:
|
28
|
+
# return self.front_end.buildurl(obj.ref, **kwargs)
|
24
29
|
loc = obj.__class__._lino_publisher_location
|
25
30
|
if loc is None:
|
26
31
|
# logger.warning("No location for %s", obj.__class__)
|
27
32
|
return None
|
28
|
-
add_user_language(kwargs, ar)
|
29
33
|
return self.front_end.buildurl(loc, str(obj.pk), **kwargs)
|
30
34
|
# for i in PublisherViews.get_list_items():
|
31
35
|
# if isinstance(obj, i.table_class.model):
|
lino/modlib/publisher/ui.py
CHANGED
@@ -1,86 +1,19 @@
|
|
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
|
-
from html import escape
|
6
5
|
from django.db import models
|
7
|
-
from django.http import HttpResponseRedirect
|
8
|
-
from django.conf import settings
|
9
|
-
from django.utils import translation
|
10
|
-
from django.utils.translation import pgettext_lazy
|
11
6
|
|
12
7
|
# from django.utils.translation import get_language
|
13
|
-
from django.utils.html import
|
14
|
-
from django.utils.html import format_html
|
8
|
+
# from django.utils.html import format_html
|
15
9
|
|
16
10
|
from lino.api import dd, rt, _
|
17
11
|
from lino.utils.html import E
|
18
12
|
from lino.core import constants
|
19
13
|
# from lino.core.renderer import add_user_language
|
20
|
-
|
21
|
-
from lino.utils.mldbc.fields import LanguageField
|
22
|
-
from lino import mixins
|
23
|
-
from lino.mixins import Hierarchical, Sequenced, Referrable
|
24
14
|
from lino.modlib.office.roles import OfficeUser
|
25
|
-
|
26
|
-
|
27
|
-
# from lino.modlib.publisher.choicelists import PublisherViews
|
28
|
-
from lino.modlib.memo.mixins import Previewable
|
29
|
-
# from .utils import render_node
|
30
|
-
|
31
|
-
# class NodeDetail(dd.DetailLayout):
|
32
|
-
# main = "first_panel general more"
|
33
|
-
#
|
34
|
-
# first_panel = dd.Panel("""
|
35
|
-
# treeview_panel:20 preview:60
|
36
|
-
# """, label=_("Preview"))
|
37
|
-
#
|
38
|
-
# general = dd.Panel("""
|
39
|
-
# content_panel:60 right_panel:20
|
40
|
-
# """, label=_("General"), required_roles=dd.login_required(OfficeUser))
|
41
|
-
#
|
42
|
-
# more = dd.Panel("""
|
43
|
-
# # topics.TagsByOwner:20 add_interest
|
44
|
-
# comments.CommentsByRFC:20
|
45
|
-
# """, label=_("More"), required_roles=dd.login_required(OfficeUser))
|
46
|
-
#
|
47
|
-
# content_panel = """
|
48
|
-
# title id
|
49
|
-
# body
|
50
|
-
# publisher.PagesByParent
|
51
|
-
# """
|
52
|
-
#
|
53
|
-
# right_panel = """
|
54
|
-
# parent seqno
|
55
|
-
# child_node_depth
|
56
|
-
# page_type
|
57
|
-
# filler
|
58
|
-
# """
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# class Nodes(dd.Table):
|
62
|
-
# model = 'pages.Node'
|
63
|
-
# column_names = "title page_type id *"
|
64
|
-
# order_by = ["id"]
|
65
|
-
# detail_layout = 'pages.NodeDetail'
|
66
|
-
# insert_layout = """
|
67
|
-
# title
|
68
|
-
# page_type filler
|
69
|
-
# """
|
70
|
-
# display_mode = ((None, constants.DISPLAY_MODE_STORY),)
|
71
|
-
#
|
72
|
-
#
|
73
|
-
|
74
|
-
# class Translations(dd.Table):
|
75
|
-
# model = 'pages.Translation'
|
76
|
-
#
|
77
|
-
# class TranslationsByParent(Translations):
|
78
|
-
# master_key = 'parent'
|
79
|
-
# label = _("Translated to...")
|
80
|
-
#
|
81
|
-
# class TranslationsByChild(Translations):
|
82
|
-
# master_key = 'child'
|
83
|
-
# label = _("Translated from...")
|
15
|
+
|
16
|
+
from .choicelists import PageFillers, SpecialPages
|
84
17
|
|
85
18
|
|
86
19
|
if dd.is_installed("comments") and dd.is_installed("topics"):
|
@@ -129,11 +62,11 @@ class PageDetail(dd.DetailLayout):
|
|
129
62
|
# """
|
130
63
|
|
131
64
|
right_panel = """
|
132
|
-
|
133
|
-
parent seqno
|
65
|
+
group language ref
|
66
|
+
parent seqno root_page
|
134
67
|
child_node_depth main_image
|
135
|
-
|
136
|
-
publishing_state
|
68
|
+
special_page filler
|
69
|
+
publishing_state private
|
137
70
|
publisher.TranslationsByPage
|
138
71
|
"""
|
139
72
|
|
@@ -175,3 +108,18 @@ class TranslationsByPage(Pages):
|
|
175
108
|
def row_as_summary(cls, ar, obj, text=None, **kwargs):
|
176
109
|
# return format_html("({}) {}", obj.language, obj.as_summary_row(ar, **kwargs))
|
177
110
|
return E.span("({}) ".format(obj.language), obj.as_summary_item(ar, text, **kwargs))
|
111
|
+
|
112
|
+
|
113
|
+
class RootPages(Pages):
|
114
|
+
label = _("Root pages")
|
115
|
+
filter = models.Q(parent__isnull=True, special_page='')
|
116
|
+
column_names = "ref title language"
|
117
|
+
# default_display_modes = {None: constants.DISPLAY_MODE_LIST}
|
118
|
+
|
119
|
+
|
120
|
+
filler = PageFillers.add_item(RootPages)
|
121
|
+
|
122
|
+
SpecialPages.add_item(
|
123
|
+
"pages", filler=filler, body=_("List of root pages."),
|
124
|
+
title=_("Root pages"),
|
125
|
+
parent='home')
|
lino/modlib/publisher/views.py
CHANGED
@@ -7,6 +7,7 @@ from django.conf import settings
|
|
7
7
|
from django.core.exceptions import ObjectDoesNotExist
|
8
8
|
from django.utils import translation
|
9
9
|
from django.views.generic import View
|
10
|
+
from lino.core.requests import BaseRequest
|
10
11
|
|
11
12
|
|
12
13
|
class Element(View):
|
@@ -23,36 +24,50 @@ class Element(View):
|
|
23
24
|
|
24
25
|
# kw = dict(actor=self.publisher_model.get_default_table(),
|
25
26
|
# request=request, renderer=rnd, permalink_uris=True)
|
26
|
-
kw = dict(renderer=rnd)
|
27
|
+
# kw = dict(renderer=rnd)
|
27
28
|
# kw = dict(renderer=rnd, permalink_uris=True)
|
28
29
|
# if rnd.front_end.media_name == 'react':
|
29
30
|
# kw.update(hash_router=True)
|
30
31
|
|
31
|
-
kw.update(selected_pks=[pk])
|
32
|
+
# kw.update(selected_pks=[pk])
|
33
|
+
#
|
34
|
+
# try:
|
35
|
+
# ar = self.table_class.create_request(request=request, **kw)
|
36
|
+
# except ObjectDoesNotExist as e:
|
37
|
+
# # print("20240911", e)
|
38
|
+
# return http.HttpResponseNotFound(f"No row #{pk} in {self.table_class} ({e})")
|
39
|
+
# if len(ar.selected_rows) == 0:
|
40
|
+
# # print(f"20241003 Oops {ar} has no rows")
|
41
|
+
# return http.HttpResponseNotFound(f"20241003 No row #{pk} in {self.table_class}")
|
42
|
+
# obj = ar.selected_rows[0]
|
32
43
|
|
44
|
+
m = self.table_class.model
|
33
45
|
try:
|
34
|
-
|
35
|
-
except
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# print(f"20241003 Oops {ar} has no rows")
|
40
|
-
return http.HttpResponseNotFound(f"20241003 No row #{pk} in {self.table_class}")
|
41
|
-
obj = ar.selected_rows[0]
|
46
|
+
obj = m.objects.get(pk=pk)
|
47
|
+
except m.DoesNotExist as e:
|
48
|
+
return http.HttpResponseNotFound(f"No row #{pk} in {m} ({e})")
|
49
|
+
ar = BaseRequest(renderer=rnd, request=request, selected_rows=[obj])
|
50
|
+
# ar = BaseRequest(renderer=rnd, request=request)
|
42
51
|
return obj.get_publisher_response(ar)
|
43
52
|
|
44
53
|
|
45
54
|
class Index(View):
|
46
|
-
def get(self, request,
|
47
|
-
rnd = settings.SITE.plugins.publisher.renderer
|
55
|
+
def get(self, request, ref=''):
|
48
56
|
dv = settings.SITE.models.publisher.Pages
|
49
57
|
if len(settings.SITE.languages) == 1:
|
50
58
|
# language = settings.SITE.languages[0].django_code
|
51
59
|
language = translation.get_language()
|
52
60
|
else:
|
53
61
|
language = request.LANGUAGE_CODE
|
54
|
-
|
62
|
+
if ref == '':
|
63
|
+
ref = 'index'
|
64
|
+
try:
|
65
|
+
obj = dv.model.objects.get(ref=ref, language=language)
|
66
|
+
except dv.model.DoesNotExist:
|
67
|
+
return http.HttpResponseNotFound(f"No row {ref} in {dv.model}")
|
68
|
+
|
55
69
|
# print("20231025", index_node)
|
70
|
+
rnd = settings.SITE.plugins.publisher.renderer
|
56
71
|
ar = dv.create_request(request=request, renderer=rnd,
|
57
|
-
selected_rows=[
|
58
|
-
return
|
72
|
+
selected_rows=[obj])
|
73
|
+
return obj.get_publisher_response(ar)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
# Copyright 2017-2025 Rumma & Ko Ltd
|
3
|
+
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
|
+
|
5
|
+
from lino.api import dd, rt, _
|
6
|
+
|
7
|
+
|
8
|
+
def objects():
|
9
|
+
User = rt.models.users.User
|
10
|
+
UserTypes = rt.models.users.UserTypes
|
11
|
+
|
12
|
+
def user(username, **kwargs):
|
13
|
+
kwargs.update(user_type=UserTypes.user, username=username)
|
14
|
+
if not dd.plugins.users.with_nickname:
|
15
|
+
kwargs.pop('nickname', None)
|
16
|
+
return User(**kwargs)
|
17
|
+
|
18
|
+
yield user("andy", first_name="Andreas", last_name="Anderson", nickname="Andy", email="andy@example.com")
|
19
|
+
yield user("bert", first_name="Albert", last_name="Bernstein", nickname="Bert", email="bert@example.com")
|
20
|
+
yield user("chloe", first_name="Chloe", last_name="Cleoment", email="chloe@example.com")
|
lino/modlib/users/mixins.py
CHANGED
@@ -490,18 +490,16 @@ class PrivacyRelevant(dd.Model):
|
|
490
490
|
qs = super().get_request_queryset(ar, **filter)
|
491
491
|
user = ar.get_user()
|
492
492
|
if user.is_anonymous:
|
493
|
-
if dd.is_installed('groups'):
|
494
|
-
|
493
|
+
# if dd.is_installed('groups'):
|
494
|
+
# qs = qs.filter(group__private=False)
|
495
495
|
return qs.filter(private=False)
|
496
|
-
# if user.current_group is not None:
|
497
|
-
# qs = qs.filter(group=user.current_group)
|
498
496
|
if user.user_type.has_required_roles([SiteAdmin]):
|
499
497
|
return qs
|
500
498
|
flt = Q(private=False)
|
501
499
|
if issubclass(cls, UserAuthored):
|
502
500
|
flt |= Q(user=user)
|
503
501
|
if dd.is_installed('groups'):
|
504
|
-
flt |= Q(group__private=False)
|
502
|
+
# flt |= Q(group__private=False)
|
505
503
|
flt |= Q(group__members__user=user)
|
506
504
|
qs = qs.filter(flt).distinct()
|
507
505
|
return qs
|
@@ -518,9 +516,11 @@ class PrivacyRelevant(dd.Model):
|
|
518
516
|
self.private = self.group.private
|
519
517
|
|
520
518
|
def get_default_group(self):
|
521
|
-
return None
|
519
|
+
return None # dd.plugins.groups.get_default_group()
|
522
520
|
|
523
521
|
def full_clean(self):
|
524
522
|
if not self.group_id:
|
525
523
|
self.group = self.get_default_group()
|
524
|
+
if self.group and self.group.private:
|
525
|
+
self.private = True
|
526
526
|
super().full_clean()
|
@@ -34,6 +34,8 @@ class Plugin(ad.Plugin):
|
|
34
34
|
top_right_width = None
|
35
35
|
page_background_image = None
|
36
36
|
top_right_image = None
|
37
|
+
bottom_left_image = None
|
38
|
+
bottom_left_width = None
|
37
39
|
header_image = None
|
38
40
|
margin = 10
|
39
41
|
margin_left = 17
|
@@ -53,25 +55,34 @@ class Plugin(ad.Plugin):
|
|
53
55
|
yield 'django-bulma'
|
54
56
|
|
55
57
|
def pre_site_startup(self, site):
|
58
|
+
fcf = site.confdirs.find_config_file
|
56
59
|
for ext in ("jpg", "png"):
|
57
|
-
if self.
|
58
|
-
fn
|
59
|
-
|
60
|
+
if self.bottom_left_image is None:
|
61
|
+
if fn := fcf("bottom-left." + ext, "weasyprint"):
|
62
|
+
self.bottom_left_image = fn
|
63
|
+
if self.top_right_image is None:
|
64
|
+
if fn := fcf("top-right." + ext, "weasyprint"):
|
60
65
|
self.top_right_image = fn
|
61
|
-
|
62
|
-
|
63
|
-
site.logger.warning("imagesize is not installed")
|
64
|
-
continue
|
65
|
-
w, h = imagesize.get(fn)
|
66
|
-
self.top_right_width = self.header_height * w / h
|
67
|
-
fn = site.confdirs.find_config_file("header." + ext, "weasyprint")
|
68
|
-
if fn:
|
66
|
+
if self.header_image is None:
|
67
|
+
if fn := fcf("header." + ext, "weasyprint"):
|
69
68
|
# site.logger.info("Found header_image %s", fn)
|
70
69
|
self.header_image = fn
|
71
70
|
if self.page_background_image is None:
|
72
|
-
fn
|
73
|
-
"page-background." + ext, "weasyprint")
|
74
|
-
if fn:
|
71
|
+
if fn := fcf("page-background." + ext, "weasyprint"):
|
75
72
|
# site.logger.info("Found page_background_image %s", fn)
|
76
73
|
self.page_background_image = fn
|
74
|
+
if self.header_height:
|
75
|
+
if self.top_right_image and not self.top_right_width:
|
76
|
+
# if imagesize is None:
|
77
|
+
# site.logger.warning("imagesize is not installed")
|
78
|
+
# continue
|
79
|
+
w, h = imagesize.get(self.top_right_image)
|
80
|
+
self.top_right_width = self.header_height * w / h
|
81
|
+
if self.footer_height:
|
82
|
+
if self.bottom_left_image and not self.bottom_left_width:
|
83
|
+
# if imagesize is None:
|
84
|
+
# site.logger.warning("imagesize is not installed")
|
85
|
+
# continue
|
86
|
+
w, h = imagesize.get(self.bottom_left_image)
|
87
|
+
self.bottom_left_width = self.footer_height * w / h
|
77
88
|
super().pre_site_startup(site)
|