add contact pages and blocks
This commit is contained in:
@ -0,0 +1,27 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:29
|
||||||
|
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('associations', '0010_alter_associationindex_body_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='associationindex',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock())], default=[('paragraph', '')]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='associationpage',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock())], default=[('paragraph', '')]),
|
||||||
|
),
|
||||||
|
]
|
0
dnscms/contacts/__init__.py
Normal file
0
dnscms/contacts/__init__.py
Normal file
6
dnscms/contacts/apps.py
Normal file
6
dnscms/contacts/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ContactConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "contacts"
|
62
dnscms/contacts/blocks.py
Normal file
62
dnscms/contacts/blocks.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
from grapple.helpers import register_streamfield_block
|
||||||
|
from grapple.models import GraphQLForeignKey, GraphQLStreamfield, GraphQLString
|
||||||
|
from wagtail import blocks
|
||||||
|
from wagtail.snippets.blocks import SnippetChooserBlock
|
||||||
|
|
||||||
|
|
||||||
|
@register_streamfield_block
|
||||||
|
class ContactEntityBlock(blocks.StructBlock):
|
||||||
|
contact_entity = SnippetChooserBlock("contacts.ContactEntity")
|
||||||
|
|
||||||
|
graphql_fields = [
|
||||||
|
GraphQLForeignKey("contact_entity", "contacts.ContactEntity"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@register_streamfield_block
|
||||||
|
class ContactListBlock(blocks.ListBlock):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
ContactEntityList = ContactListBlock(ContactEntityBlock(), label="Liste med kontaktpunkter")
|
||||||
|
|
||||||
|
|
||||||
|
@register_streamfield_block
|
||||||
|
class ContactSubsectionBlock(blocks.StructBlock):
|
||||||
|
title = blocks.CharBlock(max_length=64, required=True, label="Tittel")
|
||||||
|
text = blocks.RichTextBlock(features=["bold", "italic", "link"])
|
||||||
|
blocks = blocks.StreamBlock(
|
||||||
|
[
|
||||||
|
("contact_entity_list", ContactEntityList),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
graphql_fields = [
|
||||||
|
GraphQLString("title", required=True),
|
||||||
|
GraphQLString("text", required=False),
|
||||||
|
GraphQLStreamfield("blocks", required=False),
|
||||||
|
]
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
icon = "folder-open-1"
|
||||||
|
|
||||||
|
|
||||||
|
@register_streamfield_block
|
||||||
|
class ContactSectionBlock(blocks.StructBlock):
|
||||||
|
title = blocks.CharBlock(max_length=64, required=True, label="Tittel")
|
||||||
|
text = blocks.RichTextBlock(features=["bold", "italic", "link"])
|
||||||
|
blocks = blocks.StreamBlock(
|
||||||
|
[
|
||||||
|
("contact_entity_list", ContactEntityList),
|
||||||
|
("contact_subsection", ContactSubsectionBlock(label="Kontaktunderseksjon")),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
graphql_fields = [
|
||||||
|
GraphQLString("title", required=True),
|
||||||
|
GraphQLString("text", required=False),
|
||||||
|
GraphQLStreamfield("blocks", required=False),
|
||||||
|
]
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
icon = "folder-open-1"
|
34
dnscms/contacts/migrations/0001_initial.py
Normal file
34
dnscms/contacts/migrations/0001_initial.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:33
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('images', '0003_alter_customimage_alt'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ContactEntity',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=128)),
|
||||||
|
('contact_type', models.CharField(choices=[('person', 'Person')], default='person', max_length=128)),
|
||||||
|
('title', models.CharField(blank=True, max_length=128)),
|
||||||
|
('email', models.EmailField(blank=True, max_length=254)),
|
||||||
|
('phone_number', models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')])),
|
||||||
|
('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.customimage')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Kontaktpunkt',
|
||||||
|
'verbose_name_plural': 'Kontaktpunkt',
|
||||||
|
'ordering': ['name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,36 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:49
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
import wagtail.snippets.blocks
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contacts', '0001_initial'),
|
||||||
|
('wagtailcore', '0093_uploadedfile'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ContactIndex',
|
||||||
|
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(blank=True)),
|
||||||
|
('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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock()), ('contact_section', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'])), ('blocks', wagtail.blocks.StreamBlock([('contact_entity', wagtail.snippets.blocks.SnippetChooserBlock('contacts.models.ContactEntity')), ('subsections', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'])), ('blocks', wagtail.blocks.StreamBlock([('contact_entity', wagtail.snippets.blocks.SnippetChooserBlock('contacts.models.ContactEntity'))]))]))]))], label='Kontaktseksjon'))])),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
bases=('wagtailcore.page',),
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='contactentity',
|
||||||
|
options={'ordering': ['name'], 'verbose_name': 'Contact point', 'verbose_name_plural': 'Contact points'},
|
||||||
|
),
|
||||||
|
]
|
23
dnscms/contacts/migrations/0003_alter_contactindex_body.py
Normal file
23
dnscms/contacts/migrations/0003_alter_contactindex_body.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:50
|
||||||
|
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
import wagtail.snippets.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contacts', '0002_contactindex_alter_contactentity_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='contactindex',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock()), ('contact_section', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'])), ('blocks', wagtail.blocks.StreamBlock([('contact_entity', wagtail.snippets.blocks.SnippetChooserBlock('contacts.models.ContactEntity')), ('subsections', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'])), ('blocks', wagtail.blocks.StreamBlock([('contact_entity', wagtail.snippets.blocks.SnippetChooserBlock('contacts.ContactEntity'))]))]))]))], label='Kontaktseksjon'))]),
|
||||||
|
),
|
||||||
|
]
|
24
dnscms/contacts/migrations/0004_alter_contactindex_body.py
Normal file
24
dnscms/contacts/migrations/0004_alter_contactindex_body.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 02:13
|
||||||
|
|
||||||
|
import contacts.blocks
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
import wagtail.snippets.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contacts', '0003_alter_contactindex_body'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='contactindex',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock()), ('contact_section', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'])), ('blocks', wagtail.blocks.StreamBlock([('contact_entity_list', contacts.blocks.ContactListBlock(wagtail.blocks.StructBlock([('contact_entity', wagtail.snippets.blocks.SnippetChooserBlock('contacts.ContactEntity'))]), label='Liste med kontaktpunkter')), ('contact_subsection', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Tittel', max_length=64, required=True)), ('text', wagtail.blocks.RichTextBlock(features=['bold', 'italic', 'link'])), ('blocks', wagtail.blocks.StreamBlock([('contact_entity_list', contacts.blocks.ContactListBlock(wagtail.blocks.StructBlock([('contact_entity', wagtail.snippets.blocks.SnippetChooserBlock('contacts.ContactEntity'))]), label='Liste med kontaktpunkter'))]))], label='Kontaktunderseksjon'))]))], label='Kontaktseksjon'))]),
|
||||||
|
),
|
||||||
|
]
|
0
dnscms/contacts/migrations/__init__.py
Normal file
0
dnscms/contacts/migrations/__init__.py
Normal file
98
dnscms/contacts/models.py
Normal file
98
dnscms/contacts/models.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
from django import forms
|
||||||
|
from django.core.validators import RegexValidator
|
||||||
|
from django.db import models
|
||||||
|
from grapple.helpers import register_query_field, register_singular_query_field
|
||||||
|
from grapple.models import GraphQLImage, GraphQLRichText, GraphQLStreamfield, GraphQLString
|
||||||
|
from wagtail.admin.panels import (
|
||||||
|
FieldPanel,
|
||||||
|
TitleFieldPanel,
|
||||||
|
)
|
||||||
|
from wagtail.fields import RichTextField, StreamField
|
||||||
|
from wagtail.models import Page
|
||||||
|
from wagtail.snippets.models import register_snippet
|
||||||
|
|
||||||
|
from contacts.blocks import ContactSectionBlock
|
||||||
|
from dnscms.blocks import BASE_BLOCKS
|
||||||
|
|
||||||
|
PHONE_REGEX_VALIDATOR = RegexValidator(
|
||||||
|
regex=r"^\+?1?\d{9,15}$",
|
||||||
|
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register_singular_query_field("contactIndex")
|
||||||
|
class ContactIndex(Page):
|
||||||
|
max_count = 1
|
||||||
|
subpage_types = []
|
||||||
|
|
||||||
|
lead = RichTextField(features=["bold", "italic", "link"], blank=True)
|
||||||
|
body = StreamField(
|
||||||
|
BASE_BLOCKS + [("contact_section", ContactSectionBlock(label="Kontaktseksjon"))]
|
||||||
|
)
|
||||||
|
|
||||||
|
content_panels = Page.content_panels + [
|
||||||
|
FieldPanel("lead", heading="Ingress"),
|
||||||
|
FieldPanel("body", heading="Innhold"),
|
||||||
|
]
|
||||||
|
|
||||||
|
graphql_fields = [GraphQLRichText("lead"), GraphQLStreamfield("body")]
|
||||||
|
|
||||||
|
|
||||||
|
@register_snippet
|
||||||
|
@register_query_field("contactEntity", "contactEntities")
|
||||||
|
class ContactEntity(models.Model):
|
||||||
|
CONTACT_TYPE_CHOICES = [
|
||||||
|
("person", "Person"),
|
||||||
|
]
|
||||||
|
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=128,
|
||||||
|
null=False,
|
||||||
|
blank=False,
|
||||||
|
)
|
||||||
|
contact_type = models.CharField(
|
||||||
|
max_length=128, choices=CONTACT_TYPE_CHOICES, default="person", blank=False
|
||||||
|
)
|
||||||
|
title = models.CharField(
|
||||||
|
max_length=128,
|
||||||
|
null=False,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
email = models.EmailField(blank=True)
|
||||||
|
phone_number = models.CharField(validators=[PHONE_REGEX_VALIDATOR], max_length=17, blank=True)
|
||||||
|
|
||||||
|
image = models.ForeignKey(
|
||||||
|
"images.CustomImage",
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name="+",
|
||||||
|
)
|
||||||
|
|
||||||
|
title_widget = forms.TextInput(attrs={"placeholder": "Navn*"})
|
||||||
|
|
||||||
|
panels = [
|
||||||
|
TitleFieldPanel("name", heading="Navn", widget=title_widget),
|
||||||
|
FieldPanel("contact_type", heading="Kontakttype"),
|
||||||
|
FieldPanel("title", heading="Tittel/stilling"),
|
||||||
|
FieldPanel("email", heading="E-post"),
|
||||||
|
FieldPanel("phone_number", heading="Telefonnummer"),
|
||||||
|
FieldPanel("image", heading="Bilde"),
|
||||||
|
]
|
||||||
|
|
||||||
|
graphql_fields = [
|
||||||
|
GraphQLString("name", required=True),
|
||||||
|
GraphQLString("contact_type", required=True),
|
||||||
|
GraphQLString("title", required=False),
|
||||||
|
GraphQLString("email", required=False),
|
||||||
|
GraphQLString("phone_number", required=False),
|
||||||
|
GraphQLImage("image", required=False),
|
||||||
|
]
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Contact point"
|
||||||
|
verbose_name_plural = "Contact points"
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
15
dnscms/contacts/views.py
Normal file
15
dnscms/contacts/views.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from wagtail.admin.viewsets.chooser import ChooserViewSet
|
||||||
|
|
||||||
|
|
||||||
|
class ContactEntityChooserViewSet(ChooserViewSet):
|
||||||
|
model = "contacts.ContactEntity"
|
||||||
|
icon = "mail"
|
||||||
|
per_page = 30
|
||||||
|
page_title = "Choose contact points"
|
||||||
|
choose_one_text = "Choose a contact point"
|
||||||
|
choose_another_text = "Choose another contact point"
|
||||||
|
edit_item_text = "Edit this contact point"
|
||||||
|
form_fields = ["name", "contact_type", "title", "email", "phone_number", "image"]
|
||||||
|
|
||||||
|
|
||||||
|
contact_entity_chooser_viewset = ContactEntityChooserViewSet("contact_entity_chooser")
|
8
dnscms/contacts/widgets.py
Normal file
8
dnscms/contacts/widgets.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from wagtail import hooks
|
||||||
|
|
||||||
|
from .views import contact_entity_chooser_viewset
|
||||||
|
|
||||||
|
|
||||||
|
@hooks.register("register_admin_viewset")
|
||||||
|
def register_viewset():
|
||||||
|
return contact_entity_chooser_viewset
|
@ -28,6 +28,7 @@ INSTALLED_APPS = [
|
|||||||
# adding more cms apps? may want to add it to GRAPPLE as well
|
# adding more cms apps? may want to add it to GRAPPLE as well
|
||||||
"images",
|
"images",
|
||||||
"generic",
|
"generic",
|
||||||
|
"contacts",
|
||||||
"home",
|
"home",
|
||||||
"associations",
|
"associations",
|
||||||
"events",
|
"events",
|
||||||
@ -188,6 +189,7 @@ GRAPPLE = {
|
|||||||
"APPS": [
|
"APPS": [
|
||||||
"images",
|
"images",
|
||||||
"generic",
|
"generic",
|
||||||
|
"contacts",
|
||||||
"home",
|
"home",
|
||||||
"associations",
|
"associations",
|
||||||
"events",
|
"events",
|
||||||
|
22
dnscms/events/migrations/0035_alter_eventpage_body.py
Normal file
22
dnscms/events/migrations/0035_alter_eventpage_body.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:29
|
||||||
|
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('events', '0034_eventpage_organizers_alter_eventorganizerlink_event'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='eventpage',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock())], default=[('paragraph', '')]),
|
||||||
|
),
|
||||||
|
]
|
22
dnscms/generic/migrations/0010_alter_genericpage_body.py
Normal file
22
dnscms/generic/migrations/0010_alter_genericpage_body.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:29
|
||||||
|
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('generic', '0009_alter_genericpage_body'),
|
||||||
|
]
|
||||||
|
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock()), ('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='Bildetekst', 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'))]),
|
||||||
|
),
|
||||||
|
]
|
18
dnscms/images/migrations/0003_alter_customimage_alt.py
Normal file
18
dnscms/images/migrations/0003_alter_customimage_alt.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:29
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('images', '0002_alter_customimage_options_alter_customimage_alt'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='customimage',
|
||||||
|
name='alt',
|
||||||
|
field=models.CharField(blank=True, help_text=('Er ikke synlig på nettsiden, men leses opp for de som bruker skjermlesere. Viktig for SEO og tilgjengelighet. Beskriv det du ser i bildet som til en blind person. F.eks. "Logo for Superforeningen" eller "Stemningsbilde fra konserten med Eminem"',), max_length=512, verbose_name='Alternativ tekst'),
|
||||||
|
),
|
||||||
|
]
|
22
dnscms/news/migrations/0005_alter_newspage_body.py
Normal file
22
dnscms/news/migrations/0005_alter_newspage_body.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:29
|
||||||
|
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('news', '0004_alter_newspage_body'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='newspage',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock())], default=[('paragraph', '')]),
|
||||||
|
),
|
||||||
|
]
|
22
dnscms/venues/migrations/0006_alter_venuepage_body.py
Normal file
22
dnscms/venues/migrations/0006_alter_venuepage_body.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-24 00:29
|
||||||
|
|
||||||
|
import dnscms.blocks
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('venues', '0005_alter_venuepage_body'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='venuepage',
|
||||||
|
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='Bildetekst', 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_navigation', dnscms.blocks.PageSectionNavigationBlock())], default=[('paragraph', '')]),
|
||||||
|
),
|
||||||
|
]
|
22
web/src/app/kontakt-test/page.tsx
Normal file
22
web/src/app/kontakt-test/page.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { graphql } from "@/gql";
|
||||||
|
//import { NewsFragment } from "@/gql/graphql";
|
||||||
|
import { getClient } from "@/app/client";
|
||||||
|
import { NewsList } from "@/components/news/NewsList";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { PageHeader } from "@/components/general/PageHeader";
|
||||||
|
import { PersonSection } from "@/components/people/PersonSection";
|
||||||
|
import { ContactInfo } from "@/components/contact/ContactInfo";
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
return (
|
||||||
|
<main className="site-main" id="main">
|
||||||
|
<PageHeader
|
||||||
|
heading="Kontakt"
|
||||||
|
lead="Her er info om hvordan du kan kontakte oss og sånt."
|
||||||
|
/>
|
||||||
|
<ContactInfo />
|
||||||
|
<PersonSection heading="Styret" />
|
||||||
|
<PersonSection heading="Administrasjonen" />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
@ -1,22 +1,40 @@
|
|||||||
import { graphql } from "@/gql";
|
import { graphql } from "@/gql";
|
||||||
//import { NewsFragment } from "@/gql/graphql";
|
import { ContactFragment, ContactIndexFragment } from "@/gql/graphql";
|
||||||
import { getClient } from "@/app/client";
|
import { getClient } from "@/app/client";
|
||||||
import { NewsList } from "@/components/news/NewsList";
|
import { ContactList } from "@/components/Contacts/ContactList";
|
||||||
|
import { Blocks } from "@/components/blocks/Blocks";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { PageHeader } from "@/components/general/PageHeader";
|
import { PageHeader } from "@/components/general/PageHeader";
|
||||||
import { PersonSection } from "@/components/people/PersonSection";
|
|
||||||
import { ContactInfo } from "@/components/contact/ContactInfo";
|
const ContactIndexDefinition = graphql(`
|
||||||
|
fragment ContactIndex on ContactIndex {
|
||||||
|
... on ContactIndex {
|
||||||
|
title
|
||||||
|
lead
|
||||||
|
body {
|
||||||
|
...Blocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
|
const contactQuery = graphql(`
|
||||||
|
query contacts {
|
||||||
|
contactIndex {
|
||||||
|
... on ContactIndex {
|
||||||
|
...ContactIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const { data, error } = await getClient().query(contactQuery, {});
|
||||||
|
const index = (data?.contactIndex ?? []) as ContactIndexFragment;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="site-main" id="main">
|
<main className="site-main" id="main">
|
||||||
<PageHeader
|
<PageHeader heading={index.title} lead={index.lead} />
|
||||||
heading="Kontakt"
|
{index.body && <Blocks blocks={index.body} />}
|
||||||
lead="Her er info om hvordan du kan kontakte oss og sånt."
|
|
||||||
/>
|
|
||||||
<ContactInfo />
|
|
||||||
<PersonSection heading="Styret" />
|
|
||||||
<PersonSection heading="Administrasjonen" />
|
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ import { ImageSliderBlock } from "./ImageSliderBlock";
|
|||||||
import { HorizontalRuleBlock } from "./HorizontalRuleBlock";
|
import { HorizontalRuleBlock } from "./HorizontalRuleBlock";
|
||||||
import { FeaturedBlock } from "./FeaturedBlock";
|
import { FeaturedBlock } from "./FeaturedBlock";
|
||||||
import { PageSectionBlock, PageSectionNavigationBlock } from "./PageSection";
|
import { PageSectionBlock, PageSectionNavigationBlock } from "./PageSection";
|
||||||
|
import { ContactSectionBlock, ContactSubsectionBlock } from "./ContactSection";
|
||||||
|
import { ContactListBlock } from "./ContactListBlock";
|
||||||
|
import { ContactEntityBlock } from "./ContactEntityBlock";
|
||||||
|
|
||||||
export const Blocks = ({ blocks }: any) => {
|
export const Blocks = ({ blocks }: any) => {
|
||||||
const sections = blocks.filter(
|
const sections = blocks.filter(
|
||||||
@ -33,6 +36,18 @@ export const Blocks = ({ blocks }: any) => {
|
|||||||
case "PageSectionNavigationBlock":
|
case "PageSectionNavigationBlock":
|
||||||
return <PageSectionNavigationBlock sections={sections} />;
|
return <PageSectionNavigationBlock sections={sections} />;
|
||||||
break;
|
break;
|
||||||
|
case "ContactSectionBlock":
|
||||||
|
return <ContactSectionBlock block={block} />;
|
||||||
|
break;
|
||||||
|
case "ContactSubsectionBlock":
|
||||||
|
return <ContactSubsectionBlock block={block} />;
|
||||||
|
break;
|
||||||
|
case "ContactListBlock":
|
||||||
|
return <ContactListBlock block={block} />;
|
||||||
|
break;
|
||||||
|
case "ContactEntityBlock":
|
||||||
|
return <ContactEntityBlock block={block} />;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return <div>Unsupported block type {block.blockType}</div>;
|
return <div>Unsupported block type {block.blockType}</div>;
|
||||||
console.log("unsupported block", block);
|
console.log("unsupported block", block);
|
||||||
|
50
web/src/components/blocks/ContactEntityBlock.tsx
Normal file
50
web/src/components/blocks/ContactEntityBlock.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { ContactEntityBlock as ContactEntityBlockType } from "@/gql/graphql";
|
||||||
|
import styles from "./contactEntityBlock.module.scss";
|
||||||
|
import { formatNorwegianPhoneNumber, formatPhoneE164 } from "@/lib/common";
|
||||||
|
|
||||||
|
export const ContactEntityBlock = ({
|
||||||
|
block,
|
||||||
|
}: {
|
||||||
|
block: ContactEntityBlockType;
|
||||||
|
}) => {
|
||||||
|
// TODO: image
|
||||||
|
|
||||||
|
const contact = block?.contactEntity;
|
||||||
|
|
||||||
|
if (!contact) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const phoneE164 = contact.phoneNumber && formatPhoneE164(contact.phoneNumber);
|
||||||
|
const phoneFormatted = phoneE164 && formatNorwegianPhoneNumber(phoneE164);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className={styles.contactItem}>
|
||||||
|
<div className={styles.image}></div>
|
||||||
|
<div className={styles.text}>
|
||||||
|
<h1 className={styles.name}>{contact.name}</h1>
|
||||||
|
{contact.title && <p className={styles.role}>{contact.title}</p>}
|
||||||
|
{(contact.email || phoneE164) && (
|
||||||
|
<ul className={styles.contact}>
|
||||||
|
{contact.email && (
|
||||||
|
<li>
|
||||||
|
<span className={styles.icon}>✉ </span>
|
||||||
|
<a href={`mailto:${contact.email}`} target="_blank">
|
||||||
|
{contact.email}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{phoneE164 && (
|
||||||
|
<li>
|
||||||
|
<span className={styles.icon}>☎ </span>
|
||||||
|
<a href={`tel:${phoneE164}`} target="_blank">
|
||||||
|
{phoneFormatted}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
15
web/src/components/blocks/ContactListBlock.tsx
Normal file
15
web/src/components/blocks/ContactListBlock.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { ContactListBlock as ContactListBlockType } from "@/gql/graphql";
|
||||||
|
import styles from "./contactListBlock.module.scss";
|
||||||
|
import { Blocks } from "./Blocks";
|
||||||
|
|
||||||
|
export const ContactListBlock = ({
|
||||||
|
block,
|
||||||
|
}: {
|
||||||
|
block: ContactListBlockType;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ul className={styles.contactList}>
|
||||||
|
<Blocks blocks={block.items} />
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
};
|
41
web/src/components/blocks/ContactSection.tsx
Normal file
41
web/src/components/blocks/ContactSection.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { ContactSectionBlock as ContactSectionBlockType } from "@/gql/graphql";
|
||||||
|
import styles from "./contactSection.module.scss";
|
||||||
|
import { Blocks } from "./Blocks";
|
||||||
|
|
||||||
|
export const ContactSectionBlock = ({
|
||||||
|
block,
|
||||||
|
}: {
|
||||||
|
block: ContactSectionBlockType;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<section className={styles.contactSection}>
|
||||||
|
<h2 className={styles.heading}>{block.title}</h2>
|
||||||
|
{block.text && (
|
||||||
|
<p
|
||||||
|
className={styles.intro}
|
||||||
|
dangerouslySetInnerHTML={{ __html: block.text }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Blocks blocks={block.blocks} />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ContactSubsectionBlock = ({
|
||||||
|
block,
|
||||||
|
}: {
|
||||||
|
block: ContactSectionBlockType;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<section className={styles.contactSubsection}>
|
||||||
|
<h3 className={styles.heading}>{block.title}</h3>
|
||||||
|
{block.text && (
|
||||||
|
<p
|
||||||
|
className={styles.intro}
|
||||||
|
dangerouslySetInnerHTML={{ __html: block.text }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Blocks blocks={block.blocks} />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
43
web/src/components/blocks/contactEntityBlock.module.scss
Normal file
43
web/src/components/blocks/contactEntityBlock.module.scss
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
.contactItem {
|
||||||
|
position: relative;
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
flex: none;
|
||||||
|
width: 7rem;
|
||||||
|
height: 7rem;
|
||||||
|
background: var(--color-placeholder);
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name,
|
||||||
|
.role {
|
||||||
|
font-size: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.role {
|
||||||
|
font-family: var(--font-serif);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact {
|
||||||
|
list-style: none;
|
||||||
|
margin: .6rem 0;
|
||||||
|
font-size: var(--font-size-caption);
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: var(--size-icon);
|
||||||
|
text-align: center;
|
||||||
|
margin-right: .4rem;
|
||||||
|
}
|
19
web/src/components/blocks/contactListBlock.module.scss
Normal file
19
web/src/components/blocks/contactListBlock.module.scss
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.contactList {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
column-gap: var(--spacing-gap-column);
|
||||||
|
row-gap: var(--spacing-gap-row);
|
||||||
|
padding-bottom: var(--spacing-section-bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 740px) {
|
||||||
|
.contactList {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1340px) {
|
||||||
|
.contactList {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
}
|
26
web/src/components/blocks/contactSection.module.scss
Normal file
26
web/src/components/blocks/contactSection.module.scss
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
.contactSection {
|
||||||
|
background: var(--color-background-secondary);
|
||||||
|
margin: calc(var(--spacing-sitepadding-block) * 2)
|
||||||
|
calc(var(--spacing-sitepadding-inline) * -1);
|
||||||
|
padding: var(--spacing-sitepadding-block) var(--spacing-sitepadding-inline);
|
||||||
|
|
||||||
|
+ .contactSection {
|
||||||
|
margin-top: calc(var(--spacing-sitepadding-block) * -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(even) {
|
||||||
|
background: var(--color-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
margin: 0 0 1.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
@ -25,15 +25,18 @@ const documents = {
|
|||||||
"\n fragment AssociationIndex on AssociationIndex {\n ... on AssociationIndex {\n title\n lead\n body {\n ...Blocks\n }\n }\n }\n": types.AssociationIndexFragmentDoc,
|
"\n fragment AssociationIndex on AssociationIndex {\n ... on AssociationIndex {\n title\n lead\n body {\n ...Blocks\n }\n }\n }\n": types.AssociationIndexFragmentDoc,
|
||||||
"\n fragment Association on AssociationPage {\n __typename\n id\n slug\n title\n excerpt\n body {\n ...Blocks\n }\n logo {\n url\n width\n height\n }\n associationType\n websiteUrl\n }\n": types.AssociationFragmentDoc,
|
"\n fragment Association on AssociationPage {\n __typename\n id\n slug\n title\n excerpt\n body {\n ...Blocks\n }\n logo {\n url\n width\n height\n }\n associationType\n websiteUrl\n }\n": types.AssociationFragmentDoc,
|
||||||
"\n query allAssociations {\n index: associationIndex {\n ... on AssociationIndex {\n ...AssociationIndex\n }\n }\n associations: pages(contentType: \"associations.AssociationPage\") {\n ... on AssociationPage {\n ...Association\n }\n }\n }\n ": types.AllAssociationsDocument,
|
"\n query allAssociations {\n index: associationIndex {\n ... on AssociationIndex {\n ...AssociationIndex\n }\n }\n associations: pages(contentType: \"associations.AssociationPage\") {\n ... on AssociationPage {\n ...Association\n }\n }\n }\n ": types.AllAssociationsDocument,
|
||||||
|
"\n fragment ContactIndex on ContactIndex {\n ... on ContactIndex {\n title\n lead\n body {\n ...Blocks\n }\n }\n }\n": types.ContactIndexFragmentDoc,
|
||||||
|
"\n query contacts {\n contactIndex {\n ... on ContactIndex {\n ...ContactIndex\n }\n }\n }\n ": types.ContactsDocument,
|
||||||
"\n query allVenueSlugs {\n pages(contentType: \"venues.VenuePage\") {\n id\n slug\n }\n }\n ": types.AllVenueSlugsDocument,
|
"\n query allVenueSlugs {\n pages(contentType: \"venues.VenuePage\") {\n id\n slug\n }\n }\n ": types.AllVenueSlugsDocument,
|
||||||
"\n query venueBySlug($slug: String!) {\n venue: page(contentType: \"venues.VenuePage\", slug: $slug) {\n ... on VenuePage {\n ...Venue\n }\n }\n }\n ": types.VenueBySlugDocument,
|
"\n query venueBySlug($slug: String!) {\n venue: page(contentType: \"venues.VenuePage\", slug: $slug) {\n ... on VenuePage {\n ...Venue\n }\n }\n }\n ": types.VenueBySlugDocument,
|
||||||
"\n fragment Venue on VenuePage {\n __typename\n id\n slug\n title\n body {\n ...Blocks\n }\n featuredImage {\n ...Image\n }\n showAsBookable\n floor\n preposition\n capabilityAudio\n capabilityAudioVideo\n capabilityBar\n capabilityLighting\n capacityLegal\n capacityStanding\n capacitySitting\n }\n": types.VenueFragmentDoc,
|
"\n fragment Venue on VenuePage {\n __typename\n id\n slug\n title\n body {\n ...Blocks\n }\n featuredImage {\n ...Image\n }\n showAsBookable\n floor\n preposition\n capabilityAudio\n capabilityAudioVideo\n capabilityBar\n capabilityLighting\n capacityLegal\n capacityStanding\n capacitySitting\n }\n": types.VenueFragmentDoc,
|
||||||
"\n query allVenues {\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n ...Venue\n }\n }\n }\n ": types.AllVenuesDocument,
|
"\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 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: 4) {\n ... on NewsPage {\n ...News\n }\n }\n }\n ": types.HomeDocument,
|
"\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: 4) {\n ... on NewsPage {\n ...News\n }\n }\n }\n ": types.HomeDocument,
|
||||||
"\n fragment OneLevelOfBlocks 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.OneLevelOfBlocksFragmentDoc,
|
"\n fragment OneLevelOfBlocks 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 ... on ContactListBlock {\n items {\n blockType\n ... on ContactEntityBlock {\n contactEntity {\n ...ContactEntity\n }\n }\n }\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": types.BlocksFragmentDoc,
|
"\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ... on ContactSectionBlock {\n title\n text\n blocks {\n ... on ContactSubsectionBlock {\n title\n text\n blocks {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\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 Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n": types.ImageFragmentDoc,
|
||||||
|
"\n fragment ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n": types.ContactEntityFragmentDoc,
|
||||||
"\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 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,
|
"\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,
|
||||||
"\n fragment News on NewsPage {\n __typename\n id\n slug\n title\n firstPublishedAt\n excerpt\n featuredImage {\n ...Image\n }\n body {\n ...Blocks\n }\n }\n": types.NewsFragmentDoc,
|
"\n fragment News on NewsPage {\n __typename\n id\n slug\n title\n firstPublishedAt\n excerpt\n featuredImage {\n ...Image\n }\n body {\n ...Blocks\n }\n }\n": types.NewsFragmentDoc,
|
||||||
@ -103,6 +106,14 @@ export function graphql(source: "\n fragment Association on AssociationPage {\n
|
|||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query allAssociations {\n index: associationIndex {\n ... on AssociationIndex {\n ...AssociationIndex\n }\n }\n associations: pages(contentType: \"associations.AssociationPage\") {\n ... on AssociationPage {\n ...Association\n }\n }\n }\n "): (typeof documents)["\n query allAssociations {\n index: associationIndex {\n ... on AssociationIndex {\n ...AssociationIndex\n }\n }\n associations: pages(contentType: \"associations.AssociationPage\") {\n ... on AssociationPage {\n ...Association\n }\n }\n }\n "];
|
export function graphql(source: "\n query allAssociations {\n index: associationIndex {\n ... on AssociationIndex {\n ...AssociationIndex\n }\n }\n associations: pages(contentType: \"associations.AssociationPage\") {\n ... on AssociationPage {\n ...Association\n }\n }\n }\n "): (typeof documents)["\n query allAssociations {\n index: associationIndex {\n ... on AssociationIndex {\n ...AssociationIndex\n }\n }\n associations: pages(contentType: \"associations.AssociationPage\") {\n ... on AssociationPage {\n ...Association\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 ContactIndex on ContactIndex {\n ... on ContactIndex {\n title\n lead\n body {\n ...Blocks\n }\n }\n }\n"): (typeof documents)["\n fragment ContactIndex on ContactIndex {\n ... on ContactIndex {\n title\n lead\n body {\n ...Blocks\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 query contacts {\n contactIndex {\n ... on ContactIndex {\n ...ContactIndex\n }\n }\n }\n "): (typeof documents)["\n query contacts {\n contactIndex {\n ... on ContactIndex {\n ...ContactIndex\n }\n }\n }\n "];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
@ -130,15 +141,19 @@ 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.
|
* 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 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 OneLevelOfBlocks 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 OneLevelOfBlocks 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 ... on ContactListBlock {\n items {\n blockType\n ... on ContactEntityBlock {\n contactEntity {\n ...ContactEntity\n }\n }\n }\n }\n }\n"): (typeof documents)["\n fragment OneLevelOfBlocks 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 ... on ContactListBlock {\n items {\n blockType\n ... on ContactEntityBlock {\n contactEntity {\n ...ContactEntity\n }\n }\n }\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* 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"): (typeof documents)["\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n }\n"];
|
export function graphql(source: "\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ... on ContactSectionBlock {\n title\n text\n blocks {\n ... on ContactSubsectionBlock {\n title\n text\n blocks {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n }\n"): (typeof documents)["\n fragment Blocks on StreamFieldInterface {\n ... on PageSectionBlock {\n title\n backgroundColor\n body {\n ...OneLevelOfBlocks\n }\n }\n ... on ContactSectionBlock {\n title\n text\n blocks {\n ... on ContactSubsectionBlock {\n title\n text\n blocks {\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n }\n }\n ...OneLevelOfBlocks\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* 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 Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n"): (typeof documents)["\n fragment Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n"];
|
export function graphql(source: "\n fragment Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n"): (typeof documents)["\n fragment Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\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 ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n"): (typeof documents)["\n fragment ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* 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,6 +37,31 @@ export function unique<T>(array: any[]): any[] {
|
|||||||
return Array.from(array.reduce((set, item) => set.add(item), new Set()));
|
return Array.from(array.reduce((set, item) => set.add(item), new Set()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function stripWhitespace(s: string): string {
|
||||||
|
return s.replace(/\s/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatPhoneE164(phone: string): string {
|
||||||
|
phone = stripWhitespace(phone);
|
||||||
|
if (phone.startsWith("+") || phone.length != 8) {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
return "+47" + phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatNorwegianPhoneNumber(phone: string): string {
|
||||||
|
if (phone.startsWith("+47")) {
|
||||||
|
const local = phone.substring(3);
|
||||||
|
if (local.length === 8) {
|
||||||
|
return `${local.substring(0, 3)} ${local.substring(
|
||||||
|
3,
|
||||||
|
5
|
||||||
|
)} ${local.substring(5)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
const OneLevelOfBlocksFragmentDefinition = graphql(`
|
const OneLevelOfBlocksFragmentDefinition = graphql(`
|
||||||
fragment OneLevelOfBlocks on StreamFieldInterface {
|
fragment OneLevelOfBlocks on StreamFieldInterface {
|
||||||
id
|
id
|
||||||
@ -90,6 +115,16 @@ const OneLevelOfBlocksFragmentDefinition = graphql(`
|
|||||||
...Image
|
...Image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
... on ContactListBlock {
|
||||||
|
items {
|
||||||
|
blockType
|
||||||
|
... on ContactEntityBlock {
|
||||||
|
contactEntity {
|
||||||
|
...ContactEntity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@ -102,6 +137,20 @@ const BlockFragmentDefinition = graphql(`
|
|||||||
...OneLevelOfBlocks
|
...OneLevelOfBlocks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
... on ContactSectionBlock {
|
||||||
|
title
|
||||||
|
text
|
||||||
|
blocks {
|
||||||
|
... on ContactSubsectionBlock {
|
||||||
|
title
|
||||||
|
text
|
||||||
|
blocks {
|
||||||
|
...OneLevelOfBlocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...OneLevelOfBlocks
|
||||||
|
}
|
||||||
|
}
|
||||||
...OneLevelOfBlocks
|
...OneLevelOfBlocks
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@ -116,3 +165,17 @@ const ImageFragmentDefinition = graphql(`
|
|||||||
attribution
|
attribution
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
const ContactEntityFragmentDefinition = graphql(`
|
||||||
|
fragment ContactEntity on ContactEntity {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
contactType
|
||||||
|
title
|
||||||
|
email
|
||||||
|
phoneNumber
|
||||||
|
image {
|
||||||
|
...Image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
Reference in New Issue
Block a user