From 2ae23bc493d61b1582510e07be967f332e2f7f6d Mon Sep 17 00:00:00 2001 From: MN <97020799+VWSCoronaDashboard24@users.noreply.github.com> Date: Tue, 2 Aug 2022 16:50:20 +0200 Subject: [PATCH] COR-754 | Proposal: dynamic loading of Sanity keys in debug mode (#4328) * wip: dynamic sanity content loading * wip: dynamic sanity content gathering * feat: custom hook for dynamic sanity content loading * fix: update lockfile * fix: revert changes in cms packages * fix: code cleanup * Update packages/app/src/utils/cms/use-dynamic-lokalize-texts.ts * fix: pr feedback Co-authored-by: VWSCoronaDashboard24 --- packages/app/package.json | 2 +- packages/app/src/locale/use-lokalize-text.tsx | 10 ++-- packages/app/src/pages/index.tsx | 43 ++++++++--------- packages/app/src/utils/cms/client.ts | 15 ++++++ .../app/src/utils/cms/fetch-lokalize-texts.ts | 12 +++++ .../utils/cms/use-dynamic-lokalize-texts.ts | 34 ++++++++++++++ yarn.lock | 46 +++++++++++++------ 7 files changed, 118 insertions(+), 44 deletions(-) create mode 100644 packages/app/src/utils/cms/client.ts create mode 100644 packages/app/src/utils/cms/fetch-lokalize-texts.ts create mode 100644 packages/app/src/utils/cms/use-dynamic-lokalize-texts.ts diff --git a/packages/app/package.json b/packages/app/package.json index 6f9b8c052b..9d142c4a78 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -9,7 +9,7 @@ "@reach/combobox": "^0.16.4", "@reach/disclosure": "^0.16.2", "@sanity/block-content-to-react": "^3.0.0", - "@sanity/client": "^2.22.3", + "@sanity/client": "^3.3.2", "@styled-system/css": "^5.1.5", "@styled-system/should-forward-prop": "^5.1.5", "@tippyjs/react": "^4.2.6", diff --git a/packages/app/src/locale/use-lokalize-text.tsx b/packages/app/src/locale/use-lokalize-text.tsx index 45e6d6d3a1..8ea04436f9 100644 --- a/packages/app/src/locale/use-lokalize-text.tsx +++ b/packages/app/src/locale/use-lokalize-text.tsx @@ -21,6 +21,10 @@ export type Dataset = typeof datasets[number]; const query = `*[_type == 'lokalizeText']`; const enableHotReload = process.env.NEXT_PUBLIC_PHASE === 'develop'; +export const IS_STAGING_ENV = + typeof window !== 'undefined' && + window.location.host === 'staging.coronadashboard.rijksoverheid.nl'; + /** * This hook will return an object which contains all lokalize translations. * @@ -35,9 +39,7 @@ export function useLokalizeText(initialLocale: LanguageKey) { const [locale, setLocale] = useState(initialLocale); const [text, setText] = useState(languages[locale]); const lokalizeTextsRef = useRef[]>([]); - - const isStagingEnv = typeof window !== 'undefined' && window.location.host === 'staging.coronadashboard.rijksoverheid.nl'; - const showSanityDebugToggle = enableHotReload || isStagingEnv; + const showSanityDebugToggle = enableHotReload || IS_STAGING_ENV; const [dataset, setDataset] = useState( (process.env.NEXT_PUBLIC_SANITY_DATASET as Dataset | undefined) ?? @@ -143,7 +145,7 @@ export function useLokalizeText(initialLocale: LanguageKey) { * output: * { foo: { bar: 'foo.bar', baz: 'foo.baz' }} */ -function mapSiteTextValuesToKeys(siteText: SiteText) { +export function mapSiteTextValuesToKeys(siteText: SiteText) { const keys = Object.keys(flatten(siteText)); const obj = keys.reduce( diff --git a/packages/app/src/pages/index.tsx b/packages/app/src/pages/index.tsx index 38b6c7e9fd..25ef996009 100644 --- a/packages/app/src/pages/index.tsx +++ b/packages/app/src/pages/index.tsx @@ -39,7 +39,7 @@ import { selectVaccineCoverageData } from '~/domain/vaccine/data-selection/selec import { useIntl } from '~/intl'; import { getWarning } from '~/queries/get-elements-query'; import { getTopicalPageData } from '~/queries/get-topical-page-data'; -import { Languages } from '~/locale'; +import { Languages, SiteText } from '~/locale'; import { createGetStaticProps, StaticProps, @@ -61,20 +61,22 @@ import { trimNullValues, replaceVariablesInText, } from '~/utils'; +import { useDynamicLokalizeTexts } from '~/utils/cms/use-dynamic-lokalize-texts'; + +const selectLokalizeTexts = (siteText: SiteText) => ({ + hospitalText: siteText.pages.hospital_page.nl, + intensiveCareText: siteText.pages.intensive_care_page.nl, + sewerText: siteText.pages.sewer_page.shared, + positiveTestsText: siteText.pages.positive_tests_page.shared, + textNl: siteText.pages.topical_page.nl, + textShared: siteText.pages.topical_page.shared, +}); + +type LokalizeTexts = ReturnType; export const getStaticProps = createGetStaticProps( ({ locale }: { locale: keyof Languages }) => - getLokalizeTexts( - (siteText) => ({ - hospitalText: siteText.pages.hospital_page.nl, - intensiveCareText: siteText.pages.intensive_care_page.nl, - sewerText: siteText.pages.sewer_page.shared, - positiveTestsText: siteText.pages.positive_tests_page.shared, - textNl: siteText.pages.topical_page.nl, - textShared: siteText.pages.topical_page.shared, - }), - locale - ), + getLokalizeTexts(selectLokalizeTexts, locale), getLastGeneratedDate, createGetChoroplethData({ vr: ({ tested_overall, vaccine_coverage_per_age_group }) => ({ @@ -169,13 +171,7 @@ export const getStaticProps = createGetStaticProps( ); const Home = (props: StaticProps) => { - const { - pageText, - selectedNlData: data, - choropleth, - content, - lastGenerated, - } = props; + const { selectedNlData: data, choropleth, content, lastGenerated } = props; const dataSewerTotal = data.sewer; const dataICTotal = data.intensive_care_nice; @@ -184,7 +180,9 @@ const Home = (props: StaticProps) => { const { commonTexts, ...formatters } = useIntl(); const reverseRouter = useReverseRouter(); - const { hospitalText, intensiveCareText, textNl, textShared } = pageText; + + const { hospitalText, intensiveCareText, textNl, textShared } = + useDynamicLokalizeTexts(props.pageText, selectLokalizeTexts); const { formatPercentageAsNumber } = useFormatLokalizePercentage(); @@ -677,10 +675,7 @@ const Home = (props: StaticProps) => { /> {isPresent(content.articles) && ( - + )} diff --git a/packages/app/src/utils/cms/client.ts b/packages/app/src/utils/cms/client.ts new file mode 100644 index 0000000000..0049b7c04d --- /dev/null +++ b/packages/app/src/utils/cms/client.ts @@ -0,0 +1,15 @@ +import sanityClient, { ClientConfig } from '@sanity/client'; + +const clientConfig: ClientConfig = { + apiVersion: '2021-03-25', + projectId: '5mog5ask', + useCdn: false, +}; + +export function getClient(dataset = 'development') { + return sanityClient({ + ...clientConfig, + dataset, + token: process.env.SANITY_TOKEN, + }); +} diff --git a/packages/app/src/utils/cms/fetch-lokalize-texts.ts b/packages/app/src/utils/cms/fetch-lokalize-texts.ts new file mode 100644 index 0000000000..f7f6a1fbc6 --- /dev/null +++ b/packages/app/src/utils/cms/fetch-lokalize-texts.ts @@ -0,0 +1,12 @@ +import { LokalizeText } from '~/types/cms'; +import { getClient } from './client'; +import { createFlatTexts } from '@corona-dashboard/common'; +import { Dataset } from '~/locale/use-lokalize-text'; + +export const fetchLokalizeTexts = async (dataset: Dataset) => { + const client = getClient(dataset); + const documents: LokalizeText[] = await client.fetch( + `*[_type == 'lokalizeText' && (defined(key)) && !(_id in path('drafts.**'))] | order(key asc)` + ); + return createFlatTexts(documents, false); +}; diff --git a/packages/app/src/utils/cms/use-dynamic-lokalize-texts.ts b/packages/app/src/utils/cms/use-dynamic-lokalize-texts.ts new file mode 100644 index 0000000000..1fcfa8aae3 --- /dev/null +++ b/packages/app/src/utils/cms/use-dynamic-lokalize-texts.ts @@ -0,0 +1,34 @@ +import { useEffect, useState } from 'react'; +import { useIntl } from '~/intl'; +import { SiteText } from '~/locale'; +import { + IS_STAGING_ENV, + mapSiteTextValuesToKeys, +} from '~/locale/use-lokalize-text'; +import { fetchLokalizeTexts } from './fetch-lokalize-texts'; + +export const useDynamicLokalizeTexts = >( + initialTexts: T, + selector: (text: SiteText) => T +) => { + const [texts, setTexts] = useState(initialTexts); + const { dataset, locale } = useIntl(); + + useEffect(() => { + if (dataset === 'keys') { + fetchLokalizeTexts(IS_STAGING_ENV ? 'production' : 'development') + .catch((err) => { + throw new Error( + `[${useDynamicLokalizeTexts.name}] Error while fetching Sanity content: "${err}"` + ); + }) + .then((texts) => texts[locale] as unknown as SiteText) + .then((texts) => mapSiteTextValuesToKeys(texts)) + .then((texts) => setTexts(selector(texts))); + } else { + setTexts(initialTexts); + } + }, [initialTexts, dataset, locale, selector]); + + return texts; +}; diff --git a/yarn.lock b/yarn.lock index 293d4588e0..ac4691b915 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2550,7 +2550,7 @@ __metadata: "@reach/combobox": ^0.16.4 "@reach/disclosure": ^0.16.2 "@sanity/block-content-to-react": ^3.0.0 - "@sanity/client": ^2.22.3 + "@sanity/client": ^3.3.2 "@styled-system/css": ^5.1.5 "@styled-system/should-forward-prop": ^5.1.5 "@testing-library/react": ^12.1.2 @@ -4051,32 +4051,31 @@ __metadata: languageName: node linkType: hard -"@sanity/client@npm:^2.22.3": - version: 2.22.3 - resolution: "@sanity/client@npm:2.22.3" +"@sanity/client@npm:^3.2.0": + version: 3.3.0 + resolution: "@sanity/client@npm:3.3.0" dependencies: - "@sanity/eventsource": 2.14.0 - "@sanity/generate-help-url": 2.18.0 - "@sanity/observable": 2.0.9 - deep-assign: ^2.0.0 - get-it: ^5.0.3 + "@sanity/eventsource": ^3.0.2 + "@sanity/generate-help-url": ^3.0.0 + get-it: ^6.0.1 make-error: ^1.3.0 object-assign: ^4.1.1 - checksum: f9bc475226d8ec90cf970d8f22d5f6a4314be71220156f71445ae986cee214d5a208217c55a22efb10d8b0176beee1e0a4d30de084f1821f87ad51ead0c32d3a + rxjs: ^6.0.0 + checksum: d3a25bf6c85635b5a107f63eff9db8a12ec906e69131c1f778b449821b1fb1497081ab97a73c691254c69bacfe506ccb5905f6556ed57020e0f8805d0fa53667 languageName: node linkType: hard -"@sanity/client@npm:^3.2.0": - version: 3.3.0 - resolution: "@sanity/client@npm:3.3.0" +"@sanity/client@npm:^3.3.2": + version: 3.3.2 + resolution: "@sanity/client@npm:3.3.2" dependencies: - "@sanity/eventsource": ^3.0.2 + "@sanity/eventsource": ^4.0.0 "@sanity/generate-help-url": ^3.0.0 get-it: ^6.0.1 make-error: ^1.3.0 object-assign: ^4.1.1 rxjs: ^6.0.0 - checksum: d3a25bf6c85635b5a107f63eff9db8a12ec906e69131c1f778b449821b1fb1497081ab97a73c691254c69bacfe506ccb5905f6556ed57020e0f8805d0fa53667 + checksum: aa435c905a7ba567fe75736414acf9bfaf9b325aaeb48a6e888694a6a7f12d172081f364dee021b68f64a823726f5ad00ef7985644c30f3896a57965b22acf89 languageName: node linkType: hard @@ -4317,6 +4316,16 @@ __metadata: languageName: node linkType: hard +"@sanity/eventsource@npm:^4.0.0": + version: 4.0.0 + resolution: "@sanity/eventsource@npm:4.0.0" + dependencies: + event-source-polyfill: 1.0.25 + eventsource: ^2.0.2 + checksum: ae1f950ff126fd37cea5cbb2adaa952ab4a56221b2af5e284ebd113adc0754b4a8fdea9d6d7e0022058425a72b158342cb1f1a8d799b22f53f6d995065cbc141 + languageName: node + linkType: hard + "@sanity/export@npm:2.29.3": version: 2.29.3 resolution: "@sanity/export@npm:2.29.3" @@ -14025,6 +14034,13 @@ __metadata: languageName: node linkType: hard +"eventsource@npm:^2.0.2": + version: 2.0.2 + resolution: "eventsource@npm:2.0.2" + checksum: c0072d972753e10c705d9b2285b559184bf29d011bc208973dde9c8b6b8b7b6fdad4ef0846cecb249f7b1585e860fdf324cbd2ac854a76bc53649e797496e99a + languageName: node + linkType: hard + "evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": version: 1.0.3 resolution: "evp_bytestokey@npm:1.0.3"