add support for page sections on generic pages
This commit is contained in:
@ -136,3 +136,50 @@ class FeaturedBlock(blocks.StructBlock):
|
||||
|
||||
class Meta:
|
||||
icon = "arrow-right-full"
|
||||
|
||||
|
||||
class PageSectionNavigationBlock(blocks.StaticBlock):
|
||||
class Meta:
|
||||
icon = "order-down"
|
||||
label = "Sideseksjonsnavigasjon"
|
||||
admin_text = "Lager automatisk ankerlenker til alle sideseksjoner"
|
||||
|
||||
|
||||
BASE_BLOCKS = [
|
||||
("paragraph", blocks.RichTextBlock(label="Rik tekst")),
|
||||
("image", ImageWithTextBlock(label="Bilde")),
|
||||
("image_slider", ImageSliderBlock(label="Bildegalleri")),
|
||||
("horizontal_rule", HorizontalRuleBlock(label="Skillelinje")),
|
||||
("featured", FeaturedBlock(label="Fremhevet underside")),
|
||||
("page_section_navigation", PageSectionNavigationBlock()),
|
||||
]
|
||||
|
||||
|
||||
@register_streamfield_block
|
||||
class PageSectionBlock(blocks.StructBlock):
|
||||
COLOR_CHOICES = (
|
||||
("deepBrick", "Dyp tegl"),
|
||||
("neufPink", "Griserosa"),
|
||||
("goldenOrange", "Gyllen oransje"),
|
||||
("goldenBeige", "Gyllen beige"),
|
||||
("chateauBlue", "Slottsblå"),
|
||||
)
|
||||
|
||||
title = blocks.CharBlock(max_length=64, required=True, label="Tittel")
|
||||
background_color = blocks.ChoiceBlock(
|
||||
label="Bakgrunnsfarge",
|
||||
required=False,
|
||||
choices=COLOR_CHOICES,
|
||||
)
|
||||
body = blocks.StreamBlock(
|
||||
[block for block in BASE_BLOCKS if block[0] != "page_section_navigation"]
|
||||
)
|
||||
|
||||
graphql_fields = [
|
||||
GraphQLString("title", required=True),
|
||||
GraphQLString("background_color", required=False),
|
||||
GraphQLStreamfield("body", required=True),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
icon = "folder-open-1"
|
||||
|
@ -1,15 +1,8 @@
|
||||
from wagtail import blocks
|
||||
from wagtail.fields import StreamField
|
||||
|
||||
from dnscms.blocks import FeaturedBlock, HorizontalRuleBlock, ImageSliderBlock, ImageWithTextBlock
|
||||
from dnscms.blocks import BASE_BLOCKS
|
||||
|
||||
CommonStreamField = StreamField(
|
||||
[
|
||||
("paragraph", blocks.RichTextBlock(label="Rik tekst")),
|
||||
("image", ImageWithTextBlock(label="Bilde")),
|
||||
("image_slider", ImageSliderBlock(label="Bildegalleri")),
|
||||
("horizontal_rule", HorizontalRuleBlock(label="Skillelinje")),
|
||||
("featured", FeaturedBlock(label="Fremhevet underside")),
|
||||
],
|
||||
BASE_BLOCKS,
|
||||
default=[("paragraph", "")],
|
||||
)
|
||||
|
@ -0,0 +1,36 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-21 00:36
|
||||
|
||||
import django.db.models.deletion
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0006_alter_genericpage_body'),
|
||||
('wagtailcore', '0093_uploadedfile'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='GenericSectionedPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
|
||||
('lead', wagtail.fields.RichTextField()),
|
||||
('body', wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock(label='Rik tekst')), ('image', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('image_format', wagtail.blocks.ChoiceBlock(choices=[('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], icon='cup', label='Bildeformat')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))], label='Bilde')), ('image_slider', wagtail.blocks.StructBlock([('images', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))]), label='Bilder', min_num=1))], label='Bildegalleri')), ('horizontal_rule', wagtail.blocks.StructBlock([('color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Farge', required=False))], label='Skillelinje')), ('featured', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'], label='Tekst', required=True)), ('featured_page', wagtail.blocks.PageChooserBlock(header='Fremhevet side', required=True)), ('link_text', wagtail.blocks.CharBlock(default='Les mer', help_text='Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', label='Lenketekst', max_length=64, required=True)), ('image_position', wagtail.blocks.ChoiceBlock(choices=[('left', 'Venstre'), ('right', 'Høyre')], label='Bildeplassering')), ('featured_image_override', wagtail.images.blocks.ImageChooserBlock(header='Overstyr bilde', help_text='Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', required=False))], label='Fremhevet underside')), ('page_section', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('background_color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Bakgrunnsfarge', required=False)), ('blocks', wagtail.blocks.StreamBlock([('paragraph', wagtail.blocks.RichTextBlock(label='Rik tekst')), ('image', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('image_format', wagtail.blocks.ChoiceBlock(choices=[('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], icon='cup', label='Bildeformat')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))], label='Bilde')), ('image_slider', wagtail.blocks.StructBlock([('images', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))]), label='Bilder', min_num=1))], label='Bildegalleri')), ('horizontal_rule', wagtail.blocks.StructBlock([('color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Farge', required=False))], label='Skillelinje')), ('featured', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'], label='Tekst', required=True)), ('featured_page', wagtail.blocks.PageChooserBlock(header='Fremhevet side', required=True)), ('link_text', wagtail.blocks.CharBlock(default='Les mer', help_text='Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', label='Lenketekst', max_length=64, required=True)), ('image_position', wagtail.blocks.ChoiceBlock(choices=[('left', 'Venstre'), ('right', 'Høyre')], label='Bildeplassering')), ('featured_image_override', wagtail.images.blocks.ImageChooserBlock(header='Overstyr bilde', help_text='Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', required=False))], label='Fremhevet underside'))]))], label='Seksjon'))])),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='genericpage',
|
||||
name='lead',
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-21 00:44
|
||||
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0007_genericsectionedpage_genericpage_lead'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='genericpage',
|
||||
name='body',
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock(label='Rik tekst')), ('image', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('image_format', wagtail.blocks.ChoiceBlock(choices=[('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], icon='cup', label='Bildeformat')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))], label='Bilde')), ('image_slider', wagtail.blocks.StructBlock([('images', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))]), label='Bilder', min_num=1))], label='Bildegalleri')), ('horizontal_rule', wagtail.blocks.StructBlock([('color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Farge', required=False))], label='Skillelinje')), ('featured', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'], label='Tekst', required=True)), ('featured_page', wagtail.blocks.PageChooserBlock(header='Fremhevet side', required=True)), ('link_text', wagtail.blocks.CharBlock(default='Les mer', help_text='Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', label='Lenketekst', max_length=64, required=True)), ('image_position', wagtail.blocks.ChoiceBlock(choices=[('left', 'Venstre'), ('right', 'Høyre')], label='Bildeplassering')), ('featured_image_override', wagtail.images.blocks.ImageChooserBlock(header='Overstyr bilde', help_text='Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', required=False))], label='Fremhevet underside')), ('page_section', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('background_color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Bakgrunnsfarge', required=False)), ('blocks', wagtail.blocks.StreamBlock([('paragraph', wagtail.blocks.RichTextBlock(label='Rik tekst')), ('image', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('image_format', wagtail.blocks.ChoiceBlock(choices=[('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], icon='cup', label='Bildeformat')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))], label='Bilde')), ('image_slider', wagtail.blocks.StructBlock([('images', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))]), label='Bilder', min_num=1))], label='Bildegalleri')), ('horizontal_rule', wagtail.blocks.StructBlock([('color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Farge', required=False))], label='Skillelinje')), ('featured', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'], label='Tekst', required=True)), ('featured_page', wagtail.blocks.PageChooserBlock(header='Fremhevet side', required=True)), ('link_text', wagtail.blocks.CharBlock(default='Les mer', help_text='Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', label='Lenketekst', max_length=64, required=True)), ('image_position', wagtail.blocks.ChoiceBlock(choices=[('left', 'Venstre'), ('right', 'Høyre')], label='Bildeplassering')), ('featured_image_override', wagtail.images.blocks.ImageChooserBlock(header='Overstyr bilde', help_text='Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', required=False))], label='Fremhevet underside'))]))], label='Seksjon'))]),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='GenericSectionedPage',
|
||||
),
|
||||
]
|
21
dnscms/generic/migrations/0009_alter_genericpage_body.py
Normal file
21
dnscms/generic/migrations/0009_alter_genericpage_body.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-21 01:13
|
||||
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0008_alter_genericpage_body_delete_genericsectionedpage'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='genericpage',
|
||||
name='body',
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock(label='Rik tekst')), ('image', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('image_format', wagtail.blocks.ChoiceBlock(choices=[('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], icon='cup', label='Bildeformat')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))], label='Bilde')), ('image_slider', wagtail.blocks.StructBlock([('images', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))]), label='Bilder', min_num=1))], label='Bildegalleri')), ('horizontal_rule', wagtail.blocks.StructBlock([('color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Farge', required=False))], label='Skillelinje')), ('featured', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'], label='Tekst', required=True)), ('featured_page', wagtail.blocks.PageChooserBlock(header='Fremhevet side', required=True)), ('link_text', wagtail.blocks.CharBlock(default='Les mer', help_text='Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', label='Lenketekst', max_length=64, required=True)), ('image_position', wagtail.blocks.ChoiceBlock(choices=[('left', 'Venstre'), ('right', 'Høyre')], label='Bildeplassering')), ('featured_image_override', wagtail.images.blocks.ImageChooserBlock(header='Overstyr bilde', help_text='Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', required=False))], label='Fremhevet underside')), ('page_section', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('background_color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Bakgrunnsfarge', required=False)), ('body', wagtail.blocks.StreamBlock([('paragraph', wagtail.blocks.RichTextBlock(label='Rik tekst')), ('image', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('image_format', wagtail.blocks.ChoiceBlock(choices=[('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], icon='cup', label='Bildeformat')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))], label='Bilde')), ('image_slider', wagtail.blocks.StructBlock([('images', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Bilde')), ('text', wagtail.blocks.CharBlock(label='Tekst', max_length=512, required=False))]), label='Bilder', min_num=1))], label='Bildegalleri')), ('horizontal_rule', wagtail.blocks.StructBlock([('color', wagtail.blocks.ChoiceBlock(choices=[('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], label='Farge', required=False))], label='Skillelinje')), ('featured', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'], label='Tekst', required=True)), ('featured_page', wagtail.blocks.PageChooserBlock(header='Fremhevet side', required=True)), ('link_text', wagtail.blocks.CharBlock(default='Les mer', help_text='Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', label='Lenketekst', max_length=64, required=True)), ('image_position', wagtail.blocks.ChoiceBlock(choices=[('left', 'Venstre'), ('right', 'Høyre')], label='Bildeplassering')), ('featured_image_override', wagtail.images.blocks.ImageChooserBlock(header='Overstyr bilde', help_text='Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', required=False))], label='Fremhevet underside'))]))], label='Seksjon'))]),
|
||||
),
|
||||
]
|
@ -1,20 +1,25 @@
|
||||
from grapple.models import GraphQLStreamfield
|
||||
from grapple.models import GraphQLRichText, GraphQLStreamfield
|
||||
from wagtail.admin.panels import FieldPanel
|
||||
from wagtail.fields import RichTextField, StreamField
|
||||
from wagtail.models import Page
|
||||
|
||||
from dnscms.fields import CommonStreamField
|
||||
from dnscms.blocks import PageSectionBlock
|
||||
from dnscms.fields import BASE_BLOCKS
|
||||
|
||||
|
||||
class GenericPage(Page):
|
||||
subpage_types = ["generic.GenericPage"]
|
||||
show_in_menus = True
|
||||
|
||||
body = CommonStreamField
|
||||
lead = RichTextField(features=["bold", "italic", "link"])
|
||||
body = StreamField(BASE_BLOCKS + [("page_section", PageSectionBlock(label="Seksjon"))])
|
||||
|
||||
content_panels = Page.content_panels + [
|
||||
FieldPanel("lead", heading="Leder"),
|
||||
FieldPanel("body", heading="Innhold"),
|
||||
]
|
||||
|
||||
graphql_fields = [
|
||||
GraphQLRichText("lead"),
|
||||
GraphQLStreamfield("body"),
|
||||
]
|
||||
|
52
web/package-lock.json
generated
52
web/package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"@graphql-codegen/cli": "^5.0.2",
|
||||
"@graphql-codegen/client-preset": "^4.3.0",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@sindresorhus/slugify": "^2.2.1",
|
||||
"@urql/next": "^1.1.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns-tz": "^3.1.3",
|
||||
@ -2661,6 +2662,57 @@
|
||||
"integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@sindresorhus/slugify": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz",
|
||||
"integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/transliterate": "^1.0.0",
|
||||
"escape-string-regexp": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/slugify/node_modules/escape-string-regexp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/transliterate": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz",
|
||||
"integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==",
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"@graphql-codegen/cli": "^5.0.2",
|
||||
"@graphql-codegen/client-preset": "^4.3.0",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@sindresorhus/slugify": "^2.2.1",
|
||||
"@urql/next": "^1.1.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns-tz": "^3.1.3",
|
||||
|
@ -3,6 +3,7 @@ import { GenericFragment } from "@/gql/graphql";
|
||||
import { getClient } from "@/app/client";
|
||||
import { Blocks } from "@/components/blocks/Blocks";
|
||||
import { notFound } from "next/navigation";
|
||||
import { PageHeader } from "@/components/general/PageHeader";
|
||||
|
||||
export const dynamicParams = false;
|
||||
|
||||
@ -12,6 +13,7 @@ const GenericFragmentDefinition = graphql(`
|
||||
id
|
||||
urlPath
|
||||
title
|
||||
lead
|
||||
body {
|
||||
...Blocks
|
||||
}
|
||||
@ -70,12 +72,13 @@ export default async function Page({ params }: { params: { url: string[] } }) {
|
||||
if (!page) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<main className="site-main" id="main">
|
||||
<section className="page-header">
|
||||
<h1>{page.title}</h1>
|
||||
</section>
|
||||
<PageHeader
|
||||
heading={page.title}
|
||||
lead={page.lead}
|
||||
/>
|
||||
<Blocks blocks={page.body} />
|
||||
</main>
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { getClient } from "@/app/client";
|
||||
import Link from "next/link";
|
||||
import { PageHeader } from "@/components/general/PageHeader";
|
||||
import { IconListBlock } from "@/components/blocks/IconListBlock";
|
||||
import { PageSection } from "@/components/blocks/PageSection";
|
||||
import { PageSectionBlock } from "@/components/blocks/PageSection";
|
||||
|
||||
export default async function Page() {
|
||||
return (
|
||||
@ -61,12 +61,11 @@ export default async function Page() {
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<PageSection
|
||||
heading="Adkomst"
|
||||
subheading="Hvordan kommer man seg til Neuf?"
|
||||
<PageSectionBlock
|
||||
block={{ title: "Adkomst" } as any}
|
||||
// subheading="Hvordan kommer man seg til Neuf?"
|
||||
/>
|
||||
<PageSection heading="Åpningstider" />
|
||||
<PageSection />
|
||||
<PageSectionBlock block={{ title: "Åpningstider" } as any} />
|
||||
<section className="pageSection" id="adkomst">
|
||||
<h1>Adkomst</h1>
|
||||
<div className="pageSectionGroup">
|
||||
|
@ -3,9 +3,15 @@ import { ImageWithTextBlock } from "./ImageWithTextBlock";
|
||||
import { ImageSliderBlock } from "./ImageSliderBlock";
|
||||
import { HorizontalRuleBlock } from "./HorizontalRuleBlock";
|
||||
import { FeaturedBlock } from "./FeaturedBlock";
|
||||
import { PageSectionBlock, PageSectionNavigationBlock } from "./PageSection";
|
||||
|
||||
export const Blocks = ({ blocks }: any) => {
|
||||
const sections = blocks.filter(
|
||||
(block: any) => block.__typename === "PageSectionBlock"
|
||||
);
|
||||
|
||||
return blocks.map((block: any) => {
|
||||
console.log("block aaa", block);
|
||||
switch (block.blockType) {
|
||||
case "RichTextBlock":
|
||||
return <RichTextBlock block={block} />;
|
||||
@ -22,9 +28,15 @@ export const Blocks = ({ blocks }: any) => {
|
||||
case "FeaturedBlock":
|
||||
return <FeaturedBlock block={block} />;
|
||||
break;
|
||||
case "PageSectionBlock":
|
||||
return <PageSectionBlock block={block} />;
|
||||
break;
|
||||
case "PageSectionNavigationBlock":
|
||||
return <PageSectionNavigationBlock sections={sections} />;
|
||||
break;
|
||||
default:
|
||||
return <div>Unsupported block type {block.blockType}</div>;
|
||||
console.log("unsupported block", block);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -1,14 +1,55 @@
|
||||
import { PageSectionBlock as PageSectionBlockType } from "@/gql/graphql";
|
||||
import styles from "./pageSection.module.scss";
|
||||
import { Blocks } from "./Blocks";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
|
||||
export const PageSectionBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: PageSectionBlockType;
|
||||
}) => {
|
||||
// TODO: add icon selection to model
|
||||
// TODO: there's a block.backgroundColor
|
||||
|
||||
const anchor = slugify(block.title);
|
||||
|
||||
export const PageSection = ({ heading }: any) => {
|
||||
return (
|
||||
<section className={styles.pageSection}>
|
||||
<section className={styles.pageSection} id={anchor}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={styles.icon}>
|
||||
<img src="/assets/icons/neufneuf.svg" />
|
||||
</div>
|
||||
<h1>{heading}</h1>
|
||||
<h1>{block.title}</h1>
|
||||
</div>
|
||||
<Blocks blocks={block.body} />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export const PageSectionNavigationBlock = ({
|
||||
sections,
|
||||
}: {
|
||||
sections: PageSectionBlockType[];
|
||||
}) => {
|
||||
if (!sections.length) {
|
||||
return <></>;
|
||||
}
|
||||
return (
|
||||
<div className="anchorLinks">
|
||||
<span className="suphead">Hopp til</span>
|
||||
<ul>
|
||||
{sections.map((section) => {
|
||||
const anchor = slugify(section.title);
|
||||
|
||||
return (
|
||||
<li key={anchor}>
|
||||
<a href={`#${anchor}`} className="button">
|
||||
{section.title}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -10,7 +10,9 @@ export const PageHeader = ({
|
||||
return (
|
||||
<div className={styles.pageHeader}>
|
||||
<h1 className={styles.title}>{heading}</h1>
|
||||
{lead && <p className="lead">{lead}</p>}
|
||||
{lead && (
|
||||
<p className="lead" dangerouslySetInnerHTML={{ __html: lead }} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
|
||||
* Therefore it is highly recommended to use the babel or swc plugin for production.
|
||||
*/
|
||||
const documents = {
|
||||
"\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n title\n body {\n ...Blocks\n }\n }\n": types.GenericFragmentDoc,
|
||||
"\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n title\n lead\n body {\n ...Blocks\n }\n }\n": types.GenericFragmentDoc,
|
||||
"\n query allGenericSlugs {\n pages(contentType: \"generic.GenericPage\") {\n id\n urlPath\n }\n }\n ": types.AllGenericSlugsDocument,
|
||||
"\n query genericPageByUrl($urlPath: String!) {\n page: page(contentType: \"generic.GenericPage\", urlPath: $urlPath) {\n ... on GenericPage {\n ...Generic\n }\n }\n }\n ": types.GenericPageByUrlDocument,
|
||||
"\n query allNewsSlugs {\n pages(contentType: \"news.NewsPage\") {\n id\n slug\n }\n }\n ": types.AllNewsSlugsDocument,
|
||||
@ -31,7 +31,13 @@ const documents = {
|
||||
"\n query allVenues {\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n ...Venue\n }\n }\n }\n ": types.AllVenuesDocument,
|
||||
"\n fragment Home on HomePage {\n ... on HomePage {\n featuredEvents {\n id\n }\n }\n }\n": types.HomeFragmentDoc,
|
||||
"\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", limit: 3) {\n ... on NewsPage {\n ...News\n }\n }\n }\n ": types.HomeDocument,
|
||||
"\n fragment Blocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n ... on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n ... on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n ... on HorizontalRuleBlock {\n color\n }\n ... on FeaturedBlock {\n title\n featuredBlockText: text\n linkText\n imagePosition\n featuredPage {\n contentType\n pageType\n url\n ... on EventPage {\n featuredImage {\n ...Image\n }\n }\n ... on NewsPage {\n featuredImage {\n ...Image\n }\n }\n }\n featuredImageOverride {\n ...Image\n }\n }\n }\n": types.BlocksFragmentDoc,
|
||||
"\n fragment RichTextBlock on RichTextBlock {\n rawValue\n value\n }\n": types.RichTextBlockFragmentDoc,
|
||||
"\n fragment ImageWithTextBlock on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n": types.ImageWithTextBlockFragmentDoc,
|
||||
"\n fragment ImageSliderBlock on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n": types.ImageSliderBlockFragmentDoc,
|
||||
"\n fragment HorizontalRuleBlock on HorizontalRuleBlock {\n color\n }\n": types.HorizontalRuleBlockFragmentDoc,
|
||||
"\n fragment FeaturedBlock on FeaturedBlock {\n title\n featuredBlockText: text\n linkText\n imagePosition\n featuredPage {\n contentType\n pageType\n url\n ... on EventPage {\n featuredImage {\n ...Image\n }\n }\n ... on NewsPage {\n featuredImage {\n ...Image\n }\n }\n }\n featuredImageOverride {\n ...Image\n }\n }\n": types.FeaturedBlockFragmentDoc,
|
||||
"\n fragment OneLevelOfBlocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n ...RichTextBlock\n }\n ... on ImageWithTextBlock {\n ...ImageWithTextBlock\n }\n ... on ImageSliderBlock {\n ...ImageSliderBlock\n }\n ... on HorizontalRuleBlock {\n ...HorizontalRuleBlock\n }\n ... on FeaturedBlock {\n ...FeaturedBlock\n }\n }\n": types.OneLevelOfBlocksFragmentDoc,
|
||||
"\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n\n }\n": types.BlocksFragmentDoc,
|
||||
"\n fragment Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n": types.ImageFragmentDoc,
|
||||
"\n fragment Event on EventPage {\n __typename\n id\n slug\n title\n body {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n }\n featuredImage {\n ...Image\n }\n pig\n facebookUrl\n ticketUrl\n free\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n name\n slug\n pig\n }\n }\n occurrences {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n preposition\n url\n }\n }\n }\n organizers {\n ... on EventOrganizer {\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n }\n }\n": types.EventFragmentDoc,
|
||||
"\n query futureEvents {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n eventOrganizers: eventOrganizers {\n ... on EventOrganizer {\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n }\n }\n": types.FutureEventsDocument,
|
||||
@ -57,7 +63,7 @@ export function graphql(source: string): unknown;
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n title\n body {\n ...Blocks\n }\n }\n"): (typeof documents)["\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n title\n body {\n ...Blocks\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n title\n lead\n body {\n ...Blocks\n }\n }\n"): (typeof documents)["\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n title\n lead\n body {\n ...Blocks\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@ -129,7 +135,31 @@ export function graphql(source: "\n query home {\n events: eventIndex {\
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment Blocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n ... on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n ... on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n ... on HorizontalRuleBlock {\n color\n }\n ... on FeaturedBlock {\n title\n featuredBlockText: text\n linkText\n imagePosition\n featuredPage {\n contentType\n pageType\n url\n ... on EventPage {\n featuredImage {\n ...Image\n }\n }\n ... on NewsPage {\n featuredImage {\n ...Image\n }\n }\n }\n featuredImageOverride {\n ...Image\n }\n }\n }\n"): (typeof documents)["\n fragment Blocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n ... on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n ... on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n ... on HorizontalRuleBlock {\n color\n }\n ... on FeaturedBlock {\n title\n featuredBlockText: text\n linkText\n imagePosition\n featuredPage {\n contentType\n pageType\n url\n ... on EventPage {\n featuredImage {\n ...Image\n }\n }\n ... on NewsPage {\n featuredImage {\n ...Image\n }\n }\n }\n featuredImageOverride {\n ...Image\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment RichTextBlock on RichTextBlock {\n rawValue\n value\n }\n"): (typeof documents)["\n fragment RichTextBlock on RichTextBlock {\n rawValue\n value\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment ImageWithTextBlock on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n"): (typeof documents)["\n fragment ImageWithTextBlock on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment ImageSliderBlock on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n"): (typeof documents)["\n fragment ImageSliderBlock on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment HorizontalRuleBlock on HorizontalRuleBlock {\n color\n }\n"): (typeof documents)["\n fragment HorizontalRuleBlock on HorizontalRuleBlock {\n color\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment FeaturedBlock on FeaturedBlock {\n title\n featuredBlockText: text\n linkText\n imagePosition\n featuredPage {\n contentType\n pageType\n url\n ... on EventPage {\n featuredImage {\n ...Image\n }\n }\n ... on NewsPage {\n featuredImage {\n ...Image\n }\n }\n }\n featuredImageOverride {\n ...Image\n }\n }\n"): (typeof documents)["\n fragment FeaturedBlock on FeaturedBlock {\n title\n featuredBlockText: text\n linkText\n imagePosition\n featuredPage {\n contentType\n pageType\n url\n ... on EventPage {\n featuredImage {\n ...Image\n }\n }\n ... on NewsPage {\n featuredImage {\n ...Image\n }\n }\n }\n featuredImageOverride {\n ...Image\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment OneLevelOfBlocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n ...RichTextBlock\n }\n ... on ImageWithTextBlock {\n ...ImageWithTextBlock\n }\n ... on ImageSliderBlock {\n ...ImageSliderBlock\n }\n ... on HorizontalRuleBlock {\n ...HorizontalRuleBlock\n }\n ... on FeaturedBlock {\n ...FeaturedBlock\n }\n }\n"): (typeof documents)["\n fragment OneLevelOfBlocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n ...RichTextBlock\n }\n ... on ImageWithTextBlock {\n ...ImageWithTextBlock\n }\n ... on ImageSliderBlock {\n ...ImageSliderBlock\n }\n ... on HorizontalRuleBlock {\n ...HorizontalRuleBlock\n }\n ... on FeaturedBlock {\n ...FeaturedBlock\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n\n }\n"): (typeof documents)["\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
File diff suppressed because one or more lines are too long
@ -37,8 +37,8 @@ export function unique<T>(array: any[]): any[] {
|
||||
return Array.from(array.reduce((set, item) => set.add(item), new Set()));
|
||||
}
|
||||
|
||||
const BlockFragmentDefinition = graphql(`
|
||||
fragment Blocks on StreamFieldInterface {
|
||||
const OneLevelOfBlocksFragmentDefinition = graphql(`
|
||||
fragment OneLevelOfBlocks on StreamFieldInterface {
|
||||
id
|
||||
blockType
|
||||
field
|
||||
@ -93,6 +93,19 @@ const BlockFragmentDefinition = graphql(`
|
||||
}
|
||||
`);
|
||||
|
||||
const BlockFragmentDefinition = graphql(`
|
||||
fragment Blocks on StreamFieldInterface {
|
||||
... on PageSectionBlock {
|
||||
title
|
||||
backgroundColor
|
||||
body {
|
||||
...OneLevelOfBlocks
|
||||
}
|
||||
}
|
||||
...OneLevelOfBlocks
|
||||
}
|
||||
`);
|
||||
|
||||
const ImageFragmentDefinition = graphql(`
|
||||
fragment Image on CustomImage {
|
||||
id
|
||||
|
Reference in New Issue
Block a user