From 8ba50bcb212ae9e84d7fc603f0e201ff4f1f8d95 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Tue, 9 Jan 2024 11:23:37 +0200 Subject: [PATCH] fix(types): remove "as unknown as" type unsafe casts fix most of the underlying type problems (apolloClient's type is still handled without type safety, add FIXME for that): - related to react-helsinki-headless-cms Config type - add missing fields to returned field named `copy` - handle `currentLanguageCode` field type safely - fix incorrect parameter and return type of `utils.getEventCardProps` - fix incorrect parameter type of `utils.getRoutedInternalHref` refs HH-189 --- .../config/jest/TestProviders.tsx | 30 +++++++++++++--- .../src/hooks/useEventsRHHCConfig.tsx | 28 ++++++++------- .../src/pages/articles/[...slug].tsx | 4 +-- .../src/pages/articles/index.tsx | 11 +++--- .../config/jest/TestProviders.tsx | 30 +++++++++++++--- .../src/hooks/useHobbiesRHHCConfig.tsx | 26 ++++++++------ .../src/pages/articles/[...slug].tsx | 4 +-- .../src/pages/articles/index.tsx | 11 +++--- .../config/jest/TestProviders.tsx | 34 ++++++++++++++---- .../src/hooks/useSportsRHHCConfig.tsx | 28 ++++++++------- .../src/pages/articles/[...slug].tsx | 4 +-- .../src/pages/articles/index.tsx | 11 +++--- apps/sports-helsinki/src/pages/search/map.tsx | 5 +-- .../config/tests/app-test-providers.tsx | 35 +++++++++++++++---- .../components/domain/event/useEventCards.tsx | 3 +- .../utils/__tests__/getLanguageCode.test.ts | 10 ++++++ .../__tests__/getLanguageCodeFilter.test.ts | 19 ++++++++++ .../components/src/utils/getLanguageCode.ts | 12 +++++++ .../src/utils/getLanguageCodeFilter.ts | 15 ++++++++ packages/components/src/utils/index.ts | 2 ++ 20 files changed, 232 insertions(+), 90 deletions(-) create mode 100644 packages/components/src/utils/__tests__/getLanguageCode.test.ts create mode 100644 packages/components/src/utils/__tests__/getLanguageCodeFilter.test.ts create mode 100644 packages/components/src/utils/getLanguageCode.ts create mode 100644 packages/components/src/utils/getLanguageCodeFilter.ts diff --git a/apps/events-helsinki/config/jest/TestProviders.tsx b/apps/events-helsinki/config/jest/TestProviders.tsx index 331651803..03bc9e770 100644 --- a/apps/events-helsinki/config/jest/TestProviders.tsx +++ b/apps/events-helsinki/config/jest/TestProviders.tsx @@ -1,4 +1,9 @@ -import type { ApolloCache, ApolloClient, InMemoryCache } from '@apollo/client'; +import type { + ApolloCache, + ApolloClient, + InMemoryCache, + NormalizedCacheObject, +} from '@apollo/client'; import { useApolloClient } from '@apollo/client'; import type { MockedResponse } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing'; @@ -6,6 +11,7 @@ import { AppRoutingProvider, CmsHelperProvider, DEFAULT_LANGUAGE, + getLanguageCode, NavigationContext, } from '@events-helsinki/components'; import { RouterContext } from 'next/dist/shared/lib/router-context'; @@ -81,7 +87,10 @@ function RHHCConfigProviderWithMockedApolloClient({ children, router }: Props) { ); } -function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { +function getRHHCConfig( + router: NextRouter, + apolloClient: ApolloClient +): RHHCConfig { const locale = DEFAULT_LANGUAGE; const getIsHrefExternal = (href: string) => { @@ -127,11 +136,15 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { return routerHelper.getLocalizedCmsItemUrl(link, {}, locale); }; + // FIXME: Fix types of apolloClient/RHHCConfig so they are compatible without casting + const normalizedCacheObjectApolloClient = + apolloClient as ApolloClient; + return { ...rhhcDefaultConfig, siteName: 'appName', - currentLanguageCode: locale.toUpperCase(), - apolloClient, + currentLanguageCode: getLanguageCode(locale), + apolloClient: normalizedCacheObjectApolloClient, components: { ...rhhcDefaultConfig.components, // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -151,7 +164,12 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { ), openInNewTabAriaLabel: i18n.t('common:srOnly.opensInANewTab'), closeButtonLabelText: i18n.t('common:button.close'), + loadMoreButtonLabelText: i18n.t('common:button.loadMore'), + showAllText: i18n.t('common:button.showAll'), + next: i18n.t('common:next'), + previous: i18n.t('common:previous'), archiveSearch: { + title: i18n.t('cms:archiveSearch.title'), searchTextPlaceholder: i18n.t( 'cms:archiveSearch.searchTextPlaceholder' ), @@ -161,7 +179,9 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { loadMoreButtonLabelText: i18n.t( 'cms:archiveSearch.loadMoreButtonLabelText' ), + noResultsTitle: i18n.t('cms:archiveSearch.noResultsTitle'), noResultsText: i18n.t('cms:archiveSearch.noResultsText'), + clearAll: i18n.t('cms:archiveSearch.buttonClearFilters'), }, }, utils: { @@ -171,7 +191,7 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { getRoutedInternalHref, }, internalHrefOrigins, - } as unknown as RHHCConfig; + }; } export default TestProviders; diff --git a/apps/events-helsinki/src/hooks/useEventsRHHCConfig.tsx b/apps/events-helsinki/src/hooks/useEventsRHHCConfig.tsx index 58dfd33bd..588ef0cb4 100644 --- a/apps/events-helsinki/src/hooks/useEventsRHHCConfig.tsx +++ b/apps/events-helsinki/src/hooks/useEventsRHHCConfig.tsx @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import type { ApolloClient, NormalizedCacheObject } from '@apollo/client'; import type { EventFieldsFragment } from '@events-helsinki/components'; import { + getLanguageCode, getLinkArrowLabel, useLocale, useCommonTranslation, @@ -15,7 +15,7 @@ import { import Head from 'next/head'; import Link from 'next/link'; import React from 'react'; -import type { Config } from 'react-helsinki-headless-cms'; +import type { CardProps, Config } from 'react-helsinki-headless-cms'; import { defaultConfig as rhhcDefaultConfig, ModuleItemTypeEnum, @@ -39,7 +39,7 @@ const LINKEDEVENTS_API_EVENT_ENDPOINT = new URL( export default function useEventsRHHCConfig(args: { apolloClient: ApolloClient; -}) { +}): Config { const { apolloClient } = args; const { t: commonTranslation } = useCommonTranslation(); const { t: appTranslation } = useAppEventsTranslation(); @@ -87,20 +87,24 @@ export default function useEventsRHHCConfig(args: { ), }, siteName: appTranslation('appEvents:appName'), - currentLanguageCode: locale.toUpperCase(), + currentLanguageCode: getLanguageCode(locale), apolloClient, eventsApolloClient: apolloClient, venuesApolloClient: apolloClient, utils: { ...rhhcDefaultConfig.utils, getEventCardProps: AppConfig.showEnrolmentStatusInCardDetails - ? (item: EventFieldsFragment, locale: string) => ({ + ? ( + item: EventFieldsFragment, + organisationPrefixes: string[], + locale: string + ): CardProps => ({ ...rhhcDefaultConfig.utils.getEventCardProps( item, - CITY_OF_HELSINKI_LINKED_EVENTS_ORGANIZATION_PREFIXES, + organisationPrefixes, locale ), - getLinkArrowLabel: getLinkArrowLabel({ + linkArrowLabel: getLinkArrowLabel({ item, locale, eventTranslation, @@ -109,15 +113,15 @@ export default function useEventsRHHCConfig(args: { }) : rhhcDefaultConfig.utils.getEventCardProps, getRoutedInternalHref: ( - link: string, - _type: ModuleItemTypeEnum + link?: string | null, + type?: ModuleItemTypeEnum ): string => { - if (_type === ModuleItemTypeEnum.Venue) { + if (type === ModuleItemTypeEnum.Venue) { // quick fix for venue url rewrites return routerHelper.getLocalizedCmsItemUrl( ROUTES.VENUES, { - venueId: getVenueSourceId(link), + venueId: getVenueSourceId(link ?? ''), }, locale ); @@ -127,7 +131,7 @@ export default function useEventsRHHCConfig(args: { getIsHrefExternal, }, internalHrefOrigins, - } as unknown as Config; + }; }, [ commonConfig, appTranslation, diff --git a/apps/events-helsinki/src/pages/articles/[...slug].tsx b/apps/events-helsinki/src/pages/articles/[...slug].tsx index 44594f609..3d80ad75a 100644 --- a/apps/events-helsinki/src/pages/articles/[...slug].tsx +++ b/apps/events-helsinki/src/pages/articles/[...slug].tsx @@ -9,6 +9,7 @@ import { getLanguageOrDefault, useAppEventsTranslation, RouteMeta, + getLanguageCodeFilter, } from '@events-helsinki/components'; import type { AppLanguage } from '@events-helsinki/components'; import { logger } from '@events-helsinki/components/loggers/logger'; @@ -23,7 +24,6 @@ import type { Breadcrumb, CollectionType, ArticleType, - LanguageCodeFilterEnum, } from 'react-helsinki-headless-cms'; import { getCollections, @@ -68,7 +68,7 @@ const NextCmsArticle: NextPage<{ useCategoriesQuery({ variables: { first: CATEGORIES_AMOUNT, - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), }, }); diff --git a/apps/events-helsinki/src/pages/articles/index.tsx b/apps/events-helsinki/src/pages/articles/index.tsx index 33a33ccb5..3e89cef7d 100644 --- a/apps/events-helsinki/src/pages/articles/index.tsx +++ b/apps/events-helsinki/src/pages/articles/index.tsx @@ -10,6 +10,7 @@ import { FooterSection, getLanguageOrDefault, RouteMeta, + getLanguageCodeFilter, } from '@events-helsinki/components'; import type { GetStaticPropsContext } from 'next'; import { useRouter } from 'next/router'; @@ -23,11 +24,7 @@ import { useConfig, TemplateEnum, } from 'react-helsinki-headless-cms'; -import type { - ArticleType, - LanguageCodeFilterEnum, - PageType, -} from 'react-helsinki-headless-cms'; +import type { ArticleType, PageType } from 'react-helsinki-headless-cms'; import { useCategoriesQuery, PageByTemplateDocument, @@ -106,7 +103,7 @@ export default function ArticleArchive({ variables: { first: BLOCK_SIZE, search: searchFilters?.text ?? '', - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), categories: searchFilters?.tags ?? [], }, }); @@ -115,7 +112,7 @@ export default function ArticleArchive({ useCategoriesQuery({ variables: { first: CATEGORIES_AMOUNT, - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), }, }); diff --git a/apps/hobbies-helsinki/config/jest/TestProviders.tsx b/apps/hobbies-helsinki/config/jest/TestProviders.tsx index 27535abcd..fd751c87c 100644 --- a/apps/hobbies-helsinki/config/jest/TestProviders.tsx +++ b/apps/hobbies-helsinki/config/jest/TestProviders.tsx @@ -1,4 +1,9 @@ -import type { ApolloCache, ApolloClient, InMemoryCache } from '@apollo/client'; +import type { + ApolloCache, + ApolloClient, + InMemoryCache, + NormalizedCacheObject, +} from '@apollo/client'; import { useApolloClient } from '@apollo/client'; import type { MockedResponse } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing'; @@ -6,6 +11,7 @@ import { AppRoutingProvider, CmsHelperProvider, DEFAULT_LANGUAGE, + getLanguageCode, NavigationContext, } from '@events-helsinki/components'; import { RouterContext } from 'next/dist/shared/lib/router-context'; @@ -81,7 +87,10 @@ function RHHCConfigProviderWithMockedApolloClient({ children, router }: Props) { ); } -function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { +function getRHHCConfig( + router: NextRouter, + apolloClient: ApolloClient +): RHHCConfig { const locale = DEFAULT_LANGUAGE; const getIsHrefExternal = (href: string) => { @@ -127,11 +136,15 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { return routerHelper.getLocalizedCmsItemUrl(link, {}, locale); }; + // FIXME: Fix types of apolloClient/RHHCConfig so they are compatible without casting + const normalizedCacheObjectApolloClient = + apolloClient as ApolloClient; + return { ...rhhcDefaultConfig, siteName: 'appName', - currentLanguageCode: locale.toUpperCase(), - apolloClient, + currentLanguageCode: getLanguageCode(locale), + apolloClient: normalizedCacheObjectApolloClient, components: { ...rhhcDefaultConfig.components, // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -151,7 +164,12 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { ), openInNewTabAriaLabel: i18n.t('common:srOnly.opensInANewTab'), closeButtonLabelText: i18n.t('common:button.close'), + loadMoreButtonLabelText: i18n.t('common:button.loadMore'), + showAllText: i18n.t('common:button.showAll'), + next: i18n.t('common:next'), + previous: i18n.t('common:previous'), archiveSearch: { + title: i18n.t('cms:archiveSearch.title'), searchTextPlaceholder: i18n.t( 'cms:archiveSearch.searchTextPlaceholder' ), @@ -161,7 +179,9 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { loadMoreButtonLabelText: i18n.t( 'cms:archiveSearch.loadMoreButtonLabelText' ), + noResultsTitle: i18n.t('cms:archiveSearch.noResultsTitle'), noResultsText: i18n.t('cms:archiveSearch.noResultsText'), + clearAll: i18n.t('cms:archiveSearch.buttonClearFilters'), }, }, utils: { @@ -171,7 +191,7 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { getRoutedInternalHref, }, internalHrefOrigins, - } as unknown as RHHCConfig; + }; } export default TestProviders; diff --git a/apps/hobbies-helsinki/src/hooks/useHobbiesRHHCConfig.tsx b/apps/hobbies-helsinki/src/hooks/useHobbiesRHHCConfig.tsx index 8baa88d97..9d4b697f2 100644 --- a/apps/hobbies-helsinki/src/hooks/useHobbiesRHHCConfig.tsx +++ b/apps/hobbies-helsinki/src/hooks/useHobbiesRHHCConfig.tsx @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import type { ApolloClient, NormalizedCacheObject } from '@apollo/client'; import type { EventFieldsFragment } from '@events-helsinki/components'; import { + getLanguageCode, getLinkArrowLabel, useLocale, useCommonTranslation, @@ -15,7 +15,7 @@ import { import Head from 'next/head'; import Link from 'next/link'; import React from 'react'; -import type { Config } from 'react-helsinki-headless-cms'; +import type { CardProps, Config } from 'react-helsinki-headless-cms'; import { defaultConfig as rhhcDefaultConfig, ModuleItemTypeEnum, @@ -39,7 +39,7 @@ const LINKEDEVENTS_API_EVENT_ENDPOINT = new URL( export default function useHobbiesRHHCConfig(args: { apolloClient: ApolloClient; -}) { +}): Config { const { apolloClient } = args; const { t: commonTranslation } = useCommonTranslation(); const { t: appTranslation } = useAppHobbiesTranslation(); @@ -88,17 +88,21 @@ export default function useHobbiesRHHCConfig(args: { ), }, siteName: appTranslation('appHobbies:appName'), - currentLanguageCode: locale.toUpperCase(), + currentLanguageCode: getLanguageCode(locale), apolloClient, eventsApolloClient: apolloClient, venuesApolloClient: apolloClient, utils: { ...rhhcDefaultConfig.utils, getEventCardProps: AppConfig.showEnrolmentStatusInCardDetails - ? (item: EventFieldsFragment, locale: string) => ({ + ? ( + item: EventFieldsFragment, + organisationPrefixes: string[], + locale: string + ): CardProps => ({ ...rhhcDefaultConfig.utils.getEventCardProps( item, - CITY_OF_HELSINKI_LINKED_EVENTS_ORGANIZATION_PREFIXES, + organisationPrefixes, locale ), linkArrowLabel: getLinkArrowLabel({ @@ -110,15 +114,15 @@ export default function useHobbiesRHHCConfig(args: { }) : rhhcDefaultConfig.utils.getEventCardProps, getRoutedInternalHref: ( - link: string, - _type: ModuleItemTypeEnum + link?: string | null, + type?: ModuleItemTypeEnum ): string => { - if (_type === ModuleItemTypeEnum.Venue) { + if (type === ModuleItemTypeEnum.Venue) { // quick fix for venue url rewrites return routerHelper.getLocalizedCmsItemUrl( ROUTES.VENUES, { - venueId: getVenueSourceId(link), + venueId: getVenueSourceId(link ?? ''), }, locale ); @@ -128,7 +132,7 @@ export default function useHobbiesRHHCConfig(args: { getIsHrefExternal, }, internalHrefOrigins, - } as unknown as Config; + }; }, [ commonConfig, appTranslation, diff --git a/apps/hobbies-helsinki/src/pages/articles/[...slug].tsx b/apps/hobbies-helsinki/src/pages/articles/[...slug].tsx index b029be932..0b6a855b3 100644 --- a/apps/hobbies-helsinki/src/pages/articles/[...slug].tsx +++ b/apps/hobbies-helsinki/src/pages/articles/[...slug].tsx @@ -9,6 +9,7 @@ import { getLanguageOrDefault, useAppHobbiesTranslation, RouteMeta, + getLanguageCodeFilter, } from '@events-helsinki/components'; import type { AppLanguage } from '@events-helsinki/components'; import { logger } from '@events-helsinki/components/loggers/logger'; @@ -23,7 +24,6 @@ import type { Breadcrumb, CollectionType, ArticleType, - LanguageCodeFilterEnum, } from 'react-helsinki-headless-cms'; import { getCollections, @@ -67,7 +67,7 @@ const NextCmsArticle: NextPage<{ useCategoriesQuery({ variables: { first: CATEGORIES_AMOUNT, - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), }, }); diff --git a/apps/hobbies-helsinki/src/pages/articles/index.tsx b/apps/hobbies-helsinki/src/pages/articles/index.tsx index c11aa7d55..bd2871ac8 100644 --- a/apps/hobbies-helsinki/src/pages/articles/index.tsx +++ b/apps/hobbies-helsinki/src/pages/articles/index.tsx @@ -10,6 +10,7 @@ import { getLanguageOrDefault, RouteMeta, useAppHobbiesTranslation, + getLanguageCodeFilter, } from '@events-helsinki/components'; import type { GetStaticPropsContext } from 'next'; import { useRouter } from 'next/router'; @@ -23,11 +24,7 @@ import { useConfig, TemplateEnum, } from 'react-helsinki-headless-cms'; -import type { - ArticleType, - LanguageCodeFilterEnum, - PageType, -} from 'react-helsinki-headless-cms'; +import type { ArticleType, PageType } from 'react-helsinki-headless-cms'; import { useCategoriesQuery, PageByTemplateDocument, @@ -106,7 +103,7 @@ export default function ArticleArchive({ variables: { first: BLOCK_SIZE, search: searchFilters?.text ?? '', - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), categories: searchFilters?.tags ?? [], }, }); @@ -115,7 +112,7 @@ export default function ArticleArchive({ useCategoriesQuery({ variables: { first: CATEGORIES_AMOUNT, - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), }, }); diff --git a/apps/sports-helsinki/config/jest/TestProviders.tsx b/apps/sports-helsinki/config/jest/TestProviders.tsx index 30f4cb2bf..f711b547e 100644 --- a/apps/sports-helsinki/config/jest/TestProviders.tsx +++ b/apps/sports-helsinki/config/jest/TestProviders.tsx @@ -1,4 +1,9 @@ -import type { ApolloCache, ApolloClient, InMemoryCache } from '@apollo/client'; +import type { + ApolloCache, + ApolloClient, + InMemoryCache, + NormalizedCacheObject, +} from '@apollo/client'; import { useApolloClient } from '@apollo/client'; import { MockedProvider } from '@apollo/client/testing'; import type { MockedResponse } from '@apollo/client/testing'; @@ -6,6 +11,7 @@ import { AppRoutingProvider, CmsHelperProvider, DEFAULT_LANGUAGE, + getLanguageCode, NavigationContext, } from '@events-helsinki/components'; import { RouterContext } from 'next/dist/shared/lib/router-context'; @@ -81,7 +87,10 @@ function RHHCConfigProviderWithMockedApolloClient({ children, router }: Props) { ); } -function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { +function getRHHCConfig( + router: NextRouter, + apolloClient: ApolloClient +): RHHCConfig { const locale = DEFAULT_LANGUAGE; const getIsHrefExternal = (href: string) => { @@ -127,13 +136,17 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { return routerHelper.getLocalizedCmsItemUrl(link, {}, locale); }; + // FIXME: Fix types of apolloClient/RHHCConfig so they are compatible without casting + const normalizedCacheObjectApolloClient = + apolloClient as ApolloClient; + return { ...rhhcDefaultConfig, siteName: 'appName', - currentLanguageCode: locale.toUpperCase(), - apolloClient, - eventsApolloClient: apolloClient, - venuesApolloClient: apolloClient, + currentLanguageCode: getLanguageCode(locale), + apolloClient: normalizedCacheObjectApolloClient, + eventsApolloClient: normalizedCacheObjectApolloClient, + venuesApolloClient: normalizedCacheObjectApolloClient, components: { ...rhhcDefaultConfig.components, // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -153,7 +166,12 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { ), openInNewTabAriaLabel: i18n.t('common:srOnly.opensInANewTab'), closeButtonLabelText: i18n.t('common:button.close'), + loadMoreButtonLabelText: i18n.t('common:button.loadMore'), + showAllText: i18n.t('common:button.showAll'), + next: i18n.t('common:next'), + previous: i18n.t('common:previous'), archiveSearch: { + title: i18n.t('cms:archiveSearch.title'), searchTextPlaceholder: i18n.t( 'cms:archiveSearch.searchTextPlaceholder' ), @@ -163,7 +181,9 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { loadMoreButtonLabelText: i18n.t( 'cms:archiveSearch.loadMoreButtonLabelText' ), + noResultsTitle: i18n.t('cms:archiveSearch.noResultsTitle'), noResultsText: i18n.t('cms:archiveSearch.noResultsText'), + clearAll: i18n.t('cms:archiveSearch.buttonClearFilters'), }, }, utils: { @@ -173,7 +193,7 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { getRoutedInternalHref, }, internalHrefOrigins, - } as unknown as RHHCConfig; + }; } export default TestProviders; diff --git a/apps/sports-helsinki/src/hooks/useSportsRHHCConfig.tsx b/apps/sports-helsinki/src/hooks/useSportsRHHCConfig.tsx index b909e7c07..df4fcb2af 100644 --- a/apps/sports-helsinki/src/hooks/useSportsRHHCConfig.tsx +++ b/apps/sports-helsinki/src/hooks/useSportsRHHCConfig.tsx @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import type { ApolloClient, NormalizedCacheObject } from '@apollo/client'; import type { EventFieldsFragment } from '@events-helsinki/components'; import { + getLanguageCode, getLinkArrowLabel, useLocale, useCommonTranslation, @@ -15,7 +15,7 @@ import { import Head from 'next/head'; import Link from 'next/link'; import React from 'react'; -import type { Config } from 'react-helsinki-headless-cms'; +import type { CardProps, Config } from 'react-helsinki-headless-cms'; import { defaultConfig as rhhcDefaultConfig, ModuleItemTypeEnum, @@ -39,7 +39,7 @@ const LINKEDEVENTS_API_EVENT_ENDPOINT = new URL( export default function useSportsRHHCConfig(args: { apolloClient: ApolloClient; -}) { +}): Config { const { apolloClient } = args; const { t: commonTranslation } = useCommonTranslation(); const { t: appTranslation } = useAppSportsTranslation(); @@ -88,20 +88,24 @@ export default function useSportsRHHCConfig(args: { ), }, siteName: appTranslation('appSports:appName'), - currentLanguageCode: locale.toUpperCase(), + currentLanguageCode: getLanguageCode(locale), apolloClient, eventsApolloClient: apolloClient, venuesApolloClient: apolloClient, utils: { ...rhhcDefaultConfig.utils, getEventCardProps: AppConfig.showEnrolmentStatusInCardDetails - ? (item: EventFieldsFragment, locale: string) => ({ + ? ( + item: EventFieldsFragment, + organisationPrefixes: string[], + locale: string + ): CardProps => ({ ...rhhcDefaultConfig.utils.getEventCardProps( item, - CITY_OF_HELSINKI_LINKED_EVENTS_ORGANIZATION_PREFIXES, + organisationPrefixes, locale ), - getLinkArrowLabel: getLinkArrowLabel({ + linkArrowLabel: getLinkArrowLabel({ item, locale, eventTranslation, @@ -110,15 +114,15 @@ export default function useSportsRHHCConfig(args: { }) : rhhcDefaultConfig.utils.getEventCardProps, getRoutedInternalHref: ( - link: string, - _type: ModuleItemTypeEnum + link?: string | null, + type?: ModuleItemTypeEnum ): string => { - if (_type === ModuleItemTypeEnum.Venue) { + if (type === ModuleItemTypeEnum.Venue) { // quick fix for venue url rewrites return routerHelper.getLocalizedCmsItemUrl( ROUTES.VENUES, { - venueId: getVenueSourceId(link), + venueId: getVenueSourceId(link ?? ''), }, locale ); @@ -128,7 +132,7 @@ export default function useSportsRHHCConfig(args: { getIsHrefExternal, }, internalHrefOrigins, - } as unknown as Config; + }; }, [ commonConfig, appTranslation, diff --git a/apps/sports-helsinki/src/pages/articles/[...slug].tsx b/apps/sports-helsinki/src/pages/articles/[...slug].tsx index c0fcf1080..a50c3adb8 100644 --- a/apps/sports-helsinki/src/pages/articles/[...slug].tsx +++ b/apps/sports-helsinki/src/pages/articles/[...slug].tsx @@ -9,6 +9,7 @@ import { getLanguageOrDefault, useAppSportsTranslation, RouteMeta, + getLanguageCodeFilter, } from '@events-helsinki/components'; import type { AppLanguage } from '@events-helsinki/components'; import { logger } from '@events-helsinki/components/loggers/logger'; @@ -23,7 +24,6 @@ import type { Breadcrumb, CollectionType, ArticleType, - LanguageCodeFilterEnum, } from 'react-helsinki-headless-cms'; import { getCollections, @@ -67,7 +67,7 @@ const NextCmsArticle: NextPage<{ useCategoriesQuery({ variables: { first: CATEGORIES_AMOUNT, - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), }, }); diff --git a/apps/sports-helsinki/src/pages/articles/index.tsx b/apps/sports-helsinki/src/pages/articles/index.tsx index caaac31f7..5b99660c1 100644 --- a/apps/sports-helsinki/src/pages/articles/index.tsx +++ b/apps/sports-helsinki/src/pages/articles/index.tsx @@ -10,6 +10,7 @@ import { getLanguageOrDefault, RouteMeta, useAppSportsTranslation, + getLanguageCodeFilter, } from '@events-helsinki/components'; import type { GetStaticPropsContext } from 'next'; import { useRouter } from 'next/router'; @@ -23,11 +24,7 @@ import { useConfig, TemplateEnum, } from 'react-helsinki-headless-cms'; -import type { - ArticleType, - LanguageCodeFilterEnum, - PageType, -} from 'react-helsinki-headless-cms'; +import type { ArticleType, PageType } from 'react-helsinki-headless-cms'; import { useCategoriesQuery, PageByTemplateDocument, @@ -106,7 +103,7 @@ export default function ArticleArchive({ variables: { first: BLOCK_SIZE, search: searchFilters?.text ?? '', - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), categories: searchFilters?.tags ?? [], }, }); @@ -115,7 +112,7 @@ export default function ArticleArchive({ useCategoriesQuery({ variables: { first: CATEGORIES_AMOUNT, - language: currentLanguageCode as unknown as LanguageCodeFilterEnum, + language: getLanguageCodeFilter(currentLanguageCode), }, }); diff --git a/apps/sports-helsinki/src/pages/search/map.tsx b/apps/sports-helsinki/src/pages/search/map.tsx index a7acfcca1..27a974781 100644 --- a/apps/sports-helsinki/src/pages/search/map.tsx +++ b/apps/sports-helsinki/src/pages/search/map.tsx @@ -153,10 +153,7 @@ export default function MapSearch({ page }: { page: PageType }) { export async function getStaticProps(context: GetStaticPropsContext) { return getSportsStaticProps(context, async () => { const language = getLanguageOrDefault(context.locale); - const { data: pageData } = await sportsApolloClient.query< - PageQuery, - PageQueryVariables - >({ + await sportsApolloClient.query({ query: PageDocument, variables: { id: `/${language}${ROUTES.SEARCH}/`, diff --git a/packages/components/config/tests/app-test-providers.tsx b/packages/components/config/tests/app-test-providers.tsx index 912f59ed0..2e93aa650 100644 --- a/packages/components/config/tests/app-test-providers.tsx +++ b/packages/components/config/tests/app-test-providers.tsx @@ -1,4 +1,9 @@ -import type { ApolloCache, ApolloClient, InMemoryCache } from '@apollo/client'; +import type { + ApolloCache, + ApolloClient, + InMemoryCache, + NormalizedCacheObject, +} from '@apollo/client'; import { useApolloClient } from '@apollo/client'; import { MockedProvider } from '@apollo/client/testing'; import type { MockedResponse } from '@apollo/client/testing'; @@ -15,7 +20,11 @@ import { } from 'react-helsinki-headless-cms'; import type { Config as RHHCConfig } from 'react-helsinki-headless-cms'; import { I18nextTestStubProvider } from '@/test-utils/I18nextTestStubProvider'; -import { AppRoutingProvider, DEFAULT_LANGUAGE } from '../../src'; +import { + AppRoutingProvider, + DEFAULT_LANGUAGE, + getLanguageCode, +} from '../../src'; import { appRoutingUrlMocks } from './mockDataUtils'; const cmsApiDomain = 'tapahtumat.cms.test.domain.com'; @@ -63,7 +72,10 @@ function RHHCConfigProviderWithMockedApolloClient({ children, router }: Props) { ); } -function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { +function getRHHCConfig( + router: NextRouter, + apolloClient: ApolloClient +): RHHCConfig { const locale = DEFAULT_LANGUAGE; const getIsHrefExternal = (href: string) => { @@ -79,11 +91,15 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { return '#'; }; + // FIXME: Fix types of apolloClient/RHHCConfig so they are compatible without casting + const normalizedCacheObjectApolloClient = + apolloClient as ApolloClient; + return { ...rhhcDefaultConfig, siteName: 'appName', - currentLanguageCode: locale.toUpperCase(), - apolloClient, + currentLanguageCode: getLanguageCode(locale), + apolloClient: normalizedCacheObjectApolloClient, components: { ...rhhcDefaultConfig.components, // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -103,7 +119,12 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { ), openInNewTabAriaLabel: i18n.t('common:srOnly.opensInANewTab'), closeButtonLabelText: i18n.t('common:button.close'), + loadMoreButtonLabelText: i18n.t('common:button.loadMore'), + showAllText: i18n.t('common:button.showAll'), + next: i18n.t('common:next'), + previous: i18n.t('common:previous'), archiveSearch: { + title: i18n.t('cms:archiveSearch.title'), searchTextPlaceholder: i18n.t( 'cms:archiveSearch.searchTextPlaceholder' ), @@ -113,7 +134,9 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { loadMoreButtonLabelText: i18n.t( 'cms:archiveSearch.loadMoreButtonLabelText' ), + noResultsTitle: i18n.t('cms:archiveSearch.noResultsTitle'), noResultsText: i18n.t('cms:archiveSearch.noResultsText'), + clearAll: i18n.t('cms:archiveSearch.buttonClearFilters'), }, }, utils: { @@ -123,7 +146,7 @@ function getRHHCConfig(router: NextRouter, apolloClient: ApolloClient) { getRoutedInternalHref, }, internalHrefOrigins, - } as unknown as RHHCConfig; + }; } export default TestProviders; diff --git a/packages/components/src/components/domain/event/useEventCards.tsx b/packages/components/src/components/domain/event/useEventCards.tsx index 9e1d29b30..24a3e58f1 100644 --- a/packages/components/src/components/domain/event/useEventCards.tsx +++ b/packages/components/src/components/domain/event/useEventCards.tsx @@ -17,12 +17,13 @@ type useEventCardsProps = { function useEventCards({ events, getCardUrl }: useEventCardsProps) { const locale = useLocale(); const { + organisationPrefixes, components: { EventCardContent }, } = useConfig(); useClickCapture(1000); return ( events?.map((event, i) => { - const cardProps = getEventCardProps(event, locale); + const cardProps = getEventCardProps(event, organisationPrefixes, locale); return ( { + it('should map En/Fi/Sv to same language', () => { + expect(getLanguageCode('en')).toBe(LanguageCodeEnum.En); + expect(getLanguageCode('fi')).toBe(LanguageCodeEnum.Fi); + expect(getLanguageCode('sv')).toBe(LanguageCodeEnum.Sv); + }); +}); diff --git a/packages/components/src/utils/__tests__/getLanguageCodeFilter.test.ts b/packages/components/src/utils/__tests__/getLanguageCodeFilter.test.ts new file mode 100644 index 000000000..d89eb9a87 --- /dev/null +++ b/packages/components/src/utils/__tests__/getLanguageCodeFilter.test.ts @@ -0,0 +1,19 @@ +import { + LanguageCodeEnum, + LanguageCodeFilterEnum, +} from 'react-helsinki-headless-cms'; +import getLanguageCodeFilter from '../getLanguageCodeFilter'; + +describe('getLanguageCodeFilter function', () => { + it('should map En/Fi/Sv to same language', () => { + expect(getLanguageCodeFilter(LanguageCodeEnum.En)).toBe( + LanguageCodeFilterEnum.En + ); + expect(getLanguageCodeFilter(LanguageCodeEnum.Fi)).toBe( + LanguageCodeFilterEnum.Fi + ); + expect(getLanguageCodeFilter(LanguageCodeEnum.Sv)).toBe( + LanguageCodeFilterEnum.Sv + ); + }); +}); diff --git a/packages/components/src/utils/getLanguageCode.ts b/packages/components/src/utils/getLanguageCode.ts new file mode 100644 index 000000000..c44aa3f33 --- /dev/null +++ b/packages/components/src/utils/getLanguageCode.ts @@ -0,0 +1,12 @@ +import { LanguageCodeEnum } from 'react-helsinki-headless-cms'; +import type { AppLanguage } from '../types'; + +const appLanguageToLanguageCode: Record = { + en: LanguageCodeEnum.En, + fi: LanguageCodeEnum.Fi, + sv: LanguageCodeEnum.Sv, +} as const; + +export default function getLanguageCode(language: AppLanguage) { + return appLanguageToLanguageCode[language]; +} diff --git a/packages/components/src/utils/getLanguageCodeFilter.ts b/packages/components/src/utils/getLanguageCodeFilter.ts new file mode 100644 index 000000000..ff7352580 --- /dev/null +++ b/packages/components/src/utils/getLanguageCodeFilter.ts @@ -0,0 +1,15 @@ +import { + LanguageCodeEnum, + LanguageCodeFilterEnum, +} from 'react-helsinki-headless-cms'; + +const languageCodeFilterMap: Record = + { + [LanguageCodeEnum.En]: LanguageCodeFilterEnum.En, + [LanguageCodeEnum.Fi]: LanguageCodeFilterEnum.Fi, + [LanguageCodeEnum.Sv]: LanguageCodeFilterEnum.Sv, + } as const; + +export default function getLanguageCodeFilter(languageCode: LanguageCodeEnum) { + return languageCodeFilterMap[languageCode]; +} diff --git a/packages/components/src/utils/index.ts b/packages/components/src/utils/index.ts index 30afef132..74c551c60 100644 --- a/packages/components/src/utils/index.ts +++ b/packages/components/src/utils/index.ts @@ -24,6 +24,8 @@ export * from './typescript.utils'; export * from './headless-cms'; export { default as stringifyUrlObject } from './stringifyUrlObject'; export { default as getTranslation } from './getTranslation'; +export { default as getLanguageCode } from './getLanguageCode'; +export { default as getLanguageCodeFilter } from './getLanguageCodeFilter'; export { default as getLinkArrowLabel } from './getLinkArrowLabel'; export { default as getLocaleFromPathname } from './getLocaleFromPathname'; export * from './accessibilityProfile/typeguards';