feat(SW-66, SW-348): search functionality and ui

This commit is contained in:
Simon Emanuelsson
2024-08-28 10:47:57 +02:00
parent b9dbcf7d90
commit af850c90e7
437 changed files with 7663 additions and 9881 deletions
+134 -333
View File
@@ -1,386 +1,187 @@
import { z } from "zod"
import { Lang } from "@/constants/languages"
import { imageVaultAssetSchema } from "../schemas/imageVault"
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
import {
CardsGridEnum,
ContentBlocksTypenameEnum,
DynamicContentComponentEnum,
JoinLoyaltyContactTypenameEnum,
SidebarDynamicComponentEnum,
SidebarTypenameEnum,
} from "@/types/components/content/enums"
import { PageLinkEnum } from "@/types/requests/pageLinks"
import { RTEEmbedsEnum } from "@/types/requests/rte"
cardGridRefsSchema,
cardsGridSchema,
} from "../schemas/blocks/cardsGrid"
import {
contentRefsSchema as blockContentRefsSchema,
contentSchema as blockContentSchema,
} from "../schemas/blocks/content"
import {
dynamicContentRefsSchema,
dynamicContentSchema as blockDynamicContentSchema,
} from "../schemas/blocks/dynamicContent"
import {
shortcutsRefsSchema,
shortcutsSchema,
} from "../schemas/blocks/shortcuts"
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
import {
contentRefsSchema as sidebarContentRefsSchema,
contentSchema as sidebarContentSchema,
} from "../schemas/sidebar/content"
import { dynamicContentSchema as sidebarDynamicContentSchema } from "../schemas/sidebar/dynamicContent"
import {
joinLoyaltyContactRefsSchema,
joinLoyaltyContactSchema,
} from "../schemas/sidebar/joinLoyaltyContact"
import { systemSchema } from "../schemas/system"
import { ContentPageEnum } from "@/types/enums/contentPage"
import { textColsRefsSchema, textColsSchema } from "../schemas/blocks/textCols"
// Block schemas
export const contentPageBlockTextContent = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksContent),
content: z.object({
content: z.object({
embedded_itemsConnection: z.object({
edges: z.array(z.any()),
totalCount: z.number(),
}),
json: z.any(),
}),
}),
})
export const contentPageCards = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.CardsGrid),
})
.merge(cardsGridSchema)
export const contentPageShortcuts = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksShortcuts),
shortcuts: z.object({
title: z.string().nullable(),
preamble: z.string().nullable(),
shortcuts: z.array(
z.object({
text: z.string().optional(),
openInNewTab: z.boolean(),
url: z.string(),
title: z.string(),
})
),
}),
})
export const contentPageContent = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.Content),
})
.merge(blockContentSchema)
export const contentPageDynamicContent = z.object({
__typename: z.literal(
ContentBlocksTypenameEnum.ContentPageBlocksDynamicContent
),
dynamic_content: z.object({
title: z.string().nullable(),
subtitle: z.string().nullable(),
component: z.nativeEnum(DynamicContentComponentEnum),
link: z
.object({
text: z.string(),
href: z.string(),
})
.optional(),
}),
})
export const contentPageDynamicContent = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.DynamicContent),
})
.merge(blockDynamicContentSchema)
export const cardBlock = z.object({
__typename: z.literal(CardsGridEnum.Card),
isContentCard: z.boolean(),
heading: z.string().nullable(),
body_text: z.string().nullable(),
background_image: z.any(),
scripted_top_title: z.string().nullable(),
primaryButton: z
.object({
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.optional(),
secondaryButton: z
.object({
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.optional(),
sidePeekButton: z
.object({
title: z.string(),
})
.optional(),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
}),
})
export const loyaltyCardBlock = z.object({
__typename: z.literal(CardsGridEnum.LoyaltyCard),
heading: z.string().nullable(),
body_text: z.string().nullable(),
image: z.any(),
link: z
.object({
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.optional(),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
}),
})
const contentPageCardsItems = z.discriminatedUnion("__typename", [
loyaltyCardBlock,
cardBlock,
])
export const contentPageCards = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksCardsGrid),
cards_grid: z.object({
title: z.string().nullable(),
preamble: z.string().nullable(),
layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]),
theme: z.enum(["one", "two", "three"]).nullable(),
cards: z.array(contentPageCardsItems),
}),
})
export const contentPageShortcuts = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.Shortcuts),
})
.merge(shortcutsSchema)
export const contentPageTextCols = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksTextCols),
text_cols: z.object({
columns: z.array(
z.object({
title: z.string(),
text: z.object({
json: z.any(),
embedded_itemsConnection: z.object({
edges: z.array(z.any()),
totalCount: z.number(),
}),
}),
})
),
}),
})
const contentPageBlockItem = z.discriminatedUnion("__typename", [
contentPageBlockTextContent,
__typename: z.literal(ContentPageEnum.ContentStack.blocks.TextCols),
}).merge(textColsSchema)
export const blocksSchema = z.discriminatedUnion("__typename", [
contentPageCards,
contentPageContent,
contentPageDynamicContent,
contentPageShortcuts,
contentPageTextCols,
])
export const contentPageSidebarTextContent = z.object({
__typename: z.literal(SidebarTypenameEnum.ContentPageSidebarContent),
content: z.object({
content: z.object({
embedded_itemsConnection: z.object({
edges: z.array(z.any()),
totalCount: z.number(),
}),
json: z.any(),
}),
}),
})
export const contentPageSidebarContent = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.sidebar.Content),
})
.merge(sidebarContentSchema)
export const contentPageJoinLoyaltyContact = z.object({
__typename: z.literal(
SidebarTypenameEnum.ContentPageSidebarJoinLoyaltyContact
),
join_loyalty_contact: z.object({
title: z.string().nullable(),
preamble: z.string().nullable(),
button: z
.object({
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.nullable(),
contact: z.array(
z.object({
__typename: z.literal(
JoinLoyaltyContactTypenameEnum.ContentPageSidebarJoinLoyaltyContactBlockContactContact
),
contact: z.object({
display_text: z.string().nullable(),
contact_field: z.string(),
footnote: z.string().nullable(),
}),
})
export const contentPageSidebarDynamicContent = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.sidebar.DynamicContent),
})
.merge(sidebarDynamicContentSchema)
export const contentPageJoinLoyaltyContact = z
.object({
__typename: z.literal(
ContentPageEnum.ContentStack.sidebar.JoinLoyaltyContact
),
}),
})
})
.merge(joinLoyaltyContactSchema)
export const contentPageSidebarDynamicContent = z.object({
__typename: z.literal(SidebarTypenameEnum.ContentPageSidebarDynamicContent),
dynamic_content: z.object({
component: z.nativeEnum(SidebarDynamicComponentEnum),
}),
})
const contentPageSidebarItem = z.discriminatedUnion("__typename", [
contentPageSidebarTextContent,
export const sidebarSchema = z.discriminatedUnion("__typename", [
contentPageSidebarContent,
contentPageSidebarDynamicContent,
contentPageJoinLoyaltyContact,
])
// Content Page Schema and types
export const validateContentPageSchema = z.object({
export const contentPageSchema = z.object({
content_page: z.object({
hero_image: tempImageVaultAssetSchema,
blocks: discriminatedUnionArray(blocksSchema.options).nullable(),
sidebar: discriminatedUnionArray(sidebarSchema.options).nullable(),
title: z.string(),
header: z.object({
heading: z.string(),
preamble: z.string(),
}),
hero_image: imageVaultAssetSchema.nullable().optional(),
blocks: z.array(contentPageBlockItem).nullable(),
sidebar: z.array(contentPageSidebarItem).nullable(),
system: z.object({
uid: z.string(),
locale: z.nativeEnum(Lang),
created_at: z.string(),
updated_at: z.string(),
}),
}),
})
const pageConnectionRefs = z.object({
edges: z.array(
z.object({
node: z.object({
__typename: z.nativeEnum(PageLinkEnum),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
}),
})
),
})
const rteConnectionRefs = z.object({
edges: z.array(
z.object({
node: z.object({
__typename: z.nativeEnum(RTEEmbedsEnum),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
}),
})
),
})
const cardBlockRefs = z.object({
__typename: z.literal(CardsGridEnum.Card),
primary_button: z
.object({
linkConnection: pageConnectionRefs,
})
.nullable(),
secondary_button: z
.object({
linkConnection: pageConnectionRefs,
})
.nullable(),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
})
const loyaltyCardBlockRefs = z.object({
__typename: z.literal(CardsGridEnum.LoyaltyCard),
link: z
.object({
linkConnection: pageConnectionRefs,
})
.nullable(),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
})
const cardGridCardsRef = z.discriminatedUnion("__typename", [
loyaltyCardBlockRefs,
cardBlockRefs,
])
const contentPageBlockTextContentRefs = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksContent),
content: z.object({
content: z.object({
embedded_itemsConnection: rteConnectionRefs,
}),
}),
})
const contentPageCardsRefs = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksCardsGrid),
cards_grid: z.object({
cardConnection: z.object({
edges: z.array(
z.object({
node: cardGridCardsRef,
})
),
}),
}),
})
const contentPageShortcutsRefs = z.object({
__typename: z.literal(ContentBlocksTypenameEnum.ContentPageBlocksShortcuts),
shortcuts: z.object({
shortcuts: z.array(
system: systemSchema.merge(
z.object({
linkConnection: rteConnectionRefs,
created_at: z.string(),
updated_at: z.string(),
})
),
}),
})
const contentPageDynamicContentRefs = z.object({
__typename: z.literal(
ContentBlocksTypenameEnum.ContentPageBlocksDynamicContent
),
dynamic_content: z.object({
link: z.object({
pageConnection: pageConnectionRefs,
}),
}),
})
/** REFS */
const contentPageCardsRefs = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.CardsGrid),
})
.merge(cardGridRefsSchema)
const contentPageBlockContentRefs = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.Content),
})
.merge(blockContentRefsSchema)
const contentPageDynamicContentRefs = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.DynamicContent),
})
.merge(dynamicContentRefsSchema)
const contentPageShortcutsRefs = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.Shortcuts),
})
.merge(shortcutsRefsSchema)
const contentPageTextColsRefs = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.blocks.TextCols),
})
.merge(textColsRefsSchema)
const contentPageBlockRefsItem = z.discriminatedUnion("__typename", [
contentPageBlockTextContentRefs,
contentPageBlockContentRefs,
contentPageShortcutsRefs,
contentPageCardsRefs,
contentPageDynamicContentRefs,
contentPageTextColsRefs,
])
const contentPageSidebarTextContentRef = z.object({
__typename: z.literal(SidebarTypenameEnum.ContentPageSidebarContent),
content: z.object({
content: z.object({
embedded_itemsConnection: rteConnectionRefs,
}),
}),
})
const contentPageSidebarContentRef = z
.object({
__typename: z.literal(ContentPageEnum.ContentStack.sidebar.Content),
})
.merge(sidebarContentRefsSchema)
const contentPageSidebarJoinLoyaltyContactRef = z.object({
__typename: z.literal(
SidebarTypenameEnum.ContentPageSidebarJoinLoyaltyContact
),
join_loyalty_contact: z.object({
button: z
.object({
linkConnection: pageConnectionRefs,
})
.nullable(),
}),
})
const contentPageSidebarJoinLoyaltyContactRef = z
.object({
__typename: z.literal(
ContentPageEnum.ContentStack.sidebar.JoinLoyaltyContact
),
})
.merge(joinLoyaltyContactRefsSchema)
const contentPageSidebarRefsItem = z.discriminatedUnion("__typename", [
contentPageSidebarTextContentRef,
contentPageSidebarContentRef,
contentPageSidebarJoinLoyaltyContactRef,
])
export const validateContentPageRefsSchema = z.object({
export const contentPageRefsSchema = z.object({
content_page: z.object({
blocks: z.array(contentPageBlockRefsItem).nullable(),
sidebar: z.array(contentPageSidebarRefsItem).nullable(),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
blocks: discriminatedUnionArray(
contentPageBlockRefsItem.options
).nullable(),
sidebar: discriminatedUnionArray(
contentPageSidebarRefsItem.options
).nullable(),
system: systemSchema,
}),
})
+20 -160
View File
@@ -1,49 +1,36 @@
import { Lang } from "@/constants/languages"
import { GetContentPage } from "@/lib/graphql/Query/ContentPage.graphql"
import { GetContentPage } from "@/lib/graphql/Query/ContentPage/ContentPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import { makeImageVaultImage } from "@/utils/imageVault"
import { removeMultipleSlashes } from "@/utils/url"
import { removeEmptyObjects } from "../../utils"
import { validateContentPageSchema } from "./output"
import { contentPageSchema } from "./output"
import {
fetchContentPageRefs,
generatePageTags,
getContentPageCounter,
makeButtonObject,
validateContentPageRefs,
} from "./utils"
import {
CardsGridEnum,
ContentBlocksTypenameEnum,
SidebarTypenameEnum,
} from "@/types/components/content/enums"
import {
TrackingChannelEnum,
TrackingSDKPageData,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import {
Block,
ContentPage,
ContentPageDataRaw,
Sidebar,
} from "@/types/trpc/routers/contentstack/contentPage"
import type { GetContentPageSchema } from "@/types/trpc/routers/contentstack/contentPage"
export const contentPageQueryRouter = router({
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const { lang, uid } = ctx
const cleanedRefsData = await fetchContentPageRefs(lang, uid)
const validatedRefsData = validateContentPageRefs(
cleanedRefsData,
const contentPageRefsData = await fetchContentPageRefs(lang, uid)
const contentPageRefs = validateContentPageRefs(
contentPageRefsData,
lang,
uid
)
const tags = generatePageTags(validatedRefsData, lang)
if (!contentPageRefs) {
return null
}
const tags = generatePageTags(contentPageRefs, lang)
getContentPageCounter.add(1, { lang, uid })
console.info(
@@ -53,7 +40,7 @@ export const contentPageQueryRouter = router({
})
)
const response = await request<ContentPageDataRaw>(
const response = await request<GetContentPageSchema>(
GetContentPage,
{ locale: lang, uid },
{
@@ -64,154 +51,27 @@ export const contentPageQueryRouter = router({
}
)
const { content_page } = removeEmptyObjects(response.data)
if (!content_page) {
throw notFound(response)
}
const contentPage = contentPageSchema.safeParse(response.data)
const processedBlocks = content_page.blocks
? content_page.blocks.map((block: any) => {
switch (block.__typename) {
case ContentBlocksTypenameEnum.ContentPageBlocksContent:
return block
case ContentBlocksTypenameEnum.ContentPageBlocksShortcuts:
return {
...block,
shortcuts: {
...block.shortcuts,
shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({
text: shortcut.text,
openInNewTab: shortcut.open_in_new_tab,
...shortcut.linkConnection.edges[0].node,
url:
shortcut.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes(
`/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}`
),
})),
},
}
case ContentBlocksTypenameEnum.ContentPageBlocksCardsGrid:
return {
...block,
cards_grid: {
...block.cards_grid,
cards: block.cards_grid.cardConnection.edges.map(
({ node: card }: { node: any }) => {
switch (card.__typename) {
case CardsGridEnum.Card:
return {
...card,
isContentCard: !!card.is_content_card,
backgroundImage: makeImageVaultImage(
card.background_image
),
primaryButton: card.has_primary_button
? makeButtonObject(card.primary_button)
: undefined,
secondaryButton: card.has_secondary_button
? makeButtonObject(card.secondary_button)
: undefined,
sidePeekButton:
card.has_sidepeek_button ||
!!card.sidepeek_button?.call_to_action_text
? {
title:
card.sidepeek_button.call_to_action_text,
}
: undefined,
}
case CardsGridEnum.LoyaltyCard:
return {
...card,
image: makeImageVaultImage(card.image),
link: makeButtonObject(card.link),
}
}
}
),
},
}
case ContentBlocksTypenameEnum.ContentPageBlocksDynamicContent:
return {
...block,
dynamic_content: {
...block.dynamic_content,
link: block.dynamic_content.link.pageConnection.edges.length
? {
text: block.dynamic_content.link.text,
href: removeMultipleSlashes(
`/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}`
),
title:
block.dynamic_content.link.pageConnection.edges[0]
.node.title,
}
: undefined,
},
}
default:
return block
}
})
: null
const sidebar = response.data.content_page.sidebar
? response.data.content_page.sidebar.map((item: any) => {
switch (item.__typename) {
case SidebarTypenameEnum.ContentPageSidebarJoinLoyaltyContact:
return {
...item,
join_loyalty_contact: {
...item.join_loyalty_contact,
button: makeButtonObject(item.join_loyalty_contact.button),
},
}
default:
return item
}
})
: null
const heroImage = makeImageVaultImage(content_page.hero_image)
const validatedContentPage = validateContentPageSchema.safeParse({
content_page: {
...content_page,
blocks: processedBlocks,
sidebar,
hero_image: heroImage,
},
})
if (!validatedContentPage.success) {
if (!contentPage.success) {
console.error(
`Failed to validate Contentpage Data - (lang: ${lang}, uid: ${uid})`
)
console.error(validatedContentPage.error?.format())
console.error(contentPage.error?.format())
return null
}
const { hero_image, blocks, ...restContentPage } =
validatedContentPage.data.content_page
const contentPage: ContentPage = {
...restContentPage,
heroImage,
blocks: blocks as Block[],
sidebar: sidebar as Sidebar[],
}
const tracking: TrackingSDKPageData = {
pageId: contentPage.system.uid,
lang: contentPage.system.locale as Lang,
publishedDate: contentPage.system.updated_at,
createdDate: contentPage.system.created_at,
pageId: contentPage.data.content_page.system.uid,
lang: contentPage.data.content_page.system.locale as Lang,
publishedDate: contentPage.data.content_page.system.updated_at,
createdDate: contentPage.data.content_page.system.created_at,
channel: TrackingChannelEnum["static-content-page"],
pageType: "staticcontentpage",
}
return {
contentPage,
contentPage: contentPage.data.content_page,
tracking,
}
}),
@@ -1,20 +1,20 @@
import { metrics } from "@opentelemetry/api"
import { Lang } from "@/constants/languages"
import { GetContentPageRefs } from "@/lib/graphql/Query/ContentPage.graphql"
import { GetContentPageRefs } from "@/lib/graphql/Query/ContentPage/ContentPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { generateTag, generateTags } from "@/utils/generateTag"
import { removeMultipleSlashes } from "@/utils/url"
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
import { removeEmptyObjects } from "../../utils"
import { validateContentPageRefsSchema } from "./output"
import { contentPageRefsSchema } from "./output"
import { ContentBlocksTypenameEnum } from "@/types/components/content/enums"
import { Edges } from "@/types/requests/utils/edges"
import { NodeRefs } from "@/types/requests/utils/refs"
import { ContentPageRefsDataRaw } from "@/types/trpc/routers/contentstack/contentPage"
import { ContentPageEnum } from "@/types/enums/contentPage"
import { System } from "@/types/requests/system"
import {
ContentPageRefs,
GetContentPageRefsSchema,
} from "@/types/trpc/routers/contentstack/contentPage"
const meter = metrics.getMeter("trpc.contentPage")
// OpenTelemetry metrics: ContentPage
@@ -41,10 +41,15 @@ export async function fetchContentPageRefs(lang: Lang, uid: string) {
query: { lang, uid },
})
)
const refsResponse = await request<ContentPageRefsDataRaw>(
const refsResponse = await request<GetContentPageRefsSchema>(
GetContentPageRefs,
{ locale: lang, uid },
{ cache: "force-cache", next: { tags: [generateTag(lang, uid)] } }
{
cache: "force-cache",
next: {
tags: [generateTag(lang, uid)],
},
}
)
if (!refsResponse.data) {
const notFoundError = notFound(refsResponse)
@@ -69,11 +74,15 @@ export async function fetchContentPageRefs(lang: Lang, uid: string) {
throw notFoundError
}
return removeEmptyObjects(refsResponse.data)
return refsResponse.data
}
export function validateContentPageRefs(data: any, lang: Lang, uid: string) {
const validatedData = validateContentPageRefsSchema.safeParse(data)
export function validateContentPageRefs(
data: GetContentPageRefsSchema,
lang: Lang,
uid: string
) {
const validatedData = contentPageRefsSchema.safeParse(data)
if (!validatedData.success) {
getContentPageRefsFailCounter.add(1, {
lang,
@@ -97,64 +106,70 @@ export function validateContentPageRefs(data: any, lang: Lang, uid: string) {
query: { lang, uid },
})
)
return validatedData.data
}
export function generatePageTags(validatedData: any, lang: Lang): string[] {
export function generatePageTags(
validatedData: ContentPageRefs,
lang: Lang
): string[] {
const connections = getConnections(validatedData)
return [
generateTags(lang, connections),
generateTagsFromSystem(lang, connections),
generateTag(lang, validatedData.content_page.system.uid),
].flat()
}
export function getConnections(refs: ContentPageRefsDataRaw) {
const connections: Edges<NodeRefs>[] = []
if (refs.content_page.blocks) {
refs.content_page.blocks.forEach((item) => {
switch (item.__typename) {
case ContentBlocksTypenameEnum.ContentPageBlocksContent: {
if (item.content.content.embedded_itemsConnection.edges.length) {
connections.push(item.content.content.embedded_itemsConnection)
export function getConnections({ content_page }: ContentPageRefs) {
const connections: System["system"][] = [content_page.system]
if (content_page.blocks) {
content_page.blocks.forEach((block) => {
switch (block.__typename) {
case ContentPageEnum.ContentStack.blocks.Content:
{
if (block.content.length) {
// TS has trouble infering the filtered types
// @ts-ignore
connections.push(...block.content)
}
}
break
case ContentPageEnum.ContentStack.blocks.Shortcuts: {
if (block.shortcuts.shortcuts.length) {
connections.push(...block.shortcuts.shortcuts)
}
break
}
case ContentBlocksTypenameEnum.ContentPageBlocksShortcuts: {
item.shortcuts.shortcuts.forEach((shortcut) => {
if (shortcut.linkConnection.edges.length) {
connections.push(shortcut.linkConnection)
}
})
case ContentPageEnum.ContentStack.blocks.TextCols: {
if (block.text_cols.length) {
connections.push(...block.text_cols)
}
break
}
}
})
}
if (content_page.sidebar) {
content_page.sidebar.forEach((block) => {
switch (block.__typename) {
case ContentPageEnum.ContentStack.sidebar.Content:
if (block.content.length) {
connections.push(...block.content)
}
break
case ContentPageEnum.ContentStack.sidebar.JoinLoyaltyContact:
if (block.join_loyalty_contact?.button) {
connections.push(block.join_loyalty_contact.button)
}
break
default:
break
}
})
}
return connections
}
export function makeButtonObject(button: any) {
if (!button) return null
const isContenstackLink =
button?.is_contentstack_link || button.linkConnection?.edges?.length
const linkConnnectionNode = isContenstackLink
? button.linkConnection.edges[0]?.node
: null
return {
openInNewTab: button?.open_in_new_tab,
title:
button.cta_text ||
(linkConnnectionNode
? linkConnnectionNode.title
: button.external_link.title),
href: linkConnnectionNode
? linkConnnectionNode.web?.original_url ||
removeMultipleSlashes(
`/${linkConnnectionNode.system.locale}/${linkConnnectionNode.url}`
)
: button.external_link.href,
isExternal: !isContenstackLink,
}
}