web: colocate graphql fragments, unmask where needed, more idiomatic client-preset use
This commit is contained in:
@@ -1,15 +1,26 @@
|
||||
import { AccordionBlock as AccordionBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import { type AccordionBlockFragment } from "@/gql/graphql";
|
||||
import { Blocks } from "./Blocks";
|
||||
import { Accordion } from "@/components/general/Accordion";
|
||||
|
||||
const AccordionBlockFragmentDefinition = graphql(`
|
||||
fragment AccordionBlock on AccordionBlock {
|
||||
heading
|
||||
body {
|
||||
id
|
||||
blockType
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const AccordionBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: AccordionBlockType;
|
||||
block: AccordionBlockFragment;
|
||||
}) => {
|
||||
return (
|
||||
<Accordion heading={block.heading}>
|
||||
<Blocks blocks={block.body} />
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,15 +1,33 @@
|
||||
import { ContactEntityBlock as ContactEntityBlockType } from "@/gql/graphql";
|
||||
import { graphql, unmaskFragment } from "@/gql";
|
||||
import { type ContactEntityBlockFragment } from "@/gql/graphql";
|
||||
import styles from "./contactEntityBlock.module.scss";
|
||||
import { formatNorwegianPhoneNumber, formatPhoneE164 } from "@/lib/common";
|
||||
import {
|
||||
ContactEntityFragmentDefinition,
|
||||
ImageFragmentDefinition,
|
||||
formatNorwegianPhoneNumber,
|
||||
formatPhoneE164,
|
||||
} from "@/lib/common";
|
||||
import { Icon } from "../general/Icon";
|
||||
import { Image } from "../general/Image";
|
||||
|
||||
const ContactEntityBlockFragmentDefinition = graphql(`
|
||||
fragment ContactEntityBlock on ContactEntityBlock {
|
||||
contactEntity {
|
||||
...ContactEntity
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const ContactEntityBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: ContactEntityBlockType;
|
||||
block: ContactEntityBlockFragment;
|
||||
}) => {
|
||||
const contact = block?.contactEntity;
|
||||
const contact = unmaskFragment(
|
||||
ContactEntityFragmentDefinition,
|
||||
block?.contactEntity
|
||||
);
|
||||
const image = unmaskFragment(ImageFragmentDefinition, contact?.image);
|
||||
|
||||
if (!contact) {
|
||||
return <></>;
|
||||
@@ -21,18 +39,18 @@ export const ContactEntityBlock = ({
|
||||
return (
|
||||
<li className={styles.contactItem}>
|
||||
<div className={styles.image}>
|
||||
{!contact.image && (
|
||||
{!image && (
|
||||
<img
|
||||
src="/assets/graphics/portrait-pig.svg"
|
||||
className={styles.portraitPlaceholder}
|
||||
/>
|
||||
)}
|
||||
{contact.image && (
|
||||
{image && (
|
||||
<Image
|
||||
src={contact.image.url}
|
||||
alt={contact.image.alt ?? ""}
|
||||
width={contact.image.width}
|
||||
height={contact.image.height}
|
||||
src={image.url}
|
||||
alt={image.alt ?? ""}
|
||||
width={image.width}
|
||||
height={image.height}
|
||||
sizes="25vw"
|
||||
className={styles.portrait}
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
import { ContactListBlock as ContactListBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import { type ContactListBlockFragment } from "@/gql/graphql";
|
||||
import styles from "./contactListBlock.module.scss";
|
||||
import { Blocks } from "./Blocks";
|
||||
|
||||
const ContactListBlockFragmentDefinition = graphql(`
|
||||
fragment ContactListBlock on ContactListBlock {
|
||||
items {
|
||||
blockType
|
||||
... on ContactEntityBlock {
|
||||
contactEntity {
|
||||
...ContactEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const ContactListBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: ContactListBlockType;
|
||||
block: ContactListBlockFragment;
|
||||
}) => {
|
||||
return (
|
||||
<ul className={styles.contactList}>
|
||||
|
||||
@@ -1,11 +1,37 @@
|
||||
import { ContactSectionBlock as ContactSectionBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import {
|
||||
type ContactSectionBlockFragment,
|
||||
type ContactSubsectionBlockFragment,
|
||||
} from "@/gql/graphql";
|
||||
import styles from "./contactSection.module.scss";
|
||||
import { Blocks } from "./Blocks";
|
||||
|
||||
const ContactSectionBlockFragmentDefinition = graphql(`
|
||||
fragment ContactSectionBlock on ContactSectionBlock {
|
||||
title
|
||||
text
|
||||
blocks {
|
||||
id
|
||||
blockType
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const ContactSubsectionBlockFragmentDefinition = graphql(`
|
||||
fragment ContactSubsectionBlock on ContactSubsectionBlock {
|
||||
title
|
||||
text
|
||||
blocks {
|
||||
id
|
||||
blockType
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const ContactSectionBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: ContactSectionBlockType;
|
||||
block: ContactSectionBlockFragment;
|
||||
}) => {
|
||||
return (
|
||||
<section className={styles.contactSection}>
|
||||
@@ -24,7 +50,7 @@ export const ContactSectionBlock = ({
|
||||
export const ContactSubsectionBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: ContactSectionBlockType;
|
||||
block: ContactSubsectionBlockFragment;
|
||||
}) => {
|
||||
return (
|
||||
<section className={styles.contactSubsection}>
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import { EmbedBlock as EmbedBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import { type EmbedBlockFragment } from "@/gql/graphql";
|
||||
import styles from "./embedBlock.module.scss";
|
||||
|
||||
export const EmbedBlock = ({ block }: { block: EmbedBlockType }) => {
|
||||
const EmbedBlockFragmentDefinition = graphql(`
|
||||
fragment EmbedBlock on EmbedBlock {
|
||||
url
|
||||
embed
|
||||
rawEmbed
|
||||
}
|
||||
`);
|
||||
|
||||
export const EmbedBlock = ({ block }: { block: EmbedBlockFragment }) => {
|
||||
if (!block.embed) {
|
||||
return <></>;
|
||||
}
|
||||
@@ -18,7 +27,7 @@ export const EmbedBlock = ({ block }: { block: EmbedBlockType }) => {
|
||||
*/
|
||||
let embedData: any = {};
|
||||
try {
|
||||
embedData = JSON.parse(block.rawEmbed);
|
||||
embedData = block.rawEmbed ? JSON.parse(block.rawEmbed) : {};
|
||||
} catch (e) {
|
||||
embedData = {};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { FactBoxBlock as FactBoxBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import { type FactBoxBlockFragment } from "@/gql/graphql";
|
||||
import styles from "./factBoxBlock.module.scss";
|
||||
|
||||
type FactBoxBlockTypeWithAlias = FactBoxBlockType & {
|
||||
factBoxBody?: string;
|
||||
};
|
||||
const FactBoxBlockFragmentDefinition = graphql(`
|
||||
fragment FactBoxBlock on FactBoxBlock {
|
||||
backgroundColor
|
||||
factBoxBody: body
|
||||
}
|
||||
`);
|
||||
|
||||
export const FactBoxBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: FactBoxBlockTypeWithAlias;
|
||||
block: FactBoxBlockFragment;
|
||||
}) => {
|
||||
if (!block.factBoxBody) {
|
||||
return <></>;
|
||||
|
||||
@@ -1,22 +1,47 @@
|
||||
import { FeaturedBlock as FeaturedBlockType } from "@/gql/graphql";
|
||||
import { graphql, unmaskFragment } from "@/gql";
|
||||
import { type FeaturedBlockFragment } from "@/gql/graphql";
|
||||
import Link from "next/link";
|
||||
import { Image } from "@/components/general/Image";
|
||||
import { ImageFragmentDefinition } from "@/lib/common";
|
||||
import styles from "./featuredBlock.module.scss";
|
||||
|
||||
// the 'text' field has been aliased to 'featuredBlockText' and i'm
|
||||
// using codegen the wrong way. let's specify the field here and move on
|
||||
type FeaturedBlockTypeWithAlias = FeaturedBlockType & {
|
||||
featuredBlockText: string;
|
||||
};
|
||||
const FeaturedBlockFragmentDefinition = graphql(`
|
||||
fragment FeaturedBlock on FeaturedBlock {
|
||||
title
|
||||
featuredBlockText: text
|
||||
linkText
|
||||
imagePosition
|
||||
backgroundColor
|
||||
featuredPage {
|
||||
contentType
|
||||
pageType
|
||||
url
|
||||
... on EventPage {
|
||||
featuredImage {
|
||||
...Image
|
||||
}
|
||||
}
|
||||
... on NewsPage {
|
||||
featuredImage {
|
||||
...Image
|
||||
}
|
||||
}
|
||||
}
|
||||
featuredImageOverride {
|
||||
...Image
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const FeaturedBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: FeaturedBlockTypeWithAlias;
|
||||
block: FeaturedBlockFragment;
|
||||
}) => {
|
||||
const image = !!block.featuredImageOverride
|
||||
? block.featuredImageOverride
|
||||
: null;
|
||||
const image = unmaskFragment(
|
||||
ImageFragmentDefinition,
|
||||
block.featuredImageOverride
|
||||
);
|
||||
// TODO: fetch image from target page
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import { HorizontalRuleBlock as HorizontalRuleBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import { type HorizontalRuleBlockFragment } from "@/gql/graphql";
|
||||
import { Image } from "@/components/general/Image";
|
||||
import styles from "./horizontalRuleBlock.module.scss";
|
||||
|
||||
const HorizontalRuleBlockFragmentDefinition = graphql(`
|
||||
fragment HorizontalRuleBlock on HorizontalRuleBlock {
|
||||
color
|
||||
}
|
||||
`);
|
||||
|
||||
export const HorizontalRuleBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: HorizontalRuleBlockType;
|
||||
block: HorizontalRuleBlockFragment;
|
||||
}) => {
|
||||
const knownColors = [
|
||||
"deepBrick",
|
||||
|
||||
@@ -1,8 +1,30 @@
|
||||
"use client";
|
||||
import { ImageSliderBlock as ImageSliderBlockType } from "@/gql/graphql";
|
||||
import { graphql, unmaskFragment, type FragmentType } from "@/gql";
|
||||
import { type ImageSliderBlockFragment } from "@/gql/graphql";
|
||||
import { ImageFigure } from "@/components/general/Image";
|
||||
import { ImageFragmentDefinition } from "@/lib/common";
|
||||
import styles from "./imageSliderBlock.module.scss";
|
||||
|
||||
const ImageSliderItemFragmentDefinition = graphql(`
|
||||
fragment ImageSliderItem on ImageSliderItemBlock {
|
||||
image {
|
||||
...Image
|
||||
}
|
||||
text
|
||||
}
|
||||
`);
|
||||
|
||||
export const ImageSliderBlockFragmentDefinition = graphql(`
|
||||
fragment ImageSliderBlock on ImageSliderBlock {
|
||||
images {
|
||||
__typename
|
||||
... on ImageSliderItemBlock {
|
||||
...ImageSliderItem
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
// import swiper modules & styles
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { Pagination, Navigation } from "swiper/modules";
|
||||
@@ -11,17 +33,42 @@ import "swiper/css/pagination";
|
||||
import "swiper/css/navigation";
|
||||
import "./swiper.scss";
|
||||
|
||||
const Slide = ({
|
||||
item: maskedItem,
|
||||
}: {
|
||||
item: FragmentType<typeof ImageSliderItemFragmentDefinition>;
|
||||
}) => {
|
||||
const item = unmaskFragment(ImageSliderItemFragmentDefinition, maskedItem);
|
||||
const image = unmaskFragment(ImageFragmentDefinition, item.image);
|
||||
return (
|
||||
<ImageFigure
|
||||
key={image.id}
|
||||
src={image.url}
|
||||
alt={image.alt ?? ""}
|
||||
width={image.width}
|
||||
height={image.height}
|
||||
attribution={image.attribution}
|
||||
caption={item.text}
|
||||
sizes="100vw"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const ImageSliderBlock = ({
|
||||
block,
|
||||
hero,
|
||||
pageContent
|
||||
pageContent,
|
||||
}: {
|
||||
block: ImageSliderBlockType | any;
|
||||
block: ImageSliderBlockFragment;
|
||||
hero?: boolean;
|
||||
pageContent?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<div className={styles.imageSliderBlock} data-hero={hero} data-pagecontent={pageContent}>
|
||||
<div
|
||||
className={styles.imageSliderBlock}
|
||||
data-hero={hero}
|
||||
data-pagecontent={pageContent}
|
||||
>
|
||||
<Swiper
|
||||
pagination={{
|
||||
type: "fraction",
|
||||
@@ -30,21 +77,16 @@ export const ImageSliderBlock = ({
|
||||
modules={[Pagination, Navigation]}
|
||||
className="mySwiper"
|
||||
>
|
||||
{block.images &&
|
||||
block.images.map((imageItem: any, index: number) => (
|
||||
{block.images?.map((item, index) => {
|
||||
if (item?.__typename !== "ImageSliderItemBlock") {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<SwiperSlide key={index}>
|
||||
<ImageFigure
|
||||
key={imageItem.image.id}
|
||||
src={imageItem.image.url}
|
||||
alt={imageItem.image.alt ?? ""}
|
||||
width={imageItem.image.width}
|
||||
height={imageItem.image.height}
|
||||
attribution={imageItem.image.attribution}
|
||||
caption={imageItem.text}
|
||||
sizes="100vw"
|
||||
/>
|
||||
<Slide item={item} />
|
||||
</SwiperSlide>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</Swiper>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,18 +1,31 @@
|
||||
import { ImageWithTextBlock as ImageWithTextBlockType } from "@/gql/graphql";
|
||||
import { graphql, unmaskFragment } from "@/gql";
|
||||
import { type ImageWithTextBlockFragment } from "@/gql/graphql";
|
||||
import { ImageFigure } from "@/components/general/Image";
|
||||
import { ImageFragmentDefinition } from "@/lib/common";
|
||||
|
||||
const ImageWithTextBlockFragmentDefinition = graphql(`
|
||||
fragment ImageWithTextBlock on ImageWithTextBlock {
|
||||
image {
|
||||
...Image
|
||||
}
|
||||
imageFormat
|
||||
text
|
||||
}
|
||||
`);
|
||||
|
||||
export function ImageWithTextBlock({
|
||||
block,
|
||||
}: {
|
||||
block: ImageWithTextBlockType;
|
||||
block: ImageWithTextBlockFragment;
|
||||
}) {
|
||||
const image = unmaskFragment(ImageFragmentDefinition, block.image);
|
||||
return (
|
||||
<ImageFigure
|
||||
src={block.image.url}
|
||||
alt={block.image.alt ?? ""}
|
||||
width={block.image.width}
|
||||
height={block.image.height}
|
||||
attribution={block.image.attribution}
|
||||
src={image.url}
|
||||
alt={image.alt ?? ""}
|
||||
width={image.width}
|
||||
height={image.height}
|
||||
attribution={image.attribution}
|
||||
caption={block.text}
|
||||
imageFormat={block.imageFormat}
|
||||
/>
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
import { PageSectionBlock as PageSectionBlockType } from "@/gql/graphql";
|
||||
import { graphql } from "@/gql";
|
||||
import { type PageSectionBlockFragment } from "@/gql/graphql";
|
||||
import styles from "./pageSection.module.scss";
|
||||
import { Blocks } from "./Blocks";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { DecorativeIcon } from "../general/Icon";
|
||||
|
||||
const PageSectionBlockFragmentDefinition = graphql(`
|
||||
fragment PageSectionBlock on PageSectionBlock {
|
||||
title
|
||||
backgroundColor
|
||||
icon
|
||||
body {
|
||||
id
|
||||
blockType
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const PageSectionBlock = ({
|
||||
block,
|
||||
}: {
|
||||
block: PageSectionBlockType;
|
||||
block: PageSectionBlockFragment;
|
||||
}) => {
|
||||
const anchor = slugify(block.title);
|
||||
|
||||
@@ -31,7 +44,7 @@ export const PageSectionBlock = ({
|
||||
export const PageSectionNavigationBlock = ({
|
||||
sections,
|
||||
}: {
|
||||
sections: PageSectionBlockType[];
|
||||
sections: PageSectionBlockFragment[];
|
||||
}) => {
|
||||
if (!sections.length) {
|
||||
return <></>;
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import { graphql } from "@/gql";
|
||||
import { type RichTextBlockFragment } from "@/gql/graphql";
|
||||
import styles from "./richTextBlock.module.scss";
|
||||
|
||||
export const RichTextBlock = ({ block }: any) => {
|
||||
const RichTextBlockFragmentDefinition = graphql(`
|
||||
fragment RichTextBlock on RichTextBlock {
|
||||
rawValue
|
||||
value
|
||||
}
|
||||
`);
|
||||
|
||||
export const RichTextBlock = ({ block }: { block: RichTextBlockFragment }) => {
|
||||
return (
|
||||
<div
|
||||
className={styles.richTextBlock}
|
||||
|
||||
Reference in New Issue
Block a user