From 01cd43585464183a452da4368ffc2b0a0571e7f7 Mon Sep 17 00:00:00 2001 From: sarahframe Date: Thu, 9 May 2024 11:13:34 +1200 Subject: [PATCH] global navigation and homepage hero --- .../migrations/0004_alter_blogpost_body.py | 216 ++++++ .../migrations/0005_alter_event_body.py | 216 ++++++ cdhweb/pages/blocks/cta_block.py | 17 + ...ge_hero_image_homepage_summary_and_more.py | 638 ++++++++++++++++++ ...vel1menuitem_primarynavigation_and_more.py | 302 +++++++++ cdhweb/pages/mixin.py | 43 ++ cdhweb/pages/snippets.py | 286 ++++++++ .../pages/templates/cdhpages/home_page.html | 14 +- cdhweb/pages/templatetags/core_tags.py | 68 ++ .../migrations/0005_alter_profile_body.py | 216 ++++++ .../migrations/0005_alter_project_body.py | 216 ++++++ templates/base.html | 11 +- templates/snippets/footer_menu.html | 70 +- templates/snippets/primary_navigation.html | 56 +- templates/snippets/secondary_navigation.html | 7 + 15 files changed, 2293 insertions(+), 83 deletions(-) create mode 100644 cdhweb/blog/migrations/0004_alter_blogpost_body.py create mode 100644 cdhweb/events/migrations/0005_alter_event_body.py create mode 100644 cdhweb/pages/blocks/cta_block.py create mode 100644 cdhweb/pages/migrations/0004_homepage_hero_image_homepage_summary_and_more.py create mode 100644 cdhweb/pages/migrations/0005_footer_level1menuitem_primarynavigation_and_more.py create mode 100644 cdhweb/pages/mixin.py create mode 100644 cdhweb/pages/snippets.py create mode 100644 cdhweb/pages/templatetags/core_tags.py create mode 100644 cdhweb/people/migrations/0005_alter_profile_body.py create mode 100644 cdhweb/projects/migrations/0005_alter_project_body.py create mode 100644 templates/snippets/secondary_navigation.html diff --git a/cdhweb/blog/migrations/0004_alter_blogpost_body.py b/cdhweb/blog/migrations/0004_alter_blogpost_body.py new file mode 100644 index 000000000..2ecccbd61 --- /dev/null +++ b/cdhweb/blog/migrations/0004_alter_blogpost_body.py @@ -0,0 +1,216 @@ +# Generated by Django 5.0.5 on 2024-05-07 21:20 + +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.embeds.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("blog", "0003_alter_blogpost_body"), + ] + + operations = [ + migrations.AlterField( + model_name="blogpost", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + ] diff --git a/cdhweb/events/migrations/0005_alter_event_body.py b/cdhweb/events/migrations/0005_alter_event_body.py new file mode 100644 index 000000000..2dcafc8f0 --- /dev/null +++ b/cdhweb/events/migrations/0005_alter_event_body.py @@ -0,0 +1,216 @@ +# Generated by Django 5.0.5 on 2024-05-07 21:20 + +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.embeds.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("events", "0004_alter_event_body"), + ] + + operations = [ + migrations.AlterField( + model_name="event", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + ] diff --git a/cdhweb/pages/blocks/cta_block.py b/cdhweb/pages/blocks/cta_block.py new file mode 100644 index 000000000..374e25591 --- /dev/null +++ b/cdhweb/pages/blocks/cta_block.py @@ -0,0 +1,17 @@ +from wagtail import blocks + + +class CTABlock(blocks.StructBlock): + class Meta: + template = "core/blocks/cta.html" + label = "Call to action" + icon = "arrow-right-full" + + heading = blocks.CharBlock(max_length=80, required=True) + introduction = blocks.TextBlock( + max_length=150, required=False, help_text="Max 150 characters" + ) + + primary_link_text = blocks.CharBlock(max_length=40, required=True) + + secondary_link_text = blocks.CharBlock(max_length=40, required=False) diff --git a/cdhweb/pages/migrations/0004_homepage_hero_image_homepage_summary_and_more.py b/cdhweb/pages/migrations/0004_homepage_hero_image_homepage_summary_and_more.py new file mode 100644 index 000000000..2e45b5e5d --- /dev/null +++ b/cdhweb/pages/migrations/0004_homepage_hero_image_homepage_summary_and_more.py @@ -0,0 +1,638 @@ +# Generated by Django 5.0.5 on 2024-05-08 22:33 + +import django.db.models.deletion +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.embeds.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cdhpages", "0003_alter_contentpage_body_alter_homepage_body_and_more"), + ("wagtailimages", "0025_alter_image_file_alter_rendition_file"), + ] + + operations = [ + migrations.AddField( + model_name="homepage", + name="hero_image", + field=models.ForeignKey( + blank=True, + help_text="Image that conveys sense of site / brand", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailimages.image", + ), + ), + migrations.AddField( + model_name="homepage", + name="summary", + field=models.TextField( + blank=True, + help_text="Text that supports / qualifies the hero header and gives people a sense of who you are", + max_length=150, + verbose_name="Page Summary", + ), + ), + migrations.AlterField( + model_name="contentpage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + migrations.AlterField( + model_name="homepage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + migrations.AlterField( + model_name="landingpage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + ] diff --git a/cdhweb/pages/migrations/0005_footer_level1menuitem_primarynavigation_and_more.py b/cdhweb/pages/migrations/0005_footer_level1menuitem_primarynavigation_and_more.py new file mode 100644 index 000000000..1875d4165 --- /dev/null +++ b/cdhweb/pages/migrations/0005_footer_level1menuitem_primarynavigation_and_more.py @@ -0,0 +1,302 @@ +# Generated by Django 5.0.5 on 2024-05-08 22:53 + +import django.db.models.deletion +import modelcluster.fields +import wagtail.blocks +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cdhpages", "0004_homepage_hero_image_homepage_summary_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="Footer", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ], + options={ + "verbose_name": "Footer", + "verbose_name_plural": "Footer", + }, + ), + migrations.CreateModel( + name="Level1MenuItem", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ( + "title", + models.CharField(max_length=60, verbose_name="Menu item title"), + ), + ( + "overview", + models.TextField(max_length=120, verbose_name="Section overview"), + ), + ( + "section_link_title", + models.CharField(max_length=60, verbose_name="Section link title"), + ), + ( + "section_link", + wagtail.fields.StreamField( + [ + ("page", wagtail.blocks.PageChooserBlock()), + ("external", wagtail.blocks.URLBlock()), + ], + use_json_field=True, + ), + ), + ], + options={ + "ordering": ["sort_order"], + "abstract": False, + }, + ), + migrations.CreateModel( + name="PrimaryNavigation", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ], + options={ + "verbose_name": "Primary Navigation", + "verbose_name_plural": "Primary Navigation", + }, + ), + migrations.CreateModel( + name="SecondaryNavigation", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ], + options={ + "verbose_name": "Secondary Navigation", + "verbose_name_plural": "Secondary Navigation", + }, + ), + migrations.CreateModel( + name="FooterColumn", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "title", + models.CharField( + blank=True, + default="", + max_length=255, + verbose_name="Column heading", + ), + ), + ( + "footer", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="footer_columns", + to="cdhpages.footer", + ), + ), + ], + options={ + "verbose_name": "Footer column", + "verbose_name_plural": "Footer columns", + }, + ), + migrations.CreateModel( + name="ColumnItem", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("body", wagtail.fields.RichTextField()), + ( + "column", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="column_items", + to="cdhpages.footercolumn", + ), + ), + ], + ), + migrations.CreateModel( + name="ImprintLinkItem", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ("title", models.CharField(max_length=60, verbose_name="Menu title")), + ( + "link", + wagtail.fields.StreamField( + [ + ("page", wagtail.blocks.PageChooserBlock()), + ("external", wagtail.blocks.URLBlock()), + ], + use_json_field=True, + ), + ), + ( + "imprint_link", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="imprint_links", + to="cdhpages.footer", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.CreateModel( + name="Level2MenuItem", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ("title", models.CharField(max_length=60, verbose_name="Item title")), + ( + "link", + wagtail.fields.StreamField( + [ + ("page", wagtail.blocks.PageChooserBlock()), + ("external", wagtail.blocks.URLBlock()), + ], + use_json_field=True, + ), + ), + ( + "l1_parent", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="l2_items", + to="cdhpages.level1menuitem", + ), + ), + ], + options={ + "ordering": ["sort_order"], + "abstract": False, + }, + ), + migrations.AddField( + model_name="level1menuitem", + name="main_menu", + field=modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="l1_items", + to="cdhpages.primarynavigation", + ), + ), + migrations.CreateModel( + name="SecondaryNavigationItem", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ("title", models.CharField(max_length=60, verbose_name="Menu title")), + ( + "link", + wagtail.fields.StreamField( + [ + ("page", wagtail.blocks.PageChooserBlock()), + ("external", wagtail.blocks.URLBlock()), + ], + use_json_field=True, + ), + ), + ( + "secondary_menu", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="items", + to="cdhpages.secondarynavigation", + ), + ), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/cdhweb/pages/mixin.py b/cdhweb/pages/mixin.py new file mode 100644 index 000000000..e18a34aee --- /dev/null +++ b/cdhweb/pages/mixin.py @@ -0,0 +1,43 @@ +from django.db import models +from wagtail.admin.panels import FieldPanel, MultiFieldPanel, TitleFieldPanel + + +class HomePageHeroMixin(models.Model): + title = models.CharField( + max_length=45, + blank=True, + null=False, + verbose_name="Hero title", + help_text="Heading on the larger hero banner at top of the page", + ) + + summary = models.TextField( + max_length=150, + blank=True, + null=False, + verbose_name="Page Summary", + help_text="Text that supports / qualifies the hero header and gives people a sense of who you are", + ) + + hero_image = models.ForeignKey( + "wagtailimages.Image", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="+", + help_text="Image that conveys sense of site / brand", + ) + + content_panels = [ + MultiFieldPanel( + [ + TitleFieldPanel("title"), + FieldPanel("summary"), + FieldPanel("hero_image"), + ], + "HomePage Hero", + ) + ] + + class Meta: + abstract = True diff --git a/cdhweb/pages/snippets.py b/cdhweb/pages/snippets.py new file mode 100644 index 000000000..15cd423a4 --- /dev/null +++ b/cdhweb/pages/snippets.py @@ -0,0 +1,286 @@ +from django.core.exceptions import ValidationError +from django.db import models +from modelcluster.fields import ParentalKey +from modelcluster.models import ClusterableModel +from wagtail import blocks +from wagtail.admin.panels import FieldPanel, InlinePanel +from wagtail.fields import RichTextField, StreamField +from wagtail.models import Orderable +from wagtail.snippets.models import register_snippet + + +class Level2MenuItem(Orderable, ClusterableModel): + """ + Represents a 'second-level' menu item. + """ + + title = models.CharField(max_length=60, verbose_name="Item title") + link = StreamField( + [ + ("page", blocks.PageChooserBlock()), + ("external", blocks.URLBlock()), + ], + use_json_field=True, + max_num=1, + ) + + l1_parent = ParentalKey( + "Level1MenuItem", related_name="l2_items", on_delete=models.CASCADE + ) + + panels = [ + FieldPanel("title"), + FieldPanel("link"), + ] + + @property + def link_url(self): + """This saves a bit of faff in the templates.""" + if not self.link[0].value: + return None + if self.link[0].block_type == "page": + return self.link[0].value.url + return self.link[0].value + + def __str__(self): + return self.title + + +class Level1MenuItem(Orderable, ClusterableModel): + """ + Represents a 'first-level' menu item. + """ + + main_menu = ParentalKey( + "PrimaryNavigation", related_name="l1_items", on_delete=models.CASCADE + ) + + title = models.CharField(max_length=60, verbose_name="Menu item title") + overview = models.TextField(verbose_name="Section overview", max_length=120) + section_link_title = models.CharField( + max_length=60, verbose_name="Section link title" + ) + section_link = StreamField( + [ + ("page", blocks.PageChooserBlock()), + ("external", blocks.URLBlock()), + ], + use_json_field=True, + max_num=1, + ) + panels = [ + FieldPanel("title"), + FieldPanel("overview"), + FieldPanel("section_link_title"), + FieldPanel("section_link"), + InlinePanel("l2_items", label="Second-level menu items", max_num=20), + ] + + @property + def link_url(self): + """This saves a bit of faff in the templates.""" + if not self.section_link[0].value: + return None + if self.section_link[0].block_type == "page": + return self.section_link[0].value.url + return self.section_link[0].value + + def __str__(self): + return self.title + + +@register_snippet +class PrimaryNavigation(ClusterableModel): + """ + Root element of the menu. + """ + + def __str__(self): + return f"Primary Navigation #{self.pk}" + + class Meta: + verbose_name = "Primary Navigation" + verbose_name_plural = "Primary Navigation" + + panels = [ + InlinePanel("l1_items", label="Top-level menu items", max_num=7), + ] + + def clean(self): + # Singleton implemented here rather than as a mixin so that we can + # customise the error message below. + model = self.__class__ + if model.objects.count() > 0 and self.pk != model.objects.get().pk: + raise ValidationError( + "Only one Main Menu allowed. Please go back and edit the existing one." + ) + super().clean() + + +class MiniMenuItemBase(Orderable, ClusterableModel): + class Meta: + abstract = True + + title = models.CharField(max_length=60, verbose_name="Menu title") + link = StreamField( + [ + ("page", blocks.PageChooserBlock()), + ("external", blocks.URLBlock()), + ], + use_json_field=True, + max_num=1, + ) + panels = [ + FieldPanel("title"), + FieldPanel("link"), + ] + + @property + def link_url(self): + """This saves a bit of faff in the templates.""" + if not self.link[0].value: + return None + if self.link[0].block_type == "page": + return self.link[0].value.url + return self.link[0].value + + def __str__(self): + return f"Mini menu item: {self.title}" + + +class MiniMenu(ClusterableModel): + class Meta: + verbose_name = "Mini Menu" + verbose_name_plural = "Mini Menu" + abstract = True + + def __str__(self): + return f"Mini Menu #{self.pk}" + + def clean(self): + # Singleton implemented here rather than as a mixin so that we can + # customise the error message below. + model = self.__class__ + if model.objects.count() > 0 and self.pk != model.objects.get().pk: + verbose_name = self._meta.verbose_name + raise ValidationError( + f"Only one {verbose_name} allowed. Please go back and edit the existing one." + ) + super().clean() + + +class SecondaryNavigationItem(MiniMenuItemBase): + secondary_menu = ParentalKey( + "SecondaryNavigation", related_name="items", on_delete=models.CASCADE + ) + + def __str__(self): + return f"Secondary navigation item: {self.title}" + + +@register_snippet +class SecondaryNavigation(MiniMenu): + """ + Root element of the secondary navigation. + """ + + def __str__(self): + return f"Secondary navigation #{self.pk}" + + class Meta: + verbose_name = "Secondary Navigation" + verbose_name_plural = "Secondary Navigation" + + panels = [ + InlinePanel("items", label="Secondary navigation items", max_num=3), + ] + + +@register_snippet +class Footer(ClusterableModel): + """ + A Snippet for the site's footer that includes two columns. + """ + + class Meta: + verbose_name = "Footer" + verbose_name_plural = "Footer" + + panels = [ + InlinePanel("footer_columns", label="Footer column(s)", max_num=2), + InlinePanel("imprint_links", label="Imprint links", max_num=4), + ] + + def __str__(self): + return "Site Footer" + + def clean(self): + # Singleton implemented here rather than as a mixin etc, so that we can + # customise the error message below. + model = self.__class__ + if model.objects.count() > 0 and self.pk != model.objects.get().pk: + raise ValidationError( + "Only one Footer allowed. Please go back and edit the existing one." + ) + super().clean() + + +class FooterColumn(ClusterableModel): + """ + Represents a column in the footer, which can contain multiple items. + Each column has a bilingual heading. + """ + + class Meta: + verbose_name = "Footer column" + verbose_name_plural = "Footer columns" + + footer = ParentalKey( + "Footer", related_name="footer_columns", on_delete=models.CASCADE + ) + title = models.CharField( # noqa: DJ001 + max_length=255, verbose_name="Column heading", blank=True, default="" + ) + + panels = [ + FieldPanel("title"), + InlinePanel("column_items", label="Column item(s)", max_num=10), + ] + + def __str__(self): + return self.title + + +class ColumnItem(models.Model): + """ + Represents an item within a footer column, containing a rich text field + for contact item body, which supports bold, text, and links. + """ + + column = ParentalKey( + "FooterColumn", related_name="column_items", on_delete=models.CASCADE + ) + body = RichTextField(features=["bold", "link"]) + + panels = [ + FieldPanel("body"), + ] + + def __str__(self): + if self.title: + return self.title + return "Column Item" + + +class ImprintLinkItem(MiniMenuItemBase): + """ + Imprint link item for the bottom of the footer. + Consists of a title and link to internal or external page. + """ + + imprint_link = ParentalKey( + "Footer", related_name="imprint_links", on_delete=models.CASCADE + ) + + def __str__(self): + return f"Imprint link item: {self.title}" diff --git a/cdhweb/pages/templates/cdhpages/home_page.html b/cdhweb/pages/templates/cdhpages/home_page.html index e07a6d026..881111d4e 100644 --- a/cdhweb/pages/templates/cdhpages/home_page.html +++ b/cdhweb/pages/templates/cdhpages/home_page.html @@ -1,10 +1,22 @@ {% extends 'base.html' %} -{% load wagtailcore_tags %} +{% load wagtailcore_tags wagtailimages_tags %} {# Override entire title so there's no extra context appended #} {% block title %}{% firstof page.seo_title page.title %}{% endblock %} {% block content %} {# add a class to main content for home-page specific styles #} + +

Homepage hero

+
{{ self.title}}
+
{{ self.summary }}
+{% if self.hero_image %} +{% image self.hero_image width-400 as image %} +{{ image.title }} +{% endif %} + + + +
{% if updates %} {% include 'snippets/carousel.html' %} diff --git a/cdhweb/pages/templatetags/core_tags.py b/cdhweb/pages/templatetags/core_tags.py new file mode 100644 index 000000000..4c6fd2cc4 --- /dev/null +++ b/cdhweb/pages/templatetags/core_tags.py @@ -0,0 +1,68 @@ +from django import template +from django.conf import settings +from django.template.loader import render_to_string +from django.utils import timezone + +from cdhweb.pages.snippets import Footer, PrimaryNavigation, SecondaryNavigation + +register = template.Library() + + +@register.inclusion_tag("snippets/footer_menu.html", takes_context=True) +def site_footer(context): + """ + Returns the site footer data. + """ + # Get footer columns + footer_columns = [] + footers = Footer.objects.prefetch_related( + "footer_columns", "footer_columns__column_items", "imprint_links" + ) + + if footers.exists(): + footer_columns = footers.first().footer_columns.all() + imprint_links = footers.first().imprint_links.all() + + data = { + "footer_columns": footer_columns, + "imprint_links": imprint_links, + "request": context["request"], + } + return data + + +@register.inclusion_tag("snippets/primary_navigation.html", takes_context=True) +def primary_navigation(context): + """ + Returns the primary navigation menu. + """ + l1_menu_items = [] + main_menu = PrimaryNavigation.objects.prefetch_related( + "l1_items", "l1_items__l2_items" + ) + if main_menu.exists(): + l1_menu_items = main_menu.first().l1_items.all() + + data = { + "l1_menu_items": l1_menu_items, + "request": context["request"], + } + return data + + +@register.inclusion_tag("snippets/secondary_navigation.html", takes_context=True) +def secondary_navigation(context): + """ + Returns the secondary navigation menu. + """ + + items = [] + secondary_menu = SecondaryNavigation.objects.prefetch_related("items") + if secondary_menu.exists(): + items = secondary_menu.first().items.all() + + data = { + "secondary_nav_items": items, + "request": context["request"], + } + return data diff --git a/cdhweb/people/migrations/0005_alter_profile_body.py b/cdhweb/people/migrations/0005_alter_profile_body.py new file mode 100644 index 000000000..454fbefb4 --- /dev/null +++ b/cdhweb/people/migrations/0005_alter_profile_body.py @@ -0,0 +1,216 @@ +# Generated by Django 5.0.5 on 2024-05-07 21:20 + +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.embeds.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("people", "0004_alter_profile_body"), + ] + + operations = [ + migrations.AlterField( + model_name="profile", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + ] diff --git a/cdhweb/projects/migrations/0005_alter_project_body.py b/cdhweb/projects/migrations/0005_alter_project_body.py new file mode 100644 index 000000000..e378bc49c --- /dev/null +++ b/cdhweb/projects/migrations/0005_alter_project_body.py @@ -0,0 +1,216 @@ +# Generated by Django 5.0.5 on 2024-05-07 21:20 + +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.embeds.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("projects", "0004_alter_project_body"), + ] + + operations = [ + migrations.AlterField( + model_name="project", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "paragraph", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + ] + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ] + ), + ), + ( + "svg_image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.documents.blocks.DocumentChooserBlock(), + ), + ( + "alternative_text", + wagtail.blocks.TextBlock( + help_text="Alternative text for visually impaired users to\nbriefly communicate the intended message of the image in this context.", + required=True, + ), + ), + ( + "caption", + wagtail.blocks.RichTextBlock( + features=[ + "bold", + "italic", + "link", + "superscript", + ], + required=False, + ), + ), + ( + "extended_description", + wagtail.blocks.RichTextBlock( + features=["p"], + help_text="This text will only be read to non-sighted users and should describe the major insights or takeaways from the graphic. Multiple paragraphs are allowed.", + required=False, + ), + ), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text='For e.g. videos on YouTube, use the value in the URL bar.\n For other content, look for an "oEmbed URL" option. For videos from\n Princeton\'s Media Central, "oEmbed URL" is in the "Share" menu.' + ), + ), + ( + "migrated", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "link", + "ol", + "ul", + "hr", + "blockquote", + "superscript", + "subscript", + "strikethrough", + "code", + "image", + "embed", + ], + icon="warning", + ), + ), + ( + "code", + wagtail.blocks.StructBlock( + [ + ( + "language", + wagtail.blocks.ChoiceBlock( + choices=[ + ("bash", "Bash/Shell"), + ("css", "CSS"), + ("diff", "diff"), + ("html", "HTML"), + ("javascript", "Javascript"), + ("json", "JSON"), + ("python", "Python"), + ("scss", "SCSS"), + ("yaml", "YAML"), + ("django", "Django/Jinja2"), + ("git", "Git"), + ("go", "Go"), + ( + "markup", + "Markup + HTML + XML + SVG + MathML", + ), + ("r", "R"), + ], + help_text="Coding language", + identifier="language", + label="Language", + ), + ), + ( + "code", + wagtail.blocks.TextBlock( + identifier="code", label="Code" + ), + ), + ], + label="Code", + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + max_length=80, required=True + ), + ), + ( + "introduction", + wagtail.blocks.TextBlock( + help_text="Max 150 characters", + max_length=150, + required=False, + ), + ), + ( + "primary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=True + ), + ), + ( + "secondary_link_text", + wagtail.blocks.CharBlock( + max_length=40, required=False + ), + ), + ] + ), + ), + ], + blank=True, + use_json_field=True, + ), + ), + ] diff --git a/templates/base.html b/templates/base.html index 6d73c8413..5d9e24b96 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,4 +1,4 @@ -{% load static compress wagtailuserbar wagtailcore_tags wagtailcodeblock_tags %} +{% load static compress wagtailuserbar wagtailcore_tags wagtailcodeblock_tags core_tags %} @@ -52,7 +52,10 @@ +
+ {% endfor %} + + {% for item in imprint_links.all %} + {{ item.title }} + {% endfor %} \ No newline at end of file diff --git a/templates/snippets/primary_navigation.html b/templates/snippets/primary_navigation.html index 87a977816..4f970ed0a 100644 --- a/templates/snippets/primary_navigation.html +++ b/templates/snippets/primary_navigation.html @@ -1,37 +1,19 @@ -{% load static i18n cdh_tags %} -{# top level menu, with secondary nav for current site section #} - -{% for navpage in toplevel_pages %} - {% include "snippets/navigation_card.html" with navpages=navpage.get_children.live.in_menu %} -{% endfor %} -{% endwith %} +{% load wagtailcore_tags core_tags static %} + + +{% for item in l1_menu_items %} +
+

{{ item.title }}

+ + + +
+ +{% endfor %} \ No newline at end of file diff --git a/templates/snippets/secondary_navigation.html b/templates/snippets/secondary_navigation.html new file mode 100644 index 000000000..5616332c2 --- /dev/null +++ b/templates/snippets/secondary_navigation.html @@ -0,0 +1,7 @@ +{% load wagtailcore_tags core_tags static %} + +
+ {% for item in secondary_nav_items %} + {{ item.title }} + {% endfor %} +
\ No newline at end of file