From 62b9a665695b195a24c8c90767a3d9e816a3ce13 Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Fri, 18 Oct 2024 09:02:23 +0200 Subject: [PATCH] feat(SW-497): added link and refs to site config --- lib/graphql/Fragments/Alert.graphql | 52 ++++++++++++ lib/graphql/Query/SiteConfig.graphql | 21 +++++ server/routers/contentstack/base/output.ts | 63 ++++++++++++++- server/routers/contentstack/base/query.ts | 80 ++++++++++++++++++- server/routers/contentstack/base/telemetry.ts | 9 +++ server/routers/contentstack/base/utils.ts | 11 ++- types/trpc/routers/contentstack/siteConfig.ts | 3 + 7 files changed, 227 insertions(+), 12 deletions(-) diff --git a/lib/graphql/Fragments/Alert.graphql b/lib/graphql/Fragments/Alert.graphql index 2bd93830f..65d1d9cdb 100644 --- a/lib/graphql/Fragments/Alert.graphql +++ b/lib/graphql/Fragments/Alert.graphql @@ -3,6 +3,11 @@ #import "./PageLink/HotelPageLink.graphql" #import "./PageLink/LoyaltyPageLink.graphql" +#import "./AccountPage/Ref.graphql" +#import "./ContentPage/Ref.graphql" +#import "./HotelPage/Ref.graphql" +#import "./LoyaltyPage/Ref.graphql" + fragment Alert on Alert { type heading @@ -12,6 +17,21 @@ fragment Alert on Alert { phone_number footnote } + has_link + link { + title + linkConnection { + edges { + node { + __typename + ...AccountPageLink + ...ContentPageLink + ...HotelPageLink + ...LoyaltyPageLink + } + } + } + } has_sidepeek_button sidepeek_button { cta_text @@ -34,3 +54,35 @@ fragment Alert on Alert { } } } + +fragment AlertRef on Alert { + link { + linkConnection { + edges { + node { + __typename + ...AccountPageRef + ...ContentPageRef + ...HotelPageRef + ...LoyaltyPageRef + } + } + } + } + sidepeek_content { + content { + embedded_itemsConnection { + edges { + node { + __typename + ...AccountPageRef + ...ContentPageRef + ...HotelPageRef + ...LoyaltyPageRef + } + } + } + json + } + } +} diff --git a/lib/graphql/Query/SiteConfig.graphql b/lib/graphql/Query/SiteConfig.graphql index 59cc80616..4c21f5214 100644 --- a/lib/graphql/Query/SiteConfig.graphql +++ b/lib/graphql/Query/SiteConfig.graphql @@ -1,3 +1,5 @@ +#import "../Fragments/System.graphql" + #import "../Fragments/Alert.graphql" query GetSiteConfig($locale: String!) { @@ -16,3 +18,22 @@ query GetSiteConfig($locale: String!) { } } } + +query GetSiteConfigRef($locale: String!) { + all_site_config(limit: 1, locale: $locale) { + items { + sitewide_alert { + alertConnection { + edges { + node { + ...AlertRef + } + } + } + } + system { + ...System + } + } + } +} diff --git a/server/routers/contentstack/base/output.ts b/server/routers/contentstack/base/output.ts index e6d54f36d..85aa2651a 100644 --- a/server/routers/contentstack/base/output.ts +++ b/server/routers/contentstack/base/output.ts @@ -541,6 +541,7 @@ export const headerRefsSchema = z }) const linkUnionSchema = z.discriminatedUnion("__typename", [ + pageLinks.accountPageSchema, pageLinks.contentPageSchema, pageLinks.hotelPageSchema, pageLinks.loyaltyPageSchema, @@ -674,7 +675,9 @@ export const alertSchema = z phone_number: z.string().nullable(), footnote: z.string().nullable(), }), - has_sidepeek_button: z.boolean().default(false), + has_link: z.boolean(), + link: linkAndTitleSchema, + has_sidepeek_button: z.boolean(), sidepeek_button: z.object({ cta_text: z.string(), }), @@ -711,10 +714,13 @@ export const alertSchema = z heading, text, phone_contact, + has_link, + link, has_sidepeek_button, sidepeek_button, sidepeek_content, }) => { + const hasLink = has_link && link.link return { type, text, @@ -727,9 +733,17 @@ export const alertSchema = z footnote: phone_contact.footnote, } : null, - hasSidepeekButton: has_sidepeek_button, - sidepeekButton: has_sidepeek_button ? sidepeek_button : null, - sidepeekContent: has_sidepeek_button ? sidepeek_content : null, + hasSidepeekButton: !!has_sidepeek_button, + link: hasLink + ? { + url: link.link.url, + title: link.title, + } + : null, + sidepeekButton: + !hasLink && has_sidepeek_button ? sidepeek_button : null, + sidepeekContent: + !hasLink && has_sidepeek_button ? sidepeek_content : null, } } ) @@ -772,3 +786,44 @@ export const siteConfigSchema = z bookingWidgetDisabled: sitewide_alert.booking_widget_disabled, } }) + +const sidepeekContentRefSchema = z.object({ + content: z.object({ + embedded_itemsConnection: z.object({ + edges: z.array( + z.object({ + node: z.discriminatedUnion("__typename", [ + pageLinks.accountPageRefSchema, + pageLinks.contentPageRefSchema, + pageLinks.hotelPageRefSchema, + pageLinks.loyaltyPageRefSchema, + ]), + }) + ), + }), + }), +}) + +const alertConnectionRefSchema = z.object({ + edges: z.array( + z.object({ + node: z.object({ + link: linkRefsSchema, + sidepeek_content: sidepeekContentRefSchema, + }), + }) + ), +}) + +export const siteConfigRefSchema = z.object({ + all_site_config: z.object({ + items: z.array( + z.object({ + sitewide_alert: z.object({ + alertConnection: alertConnectionRefSchema, + }), + system: systemSchema, + }) + ), + }), +}) diff --git a/server/routers/contentstack/base/query.ts b/server/routers/contentstack/base/query.ts index 580ebf7b2..2a26e980e 100644 --- a/server/routers/contentstack/base/query.ts +++ b/server/routers/contentstack/base/query.ts @@ -10,7 +10,10 @@ import { } from "@/lib/graphql/Query/Current/Header.graphql" import { GetFooter, GetFooterRef } from "@/lib/graphql/Query/Footer.graphql" import { GetHeader, GetHeaderRef } from "@/lib/graphql/Query/Header.graphql" -import { GetSiteConfig } from "@/lib/graphql/Query/SiteConfig.graphql" +import { + GetSiteConfig, + GetSiteConfigRef, +} from "@/lib/graphql/Query/SiteConfig.graphql" import { request } from "@/lib/graphql/request" import { notFound } from "@/server/errors/trpc" import { contentstackBaseProcedure, router } from "@/server/trpc" @@ -31,6 +34,7 @@ import { type GetCurrentHeaderData, headerRefsSchema, headerSchema, + siteConfigRefSchema, siteConfigSchema, validateContactConfigSchema, validateCurrentFooterConfigSchema, @@ -64,6 +68,9 @@ import { getHeaderSuccessCounter, getSiteConfigCounter, getSiteConfigFailCounter, + getSiteConfigRefCounter, + getSiteConfigRefFailCounter, + getSiteConfigRefSuccessCounter, getSiteConfigSuccessCounter, } from "./telemetry" import { @@ -80,7 +87,10 @@ import type { GetHeader as GetHeaderData, GetHeaderRefs, } from "@/types/trpc/routers/contentstack/header" -import type { GetSiteConfigData } from "@/types/trpc/routers/contentstack/siteConfig" +import type { + GetSiteConfigData, + GetSiteConfigRefData, +} from "@/types/trpc/routers/contentstack/siteConfig" async function getContactConfig(lang: Lang) { getContactConfigCounter.add(1, { lang }) @@ -604,6 +614,72 @@ export const baseQueryRouter = router({ }), siteConfig: contentstackBaseProcedure.query(async ({ ctx }) => { const { lang } = ctx + + getSiteConfigRefCounter.add(1, { lang }) + console.info( + "contentstack.siteConfig.ref start", + JSON.stringify({ query: { lang } }) + ) + const responseRef = await request( + GetSiteConfigRef, + { + locale: lang, + }, + { + cache: "force-cache", + next: { + tags: [generateRefsResponseTag(lang, "siteConfig")], + }, + } + ) + + if (!responseRef.data) { + const notFoundError = notFound(responseRef) + getSiteConfigRefFailCounter.add(1, { + lang, + error_type: "not_found", + error: JSON.stringify({ code: notFoundError.code }), + }) + console.error( + "contentstack.siteConfig.refs not found error", + JSON.stringify({ + query: { + lang, + }, + error: { code: notFoundError.code }, + }) + ) + throw notFoundError + } + + const validatedSiteConfigRef = siteConfigRefSchema.safeParse( + responseRef.data + ) + + if (!validatedSiteConfigRef.success) { + getSiteConfigRefFailCounter.add(1, { + lang, + error_type: "validation_error", + error: JSON.stringify(validatedSiteConfigRef.error), + }) + console.error( + "contentstack.siteConfig.refs validation error", + JSON.stringify({ + query: { + lang, + }, + error: validatedSiteConfigRef.error, + }) + ) + return null + } + + getSiteConfigRefSuccessCounter.add(1, { lang }) + console.info( + "contentstack.siteConfig.refs success", + JSON.stringify({ query: { lang } }) + ) + getSiteConfigCounter.add(1, { lang }) console.info( "contentstack.siteConfig start", diff --git a/server/routers/contentstack/base/telemetry.ts b/server/routers/contentstack/base/telemetry.ts index 78000689d..159f69d36 100644 --- a/server/routers/contentstack/base/telemetry.ts +++ b/server/routers/contentstack/base/telemetry.ts @@ -92,6 +92,15 @@ export const getFooterFailCounter = meter.createCounter( ) // OpenTelemetry metrics: SiteConfig +export const getSiteConfigRefCounter = meter.createCounter( + "trpc.contentstack.SiteConfig.ref.get" +) +export const getSiteConfigRefSuccessCounter = meter.createCounter( + "trpc.contentstack.SiteConfig.ref.get-success" +) +export const getSiteConfigRefFailCounter = meter.createCounter( + "trpc.contentstack.SiteConfig.ref.get-fail" +) export const getSiteConfigCounter = meter.createCounter( "trpc.contentstack.SiteConfig.get" ) diff --git a/server/routers/contentstack/base/utils.ts b/server/routers/contentstack/base/utils.ts index 48cee6b95..df88e9cb7 100644 --- a/server/routers/contentstack/base/utils.ts +++ b/server/routers/contentstack/base/utils.ts @@ -1,13 +1,12 @@ import { getValueFromContactConfig } from "@/utils/contactConfig" -import { ContactConfig } from "./output" - import type { FooterRefDataRaw } from "@/types/components/footer/footer" -import { System } from "@/types/requests/system" -import { Edges } from "@/types/requests/utils/edges" -import { NodeRefs } from "@/types/requests/utils/refs" +import type { System } from "@/types/requests/system" +import type { Edges } from "@/types/requests/utils/edges" +import type { NodeRefs } from "@/types/requests/utils/refs" import type { HeaderRefs } from "@/types/trpc/routers/contentstack/header" -import { Alert } from "@/types/trpc/routers/contentstack/siteConfig" +import type { Alert } from "@/types/trpc/routers/contentstack/siteConfig" +import type { ContactConfig } from "./output" export function getConnections({ header }: HeaderRefs) { const connections: System["system"][] = [header.system] diff --git a/types/trpc/routers/contentstack/siteConfig.ts b/types/trpc/routers/contentstack/siteConfig.ts index 962e7777b..8dc553cb2 100644 --- a/types/trpc/routers/contentstack/siteConfig.ts +++ b/types/trpc/routers/contentstack/siteConfig.ts @@ -2,9 +2,12 @@ import { z } from "zod" import { alertSchema, + siteConfigRefSchema, siteConfigSchema, } from "@/server/routers/contentstack/base/output" +export type GetSiteConfigRefData = z.infer + export type GetSiteConfigData = z.input export type SiteConfig = z.output