wagtail-cjkcms 24.2.7__py2.py3-none-any.whl → 25.1.6__py2.py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- cjkcms/.DS_Store +0 -0
- cjkcms/__init__.py +1 -1
- cjkcms/blocks/__init__.py +4 -0
- cjkcms/blocks/content/countdown.py +116 -0
- cjkcms/blocks/content_blocks.py +46 -9
- cjkcms/migrations/0018_layoutsettings_search_format.py +10 -5
- cjkcms/migrations/0019_layoutsettings_searchbox_input_class_and_more.py +28 -11
- cjkcms/migrations/0020_socialmediasettings_github_and_more.py +35 -0
- cjkcms/migrations/0021_remove_layoutsettings_navbar_color_scheme_and_more.py +85 -0
- cjkcms/migrations/0022_cjkcmspage_breadcrumb_label_and_more.py +23 -0
- cjkcms/migrations/0023_alter_navbar_language.py +18 -0
- cjkcms/models/admin_sidebar.py +0 -28
- cjkcms/models/page_models.py +33 -0
- cjkcms/models/snippet_models.py +22 -7
- cjkcms/models/wagtailsettings_models.py +61 -22
- cjkcms/settings.py +96 -64
- cjkcms/static/.DS_Store +0 -0
- cjkcms/static/cjkcms/css/cjkcms-custom-theme-disabled.css +73 -0
- cjkcms/static/cjkcms/css/cjkcms-front.css +41 -5
- cjkcms/static/cjkcms/js/cjkcms-front.js +2 -2
- cjkcms/static/vendor/.DS_Store +0 -0
- cjkcms/static/vendor/mdb/.DS_Store +0 -0
- cjkcms/static/vendor/mdb/css/.DS_Store +0 -0
- cjkcms/static/vendor/mdb/css/mdb.min.css +18 -0
- cjkcms/static/vendor/mdb/css/mdb.min.css.map +1 -0
- cjkcms/static/vendor/mdb/js/.DS_Store +0 -0
- cjkcms/static/vendor/mdb/js/mdb.umd.min.js +21 -0
- cjkcms/static/vendor/mdb/js/mdb.umd.min.js.map +1 -0
- cjkcms/static/vendor/simplycountdown/css/circle.css +73 -0
- cjkcms/static/vendor/simplycountdown/css/cyber.css +155 -0
- cjkcms/static/vendor/simplycountdown/css/dark.css +85 -0
- cjkcms/static/vendor/simplycountdown/css/light.css +85 -0
- cjkcms/static/vendor/simplycountdown/css/losange.css +83 -0
- cjkcms/static/vendor/simplycountdown/js/simplyCountdown.umd.js +2 -0
- cjkcms/static/vendor/simplycountdown/js/simplyCountdown.umd.js.map +1 -0
- cjkcms/templates/.DS_Store +0 -0
- cjkcms/templates/404.html +72 -104
- cjkcms/templates/cjkcms/.DS_Store +0 -0
- cjkcms/templates/cjkcms/blocks/base_link_block.html +48 -51
- cjkcms/templates/cjkcms/blocks/button_block.html +2 -2
- cjkcms/templates/cjkcms/blocks/card_landing1.html +2 -2
- cjkcms/templates/cjkcms/blocks/card_landing2.html +3 -3
- cjkcms/templates/cjkcms/blocks/countdown.html +24 -0
- cjkcms/templates/cjkcms/blocks/highlight_block.html +21 -0
- cjkcms/templates/cjkcms/blocks/pricelistitem_block.html +9 -5
- cjkcms/templates/cjkcms/pages/base.html +3 -3
- cjkcms/templates/cjkcms/pages/page.mini.html +1 -1
- cjkcms/templates/cjkcms/pages/search.html +10 -1
- cjkcms/templates/cjkcms/robots.txt +0 -4
- cjkcms/templates/cjkcms/snippets/breadcrumbs.html +2 -2
- cjkcms/templates/cjkcms/snippets/frontend_assets.html +9 -1
- cjkcms/templates/cjkcms/snippets/navbar.html +12 -9
- cjkcms/templates/cjkcms/snippets/navbar_search.html +6 -35
- cjkcms/templates/cjkcms/snippets/navbar_search_modal.html +34 -0
- cjkcms/templates/cjkcms/snippets/social_media_icons.html +20 -6
- cjkcms/templatetags/cjkcms_tags.py +80 -17
- cjkcms/tests/media/images/test_O3GLriA.original.png +0 -0
- cjkcms/tests/media/original_images/test_O3GLriA.png +0 -0
- cjkcms/tests/test_countdown_block.py +100 -0
- cjkcms/tests/test_search_blocks.py +10 -10
- cjkcms/tests/test_templatetags.py +19 -1
- cjkcms/tests/test_urls.py +8 -6
- cjkcms/urls.py +3 -0
- cjkcms/views.py +80 -78
- cjkcms/wagtail_hooks.py +37 -5
- {wagtail_cjkcms-24.2.7.dist-info → wagtail_cjkcms-25.1.6.dist-info}/METADATA +6 -6
- {wagtail_cjkcms-24.2.7.dist-info → wagtail_cjkcms-25.1.6.dist-info}/RECORD +71 -40
- {wagtail_cjkcms-24.2.7.dist-info → wagtail_cjkcms-25.1.6.dist-info}/WHEEL +1 -1
- {wagtail_cjkcms-24.2.7.dist-info → wagtail_cjkcms-25.1.6.dist-info}/LICENSE +0 -0
- {wagtail_cjkcms-24.2.7.dist-info → wagtail_cjkcms-25.1.6.dist-info}/entry_points.txt +0 -0
- {wagtail_cjkcms-24.2.7.dist-info → wagtail_cjkcms-25.1.6.dist-info}/top_level.txt +0 -0
cjkcms/.DS_Store
ADDED
Binary file
|
cjkcms/__init__.py
CHANGED
cjkcms/blocks/__init__.py
CHANGED
@@ -31,8 +31,10 @@ from .content_blocks import ( # noqa
|
|
31
31
|
NavPageLinkWithSubLinkBlock,
|
32
32
|
PriceListBlock,
|
33
33
|
ReusableContentBlock,
|
34
|
+
HighlightBlock,
|
34
35
|
)
|
35
36
|
from .content.events import PublicEventBlock, EventCalendarBlock
|
37
|
+
from .content.countdown import CountdownBlock
|
36
38
|
from .layout_blocks import CardGridBlock, GridBlock, HeroBlock
|
37
39
|
from cjkcms.settings import cms_settings
|
38
40
|
|
@@ -75,6 +77,8 @@ CONTENT_STREAMBLOCKS = HTML_STREAMBLOCKS + [
|
|
75
77
|
("pricelist", PriceListBlock()),
|
76
78
|
("reusable_content", ReusableContentBlock()),
|
77
79
|
("event_calendar", EventCalendarBlock()),
|
80
|
+
("highlight", HighlightBlock()),
|
81
|
+
("countdown", CountdownBlock()),
|
78
82
|
]
|
79
83
|
|
80
84
|
NAVIGATION_STREAMBLOCKS = [
|
@@ -0,0 +1,116 @@
|
|
1
|
+
from cjkcms.blocks.base_blocks import BaseBlock
|
2
|
+
from wagtail import blocks
|
3
|
+
from django.utils.translation import gettext_lazy as _
|
4
|
+
from datetime import datetime, timedelta, timezone
|
5
|
+
import re
|
6
|
+
|
7
|
+
|
8
|
+
def convert_to_utc(naive_dt, utc_offset_str):
|
9
|
+
# Parse the UTC offset string (e.g., "UTC+05:30" or "UTC-02:00")
|
10
|
+
match = re.match(r"UTC([+-])(\d{2}):(\d{2})", utc_offset_str)
|
11
|
+
if not match:
|
12
|
+
raise ValueError("Invalid UTC offset format. Use 'UTC±HH:MM'.")
|
13
|
+
|
14
|
+
sign = match.group(1)
|
15
|
+
hours = int(match.group(2))
|
16
|
+
minutes = int(match.group(3))
|
17
|
+
|
18
|
+
# Calculate the total offset in minutes
|
19
|
+
total_offset = timedelta(hours=hours, minutes=minutes)
|
20
|
+
if sign == "-":
|
21
|
+
total_offset = -total_offset
|
22
|
+
|
23
|
+
# Create a timezone with the given offset
|
24
|
+
tz = timezone(total_offset)
|
25
|
+
|
26
|
+
# Attach the offset to the naive datetime, making it timezone-aware
|
27
|
+
aware_local_dt = naive_dt.replace(tzinfo=tz)
|
28
|
+
|
29
|
+
# Convert the timezone-aware datetime to UTC
|
30
|
+
utc_dt = aware_local_dt.astimezone(timezone.utc)
|
31
|
+
|
32
|
+
return utc_dt
|
33
|
+
|
34
|
+
|
35
|
+
class CountdownBlock(BaseBlock):
|
36
|
+
"""
|
37
|
+
Display a countdown to a specific date
|
38
|
+
"""
|
39
|
+
|
40
|
+
title = blocks.CharBlock(
|
41
|
+
required=False,
|
42
|
+
max_length=255,
|
43
|
+
label=_("Title"),
|
44
|
+
)
|
45
|
+
|
46
|
+
start_date = blocks.DateTimeBlock(
|
47
|
+
required=True,
|
48
|
+
label=_("Start date and time"),
|
49
|
+
help_text=_("Format: YYYY-MM-DD HH:MM"),
|
50
|
+
)
|
51
|
+
|
52
|
+
timezone = blocks.CharBlock(
|
53
|
+
required=True,
|
54
|
+
default="UTC",
|
55
|
+
max_length=255,
|
56
|
+
label=_("Timezone"),
|
57
|
+
help_text=_("Timezone relative to UTC, e.g. UTC+01:00"),
|
58
|
+
)
|
59
|
+
|
60
|
+
url = blocks.URLBlock(
|
61
|
+
max_length=255,
|
62
|
+
label=_("Link"),
|
63
|
+
required=False,
|
64
|
+
help_text=_("Optional link"),
|
65
|
+
)
|
66
|
+
|
67
|
+
# hide_after_end_date = blocks.BooleanBlock(
|
68
|
+
# required=False,
|
69
|
+
# default=False,
|
70
|
+
# label=_("Hide after end date"),
|
71
|
+
# help_text=_("Hide this after end date, or show zeros if false"),
|
72
|
+
# )
|
73
|
+
|
74
|
+
theme = blocks.ChoiceBlock(
|
75
|
+
choices=[
|
76
|
+
("light", _("Light")),
|
77
|
+
("dark", _("Dark")),
|
78
|
+
("cyber", _("Cyberpunk")),
|
79
|
+
("losange", _("Losange")),
|
80
|
+
("circle", _("Circle")),
|
81
|
+
# ("flipbook", _("Flipbook")),
|
82
|
+
],
|
83
|
+
default="light",
|
84
|
+
label=_("Theme"),
|
85
|
+
)
|
86
|
+
|
87
|
+
def get_context(self, value, parent_context=None):
|
88
|
+
context = super().get_context(value, parent_context=parent_context)
|
89
|
+
sd = value.get("start_date")
|
90
|
+
|
91
|
+
naive_datetime = datetime(
|
92
|
+
sd.year, sd.month, sd.day, sd.hour, sd.minute
|
93
|
+
) # Naive datetime
|
94
|
+
|
95
|
+
tz = value.get("timezone")
|
96
|
+
if tz == "UTC" or tz == "":
|
97
|
+
tz = "UTC+00:00"
|
98
|
+
|
99
|
+
utc_offset_string = tz # String containing UTC offset
|
100
|
+
utc = convert_to_utc(naive_datetime, utc_offset_string)
|
101
|
+
|
102
|
+
# print(naive_datetime, utc, utc_offset_string)
|
103
|
+
context["year"] = utc.year
|
104
|
+
context["month"] = utc.month
|
105
|
+
context["day"] = utc.day
|
106
|
+
context["hour"] = utc.hour
|
107
|
+
context["minute"] = utc.minute
|
108
|
+
context["second"] = 0
|
109
|
+
return context
|
110
|
+
|
111
|
+
class Meta:
|
112
|
+
template = "cjkcms/blocks/countdown.html"
|
113
|
+
icon = "history"
|
114
|
+
label = "Countdown"
|
115
|
+
ordering = ["start_date"]
|
116
|
+
label_format = _("Countdown to {start_date}")
|
cjkcms/blocks/content_blocks.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
Content blocks are for building complex, nested HTML structures that usually
|
3
3
|
contain sub-blocks, and may require javascript to function properly.
|
4
4
|
"""
|
5
|
+
|
5
6
|
from django.utils.translation import gettext_lazy as _
|
6
7
|
from wagtail import blocks
|
7
8
|
from wagtail.documents.blocks import DocumentChooserBlock
|
@@ -180,15 +181,6 @@ class NavBaseLinkBlock(BaseBlock):
|
|
180
181
|
required=False,
|
181
182
|
label=_("Image"),
|
182
183
|
)
|
183
|
-
visible_for = blocks.ChoiceBlock(
|
184
|
-
choices=cms_settings.CJKCMS_AUTH_VISIBILITY_CHOICES,
|
185
|
-
default=cms_settings.CJKCMS_AUTH_VISIBILITY_DEFAULT,
|
186
|
-
required=False,
|
187
|
-
label=_("Item visibility"),
|
188
|
-
help_text=_(
|
189
|
-
"DEPRECATED. Use the visibility options in the `Advanced Settings`. "
|
190
|
-
),
|
191
|
-
)
|
192
184
|
|
193
185
|
|
194
186
|
class NavExternalLinkBlock(NavBaseLinkBlock):
|
@@ -359,3 +351,48 @@ class ReusableContentBlock(BaseBlock):
|
|
359
351
|
label = _("Reusable Content")
|
360
352
|
template = "cjkcms/blocks/reusable_content_block.html"
|
361
353
|
label_format = "{content} (Reusable Content)"
|
354
|
+
|
355
|
+
|
356
|
+
class HighlightBlock(BaseBlock):
|
357
|
+
"""
|
358
|
+
Block that highlights a piece of text
|
359
|
+
"""
|
360
|
+
|
361
|
+
text = blocks.RichTextBlock(
|
362
|
+
features=cms_settings.CJKCMS_RICHTEXT_FEATURES["default"],
|
363
|
+
label=_("Text"),
|
364
|
+
)
|
365
|
+
|
366
|
+
background_color = blocks.ChoiceBlock(
|
367
|
+
choices=cms_settings.CJKCMS_HIGHLIGHT_COLORS,
|
368
|
+
default=cms_settings.CJKCMS_HIGHLIGHT_DEFAULT_COLOR,
|
369
|
+
required=False,
|
370
|
+
label=_("Background Color"),
|
371
|
+
)
|
372
|
+
|
373
|
+
border_color = blocks.ChoiceBlock(
|
374
|
+
choices=cms_settings.CJKCMS_HIGHLIGHT_COLORS,
|
375
|
+
default=cms_settings.CJKCMS_HIGHLIGHT_DEFAULT_COLOR,
|
376
|
+
required=False,
|
377
|
+
label=_("Border Color"),
|
378
|
+
)
|
379
|
+
|
380
|
+
text_color = blocks.ChoiceBlock(
|
381
|
+
choices=cms_settings.CJKCMS_HIGHLIGHT_COLORS,
|
382
|
+
default="dark",
|
383
|
+
required=False,
|
384
|
+
label=_("Text Color"),
|
385
|
+
)
|
386
|
+
|
387
|
+
icon = blocks.ChoiceBlock(
|
388
|
+
choices=cms_settings.FONT_AWESOME_ICONS,
|
389
|
+
default=cms_settings.FONT_AWESOME_ICONS_DEFAULT,
|
390
|
+
required=False,
|
391
|
+
label=_("Icon"),
|
392
|
+
)
|
393
|
+
|
394
|
+
class Meta:
|
395
|
+
icon = "thumbtack"
|
396
|
+
label = _("Highlight")
|
397
|
+
label_format = _("Highlight")
|
398
|
+
template = "cjkcms/blocks/highlight_block.html"
|
@@ -4,15 +4,20 @@ from django.db import migrations, models
|
|
4
4
|
|
5
5
|
|
6
6
|
class Migration(migrations.Migration):
|
7
|
-
|
8
7
|
dependencies = [
|
9
|
-
(
|
8
|
+
("cjkcms", "0017_layoutsettings_default_seo_image"),
|
10
9
|
]
|
11
10
|
|
12
11
|
operations = [
|
13
12
|
migrations.AddField(
|
14
|
-
model_name=
|
15
|
-
name=
|
16
|
-
field=models.CharField(
|
13
|
+
model_name="layoutsettings",
|
14
|
+
name="search_format",
|
15
|
+
field=models.CharField(
|
16
|
+
blank=True,
|
17
|
+
choices=[],
|
18
|
+
default="",
|
19
|
+
max_length=50,
|
20
|
+
verbose_name="Search format",
|
21
|
+
),
|
17
22
|
),
|
18
23
|
]
|
@@ -4,25 +4,42 @@ from django.db import migrations, models
|
|
4
4
|
|
5
5
|
|
6
6
|
class Migration(migrations.Migration):
|
7
|
-
|
8
7
|
dependencies = [
|
9
|
-
(
|
8
|
+
("cjkcms", "0018_layoutsettings_search_format"),
|
10
9
|
]
|
11
10
|
|
12
11
|
operations = [
|
13
12
|
migrations.AddField(
|
14
|
-
model_name=
|
15
|
-
name=
|
16
|
-
field=models.CharField(
|
13
|
+
model_name="layoutsettings",
|
14
|
+
name="searchbox_input_class",
|
15
|
+
field=models.CharField(
|
16
|
+
blank=True,
|
17
|
+
default="border-secondary mb-0",
|
18
|
+
help_text="Classes applied to searchbox input",
|
19
|
+
max_length=255,
|
20
|
+
verbose_name="Searchbox input class",
|
21
|
+
),
|
17
22
|
),
|
18
23
|
migrations.AddField(
|
19
|
-
model_name=
|
20
|
-
name=
|
21
|
-
field=models.CharField(
|
24
|
+
model_name="layoutsettings",
|
25
|
+
name="searchbutton_class",
|
26
|
+
field=models.CharField(
|
27
|
+
blank=True,
|
28
|
+
default="btn btn-outline-secondary",
|
29
|
+
help_text="Classes applied to search button. Add e.g. `fas fa-search` for icon.",
|
30
|
+
max_length=255,
|
31
|
+
verbose_name="Search button (with text) class",
|
32
|
+
),
|
22
33
|
),
|
23
34
|
migrations.AddField(
|
24
|
-
model_name=
|
25
|
-
name=
|
26
|
-
field=models.CharField(
|
35
|
+
model_name="layoutsettings",
|
36
|
+
name="searchbutton_label",
|
37
|
+
field=models.CharField(
|
38
|
+
blank=True,
|
39
|
+
default="Search",
|
40
|
+
help_text="Leave empty when using icon-only button. Otherwise, add button label.",
|
41
|
+
max_length=255,
|
42
|
+
verbose_name="Search button label",
|
43
|
+
),
|
27
44
|
),
|
28
45
|
]
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Generated by Django 5.0.2 on 2024-03-11 19:20
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
dependencies = [
|
8
|
+
("cjkcms", "0019_layoutsettings_searchbox_input_class_and_more"),
|
9
|
+
]
|
10
|
+
|
11
|
+
operations = [
|
12
|
+
migrations.AddField(
|
13
|
+
model_name="socialmediasettings",
|
14
|
+
name="github",
|
15
|
+
field=models.URLField(
|
16
|
+
blank=True, help_text="Your GitHub page URL", verbose_name="GitHub"
|
17
|
+
),
|
18
|
+
),
|
19
|
+
migrations.AddField(
|
20
|
+
model_name="socialmediasettings",
|
21
|
+
name="pinterset",
|
22
|
+
field=models.URLField(
|
23
|
+
blank=True,
|
24
|
+
help_text="Your Pinterest page URL",
|
25
|
+
verbose_name="Pinterest",
|
26
|
+
),
|
27
|
+
),
|
28
|
+
migrations.AddField(
|
29
|
+
model_name="socialmediasettings",
|
30
|
+
name="tiktok",
|
31
|
+
field=models.URLField(
|
32
|
+
blank=True, help_text="Your TikTok account URL", verbose_name="TikTok"
|
33
|
+
),
|
34
|
+
),
|
35
|
+
]
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Generated by Django 5.0.2 on 2024-03-21 15:11
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
dependencies = [
|
8
|
+
("cjkcms", "0020_socialmediasettings_github_and_more"),
|
9
|
+
]
|
10
|
+
|
11
|
+
operations = [
|
12
|
+
migrations.RemoveField(
|
13
|
+
model_name="layoutsettings",
|
14
|
+
name="navbar_color_scheme",
|
15
|
+
),
|
16
|
+
migrations.AddField(
|
17
|
+
model_name="layoutsettings",
|
18
|
+
name="color_scheme",
|
19
|
+
field=models.CharField(
|
20
|
+
blank=True,
|
21
|
+
choices=[],
|
22
|
+
default="",
|
23
|
+
help_text="Default light/dark/custom theme. (MD/Bootstrap only)",
|
24
|
+
max_length=50,
|
25
|
+
verbose_name="Color scheme",
|
26
|
+
),
|
27
|
+
),
|
28
|
+
migrations.AddField(
|
29
|
+
model_name="layoutsettings",
|
30
|
+
name="light_dark_switch",
|
31
|
+
field=models.BooleanField(
|
32
|
+
default=False,
|
33
|
+
help_text="Show switch to toggle light/dark theme (MD/Bootstrap only)",
|
34
|
+
verbose_name="Light/Dark switch",
|
35
|
+
),
|
36
|
+
),
|
37
|
+
migrations.AlterField(
|
38
|
+
model_name="layoutsettings",
|
39
|
+
name="frontend_theme",
|
40
|
+
field=models.CharField(
|
41
|
+
blank=True,
|
42
|
+
choices=[],
|
43
|
+
default="",
|
44
|
+
help_text="Change the source of your Bootstrap theme.",
|
45
|
+
max_length=50,
|
46
|
+
verbose_name="Theme variant",
|
47
|
+
),
|
48
|
+
),
|
49
|
+
migrations.AlterField(
|
50
|
+
model_name="layoutsettings",
|
51
|
+
name="navbar_collapse_mode",
|
52
|
+
field=models.CharField(
|
53
|
+
blank=True,
|
54
|
+
choices=[],
|
55
|
+
default="",
|
56
|
+
help_text="Control on what screen sizes to show and collapse the navbar menu links.",
|
57
|
+
max_length=50,
|
58
|
+
verbose_name="Collapse navbar menu",
|
59
|
+
),
|
60
|
+
),
|
61
|
+
migrations.AlterField(
|
62
|
+
model_name="layoutsettings",
|
63
|
+
name="navbar_format",
|
64
|
+
field=models.CharField(
|
65
|
+
blank=True,
|
66
|
+
choices=[],
|
67
|
+
default="",
|
68
|
+
max_length=50,
|
69
|
+
verbose_name="Navbar format",
|
70
|
+
),
|
71
|
+
),
|
72
|
+
migrations.AlterField(
|
73
|
+
model_name="layoutsettings",
|
74
|
+
name="navbar_langselector",
|
75
|
+
field=models.CharField(
|
76
|
+
blank=True,
|
77
|
+
choices=[],
|
78
|
+
default=None,
|
79
|
+
help_text="Choose lang choice selector",
|
80
|
+
max_length=255,
|
81
|
+
null=True,
|
82
|
+
verbose_name="Language selector",
|
83
|
+
),
|
84
|
+
),
|
85
|
+
]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generated by Django 5.0.6 on 2024-09-02 12:44
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
('cjkcms', '0021_remove_layoutsettings_navbar_color_scheme_and_more'),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AddField(
|
14
|
+
model_name='cjkcmspage',
|
15
|
+
name='breadcrumb_label',
|
16
|
+
field=models.CharField(blank=True, help_text='If empty, page title will be used.', max_length=128, verbose_name='Breadcrumb label'),
|
17
|
+
),
|
18
|
+
migrations.AddField(
|
19
|
+
model_name='cjkcmspage',
|
20
|
+
name='breadcrumbs_visible',
|
21
|
+
field=models.BooleanField(default=True, help_text='Show breadcrumbs in this page header. For global change, see Settings->Layout', verbose_name='Breadcrumbs'),
|
22
|
+
),
|
23
|
+
]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Generated by Django 5.1.4 on 2024-12-31 20:17
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
('cjkcms', '0022_cjkcmspage_breadcrumb_label_and_more'),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AlterField(
|
14
|
+
model_name='navbar',
|
15
|
+
name='language',
|
16
|
+
field=models.CharField(blank=True, choices=[], default='_all_', help_text='Select a language to limit display to specific locale.', max_length=10, verbose_name='Show in language'),
|
17
|
+
),
|
18
|
+
]
|
cjkcms/models/admin_sidebar.py
CHANGED
@@ -1,28 +0,0 @@
|
|
1
|
-
from .snippet_models import Navbar, EventCalendar
|
2
|
-
from wagtail.snippets.views.snippets import SnippetViewSet
|
3
|
-
|
4
|
-
|
5
|
-
class NavbarSnippet(SnippetViewSet):
|
6
|
-
model = Navbar
|
7
|
-
menu_label = "Navigation"
|
8
|
-
menu_icon = "link" # change as required
|
9
|
-
add_to_admin_menu = True
|
10
|
-
list_display = (
|
11
|
-
"name",
|
12
|
-
"custom_css_class",
|
13
|
-
"custom_id",
|
14
|
-
)
|
15
|
-
search_fields = [
|
16
|
-
"name",
|
17
|
-
]
|
18
|
-
|
19
|
-
|
20
|
-
class EventCalendarSnippet(SnippetViewSet):
|
21
|
-
model = EventCalendar
|
22
|
-
menu_label = "Public Events"
|
23
|
-
menu_icon = "calendar" # change as required
|
24
|
-
# add_to_admin_menu = True
|
25
|
-
list_display = ("name",)
|
26
|
-
search_fields = [
|
27
|
-
"name",
|
28
|
-
]
|
cjkcms/models/page_models.py
CHANGED
@@ -208,6 +208,25 @@ class CjkcmsPage(WagtailCacheMixin, SeoMixin, Page, metaclass=CjkcmsPageMeta):
|
|
208
208
|
blank=True, max_length=255, choices=None, verbose_name=_("Template") # type: ignore # noqa: E501
|
209
209
|
)
|
210
210
|
|
211
|
+
###############
|
212
|
+
# Breadcrumbs fields (on layout tab)
|
213
|
+
###############
|
214
|
+
|
215
|
+
breadcrumbs_visible = models.BooleanField(
|
216
|
+
default=True,
|
217
|
+
verbose_name=_("Breadcrumbs"),
|
218
|
+
help_text=_(
|
219
|
+
"Show breadcrumbs in this page header. For global change, see Settings->Layout"
|
220
|
+
),
|
221
|
+
)
|
222
|
+
|
223
|
+
breadcrumb_label = models.CharField(
|
224
|
+
blank=True,
|
225
|
+
max_length=128,
|
226
|
+
verbose_name=_("Breadcrumb label"),
|
227
|
+
help_text=_("If empty, page title will be used."),
|
228
|
+
)
|
229
|
+
|
211
230
|
###############
|
212
231
|
# SEO overrides
|
213
232
|
###############
|
@@ -269,6 +288,13 @@ class CjkcmsPage(WagtailCacheMixin, SeoMixin, Page, metaclass=CjkcmsPageMeta):
|
|
269
288
|
|
270
289
|
layout_panels = [
|
271
290
|
MultiFieldPanel([FieldPanel("custom_template")], heading=_("Visual Design")),
|
291
|
+
MultiFieldPanel(
|
292
|
+
[
|
293
|
+
FieldPanel("breadcrumbs_visible"),
|
294
|
+
FieldPanel("breadcrumb_label"),
|
295
|
+
],
|
296
|
+
heading=_("Breadcrumbs settings"),
|
297
|
+
),
|
272
298
|
MultiFieldPanel(
|
273
299
|
[
|
274
300
|
FieldPanel("index_show_subpages"),
|
@@ -347,6 +373,13 @@ class CjkcmsPage(WagtailCacheMixin, SeoMixin, Page, metaclass=CjkcmsPageMeta):
|
|
347
373
|
edit_handler = TabbedInterface(panels)
|
348
374
|
return edit_handler.bind_to_model(cls)
|
349
375
|
|
376
|
+
@property
|
377
|
+
def breadcrumb_title(self) -> str:
|
378
|
+
"""
|
379
|
+
Gets breadcrumb title, or page title if not set.
|
380
|
+
"""
|
381
|
+
return self.breadcrumb_label or self.title # type: ignore
|
382
|
+
|
350
383
|
@property
|
351
384
|
def default_seo_image(self) -> "Optional[AbstractImage]":
|
352
385
|
"""
|
cjkcms/models/snippet_models.py
CHANGED
@@ -25,6 +25,7 @@ from django.conf import settings
|
|
25
25
|
from cjkcms.fields import CjkcmsStreamField
|
26
26
|
from wagtail_color_panel.fields import ColorField
|
27
27
|
from wagtail_color_panel.edit_handlers import NativeColorPanel
|
28
|
+
from django.forms import ModelForm
|
28
29
|
|
29
30
|
|
30
31
|
@register_snippet
|
@@ -342,7 +343,7 @@ class Navbar(models.Model):
|
|
342
343
|
language = models.CharField(
|
343
344
|
blank=True,
|
344
345
|
max_length=10,
|
345
|
-
choices=[
|
346
|
+
choices=[],
|
346
347
|
default="_all_",
|
347
348
|
verbose_name=_("Show in language"),
|
348
349
|
help_text=_("Select a language to limit display to specific locale."),
|
@@ -371,24 +372,38 @@ class Navbar(models.Model):
|
|
371
372
|
def __str__(self):
|
372
373
|
return self.name
|
373
374
|
|
375
|
+
@staticmethod
|
376
|
+
def get_available_langs():
|
377
|
+
available_langs = [("_all_", _("All languages"))]
|
378
|
+
if hasattr(settings, "WAGTAIL_CONTENT_LANGUAGES"):
|
379
|
+
available_langs += settings.WAGTAIL_CONTENT_LANGUAGES
|
380
|
+
return available_langs
|
381
|
+
|
374
382
|
def __init__(self, *args, **kwargs):
|
375
383
|
"""
|
376
384
|
Inject custom choices and defaults into the form fields
|
377
385
|
to enable customization of settings without causing migration issues.
|
378
386
|
"""
|
379
387
|
super().__init__(*args, **kwargs)
|
380
|
-
# Set choices dynamically.
|
381
|
-
|
382
|
-
available_langs = [("_all_", _("All languages"))]
|
383
|
-
if hasattr(settings, "WAGTAIL_CONTENT_LANGUAGES"):
|
384
|
-
available_langs += settings.WAGTAIL_CONTENT_LANGUAGES
|
385
388
|
|
386
|
-
self._meta.get_field("language").choices =
|
389
|
+
self._meta.get_field("language").choices = Navbar.get_available_langs() # type: ignore
|
387
390
|
# Set default dynamically.
|
388
391
|
if not self.id: # type: ignore
|
389
392
|
self.language = "_all_"
|
390
393
|
|
391
394
|
|
395
|
+
class NavbarForm(ModelForm):
|
396
|
+
class Meta:
|
397
|
+
model = Navbar
|
398
|
+
fields = "__all__"
|
399
|
+
|
400
|
+
def __init__(self, *args, **kwargs):
|
401
|
+
super().__init__(*args, **kwargs)
|
402
|
+
|
403
|
+
# Set the dynamic choices
|
404
|
+
self.fields["language"].choices = Navbar.get_available_langs()
|
405
|
+
|
406
|
+
|
392
407
|
@register_snippet
|
393
408
|
class Footer(models.Model):
|
394
409
|
"""
|